diff --git a/app/assets/javascripts/discourse/app/components/composer-container.hbs b/app/assets/javascripts/discourse/app/components/composer-container.hbs
index fb8720aa58f..56b361b694f 100644
--- a/app/assets/javascripts/discourse/app/components/composer-container.hbs
+++ b/app/assets/javascripts/discourse/app/components/composer-container.hbs
@@ -195,22 +195,24 @@
{{/if}}
{{#if this.composer.canEditTags}}
-
-
-
+
{{/if}}
this.set("isTitleFocused", true);
+ this._blurHandler = () => this.set("isTitleFocused", false);
+
+ titleInput.addEventListener("focus", this._focusHandler);
+ titleInput.addEventListener("blur", this._blurHandler);
+
if (this.focusTarget === "title") {
- putCursorAtEnd(this.element.querySelector("input"));
+ putCursorAtEnd(titleInput);
}
if (this.get("composer.titleLength") > 0) {
@@ -27,19 +36,34 @@ export default Component.extend({
}
},
+ willDestroyElement() {
+ this._super(...arguments);
+ const titleInput = this.element.querySelector("input");
+
+ if (titleInput) {
+ titleInput.removeEventListener("focus", this._focusHandler);
+ titleInput.removeEventListener("blur", this._blurHandler);
+ }
+ },
+
@discourseComputed(
"composer.titleLength",
"composer.missingTitleCharacters",
"composer.minimumTitleLength",
- "lastValidatedAt"
+ "lastValidatedAt",
+ "isTitleFocused"
)
validation(
titleLength,
missingTitleChars,
minimumTitleLength,
- lastValidatedAt
+ lastValidatedAt,
+ isTitleFocused
) {
let reason;
+ if (isTitleFocused) {
+ return;
+ }
if (titleLength < 1) {
reason = I18n.t("composer.error.title_missing");
} else if (missingTitleChars > 0) {
diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js
index 52e76708580..3d967acdd5a 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js
@@ -2,6 +2,7 @@ import {
click,
currentURL,
fillIn,
+ focus,
settled,
triggerEvent,
triggerKeyEvent,
@@ -155,8 +156,9 @@ acceptance("Composer", function (needs) {
await click("#create-topic");
assert.ok(exists(".d-editor-input"), "the composer input is visible");
+ await focus(".title-input input");
assert.ok(
- exists(".title-input .popup-tip.bad.hide"),
+ exists(".title-input .popup-tip.good.hide"),
"title errors are hidden by default"
);
assert.ok(
diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-uncategorized-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-uncategorized-test.js
index 90fccca3489..ea37f14496a 100644
--- a/app/assets/javascripts/discourse/tests/acceptance/composer-uncategorized-test.js
+++ b/app/assets/javascripts/discourse/tests/acceptance/composer-uncategorized-test.js
@@ -1,4 +1,4 @@
-import { click, fillIn, visit } from "@ember/test-helpers";
+import { click, fillIn, focus, visit } from "@ember/test-helpers";
import { test } from "qunit";
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
@@ -13,8 +13,9 @@ acceptance(
await visit("/");
await click("#create-topic");
assert.ok(exists(".d-editor-input"), "the composer input is visible");
+ await focus(".title-input input");
assert.ok(
- exists(".title-input .popup-tip.bad.hide"),
+ exists(".title-input .popup-tip.good.hide"),
"title errors are hidden by default"
);
assert.ok(
diff --git a/app/assets/stylesheets/common/base/compose.scss b/app/assets/stylesheets/common/base/compose.scss
index a4091bf4968..e7c0fbf2fb1 100644
--- a/app/assets/stylesheets/common/base/compose.scss
+++ b/app/assets/stylesheets/common/base/compose.scss
@@ -235,14 +235,16 @@ html.composer-open {
}
.archetype-private_message & {
- // PMs don's have categories, so we need a wider tag input
+ // PMs don't have categories, so we need a wider tag input
.mini-tag-chooser {
width: 100%;
+ max-width: 100%;
}
}
}
.category-input {
+ position: relative;
display: flex;
flex: 1 0 40%;
max-width: 40%;
@@ -324,18 +326,22 @@ html.composer-open {
}
}
- .category-input + .mini-tag-chooser {
+ .category-input + .tags-input {
margin-left: 8px;
width: auto;
max-width: calc(50% - 4px);
}
- .mini-tag-chooser {
- flex-grow: 1;
+ .tags-input {
+ position: relative;
margin: 0 0 8px 0px;
- z-index: z("composer", "dropdown");
- .select-kit-header {
- color: var(--primary-high);
+ flex-grow: 1;
+ .mini-tag-chooser {
+ z-index: z("composer", "dropdown");
+ width: 100%;
+ .select-kit-header {
+ color: var(--primary-high);
+ }
}
}
diff --git a/app/assets/stylesheets/common/input_tip.scss b/app/assets/stylesheets/common/input_tip.scss
index 48e4453c3f7..69cbb2e2503 100644
--- a/app/assets/stylesheets/common/input_tip.scss
+++ b/app/assets/stylesheets/common/input_tip.scss
@@ -13,6 +13,7 @@
.popup-tip {
@include form-item-sizing;
position: absolute;
+ left: 0;
z-index: z("composer", "dropdown") + 1;
cursor: pointer;
@media (prefers-reduced-motion: no-preference) {
diff --git a/app/assets/stylesheets/desktop/compose.scss b/app/assets/stylesheets/desktop/compose.scss
index 928f2772547..e5285aeb419 100644
--- a/app/assets/stylesheets/desktop/compose.scss
+++ b/app/assets/stylesheets/desktop/compose.scss
@@ -24,9 +24,8 @@
.title-and-category {
flex-wrap: nowrap;
gap: 0.5em;
- .mini-tag-chooser {
+ .tags-input {
max-width: 50%;
- margin-bottom: 8px; // match title input margin
flex: 1 1 auto;
}
}
diff --git a/app/assets/stylesheets/mobile/compose.scss b/app/assets/stylesheets/mobile/compose.scss
index fde97dd9771..0d85d2caa22 100644
--- a/app/assets/stylesheets/mobile/compose.scss
+++ b/app/assets/stylesheets/mobile/compose.scss
@@ -205,9 +205,10 @@
z-index: z("base");
}
- .mini-tag-chooser {
+ .tags-input {
margin: 0 0 6px 6px;
max-width: calc(50% - 3px);
+ width: 100%;
}
}