diff --git a/frontend/src/components/tag-input.ts b/frontend/src/components/tag-input.ts index a8c7ab65..36237223 100644 --- a/frontend/src/components/tag-input.ts +++ b/frontend/src/components/tag-input.ts @@ -1,9 +1,14 @@ import { LitElement, html, css } from "lit"; import { state, property, query } from "lit/decorators.js"; import { msg, localized, str } from "@lit/localize"; -import type { SlInput, SlMenu, SlPopup } from "@shoelace-style/shoelace"; +import type { + SlInput, + SlMenu, + SlMenuItem, + SlPopup, + SlTag, +} from "@shoelace-style/shoelace"; import inputCss from "@shoelace-style/shoelace/dist/components/input/input.styles.js"; -import union from "lodash/fp/union"; import debounce from "lodash/fp/debounce"; export type Tags = string[]; @@ -105,6 +110,36 @@ export class TagInput extends LitElement { display: none; } } + + .shake { + animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; + transform: translate3d(0, 0, 0); + backface-visibility: hidden; + perspective: 1000px; + } + + @keyframes shake { + 10%, + 90% { + transform: translate3d(-1px, 0, 0); + } + + 20%, + 80% { + transform: translate3d(2px, 0, 0); + } + + 30%, + 50%, + 70% { + transform: translate3d(-3px, 0, 0); + } + + 40%, + 60% { + transform: translate3d(3px, 0, 0); + } + } `; @property({ type: Array }) @@ -129,14 +164,20 @@ export class TagInput extends LitElement { @state() private dropdownIsOpen?: boolean; + @query(".form-control") + private formControl!: HTMLElement; + @query("#input") - private input?: HTMLInputElement; + private input!: HTMLInputElement; + + @query("#dropdown") + private dropdown!: HTMLDivElement; @query("sl-menu") private menu!: SlMenu; @query("sl-popup") - private popup!: SlPopup; + private combobox!: SlPopup; connectedCallback() { if (this.initialTags) { @@ -153,13 +194,17 @@ export class TagInput extends LitElement { this.setAttribute("data-invalid", ""); } } - if (changedProperties.has("dropdownIsOpen") && this.dropdownIsOpen) { - this.popup.reposition(); + if (changedProperties.has("dropdownIsOpen")) { + if (this.dropdownIsOpen) { + this.openDropdown(); + } else { + this.closeDropdown(); + } } } reportValidity() { - this.input?.reportValidity(); + this.input.reportValidity(); } render() { @@ -175,7 +220,18 @@ export class TagInput extends LitElement {
{ + const currentTarget = e.currentTarget as SlMenuItem; + const relatedTarget = e.relatedTarget as HTMLElement; + if ( + this.dropdownIsOpen && + !currentTarget?.contains(relatedTarget) + ) { + this.dropdownIsOpen = false; + } + }} > ${this.renderTags()}