UX: Hide the error tooltip when focusing the topic title (#27531)

This commit is contained in:
Jan Cernik 2024-06-19 11:55:29 -03:00 committed by GitHub
parent e29dfe1380
commit 604ca4d46e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 68 additions and 32 deletions

View File

@ -195,22 +195,24 @@
{{/if}} {{/if}}
{{#if this.composer.canEditTags}} {{#if this.composer.canEditTags}}
<MiniTagChooser <div class="tags-input">
@value={{this.composer.model.tags}} <MiniTagChooser
@onChange={{fn (mut this.composer.model.tags)}} @value={{this.composer.model.tags}}
@options={{hash @onChange={{fn (mut this.composer.model.tags)}}
disabled=this.composer.disableTagsChooser @options={{hash
categoryId=this.composer.model.categoryId disabled=this.composer.disableTagsChooser
minimum=this.composer.model.minimumRequiredTags categoryId=this.composer.model.categoryId
}} minimum=this.composer.model.minimumRequiredTags
/> }}
<PluginOutlet />
@name="after-composer-tag-input" <PluginOutlet
@outletArgs={{hash composer=this.composer.model}} @name="after-composer-tag-input"
/> @outletArgs={{hash composer=this.composer.model}}
<PopupInputTip />
@validation={{this.composer.tagValidation}} <PopupInputTip
/> @validation={{this.composer.tagValidation}}
/>
</div>
{{/if}} {{/if}}
<PluginOutlet <PluginOutlet

View File

@ -15,11 +15,20 @@ export default Component.extend({
classNames: ["title-input"], classNames: ["title-input"],
watchForLink: alias("composer.canEditTopicFeaturedLink"), watchForLink: alias("composer.canEditTopicFeaturedLink"),
disabled: or("composer.loading", "composer.disableTitleInput"), disabled: or("composer.loading", "composer.disableTitleInput"),
isTitleFocused: false,
didInsertElement() { didInsertElement() {
this._super(...arguments); this._super(...arguments);
const titleInput = this.element.querySelector("input");
this._focusHandler = () => this.set("isTitleFocused", true);
this._blurHandler = () => this.set("isTitleFocused", false);
titleInput.addEventListener("focus", this._focusHandler);
titleInput.addEventListener("blur", this._blurHandler);
if (this.focusTarget === "title") { if (this.focusTarget === "title") {
putCursorAtEnd(this.element.querySelector("input")); putCursorAtEnd(titleInput);
} }
if (this.get("composer.titleLength") > 0) { 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( @discourseComputed(
"composer.titleLength", "composer.titleLength",
"composer.missingTitleCharacters", "composer.missingTitleCharacters",
"composer.minimumTitleLength", "composer.minimumTitleLength",
"lastValidatedAt" "lastValidatedAt",
"isTitleFocused"
) )
validation( validation(
titleLength, titleLength,
missingTitleChars, missingTitleChars,
minimumTitleLength, minimumTitleLength,
lastValidatedAt lastValidatedAt,
isTitleFocused
) { ) {
let reason; let reason;
if (isTitleFocused) {
return;
}
if (titleLength < 1) { if (titleLength < 1) {
reason = I18n.t("composer.error.title_missing"); reason = I18n.t("composer.error.title_missing");
} else if (missingTitleChars > 0) { } else if (missingTitleChars > 0) {

View File

@ -2,6 +2,7 @@ import {
click, click,
currentURL, currentURL,
fillIn, fillIn,
focus,
settled, settled,
triggerEvent, triggerEvent,
triggerKeyEvent, triggerKeyEvent,
@ -155,8 +156,9 @@ acceptance("Composer", function (needs) {
await click("#create-topic"); await click("#create-topic");
assert.ok(exists(".d-editor-input"), "the composer input is visible"); assert.ok(exists(".d-editor-input"), "the composer input is visible");
await focus(".title-input input");
assert.ok( assert.ok(
exists(".title-input .popup-tip.bad.hide"), exists(".title-input .popup-tip.good.hide"),
"title errors are hidden by default" "title errors are hidden by default"
); );
assert.ok( assert.ok(

View File

@ -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 { test } from "qunit";
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers"; import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper"; import selectKit from "discourse/tests/helpers/select-kit-helper";
@ -13,8 +13,9 @@ acceptance(
await visit("/"); await visit("/");
await click("#create-topic"); await click("#create-topic");
assert.ok(exists(".d-editor-input"), "the composer input is visible"); assert.ok(exists(".d-editor-input"), "the composer input is visible");
await focus(".title-input input");
assert.ok( assert.ok(
exists(".title-input .popup-tip.bad.hide"), exists(".title-input .popup-tip.good.hide"),
"title errors are hidden by default" "title errors are hidden by default"
); );
assert.ok( assert.ok(

View File

@ -235,14 +235,16 @@ html.composer-open {
} }
.archetype-private_message & { .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 { .mini-tag-chooser {
width: 100%; width: 100%;
max-width: 100%;
} }
} }
} }
.category-input { .category-input {
position: relative;
display: flex; display: flex;
flex: 1 0 40%; flex: 1 0 40%;
max-width: 40%; max-width: 40%;
@ -324,18 +326,22 @@ html.composer-open {
} }
} }
.category-input + .mini-tag-chooser { .category-input + .tags-input {
margin-left: 8px; margin-left: 8px;
width: auto; width: auto;
max-width: calc(50% - 4px); max-width: calc(50% - 4px);
} }
.mini-tag-chooser { .tags-input {
flex-grow: 1; position: relative;
margin: 0 0 8px 0px; margin: 0 0 8px 0px;
z-index: z("composer", "dropdown"); flex-grow: 1;
.select-kit-header { .mini-tag-chooser {
color: var(--primary-high); z-index: z("composer", "dropdown");
width: 100%;
.select-kit-header {
color: var(--primary-high);
}
} }
} }

View File

@ -13,6 +13,7 @@
.popup-tip { .popup-tip {
@include form-item-sizing; @include form-item-sizing;
position: absolute; position: absolute;
left: 0;
z-index: z("composer", "dropdown") + 1; z-index: z("composer", "dropdown") + 1;
cursor: pointer; cursor: pointer;
@media (prefers-reduced-motion: no-preference) { @media (prefers-reduced-motion: no-preference) {

View File

@ -24,9 +24,8 @@
.title-and-category { .title-and-category {
flex-wrap: nowrap; flex-wrap: nowrap;
gap: 0.5em; gap: 0.5em;
.mini-tag-chooser { .tags-input {
max-width: 50%; max-width: 50%;
margin-bottom: 8px; // match title input margin
flex: 1 1 auto; flex: 1 1 auto;
} }
} }

View File

@ -205,9 +205,10 @@
z-index: z("base"); z-index: z("base");
} }
.mini-tag-chooser { .tags-input {
margin: 0 0 6px 6px; margin: 0 0 6px 6px;
max-width: calc(50% - 3px); max-width: calc(50% - 3px);
width: 100%;
} }
} }