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%; } }