diff --git a/src/components/ha-form/ha-form-multi_select.ts b/src/components/ha-form/ha-form-multi_select.ts
index 37155d4ecc..9640aa53cc 100644
--- a/src/components/ha-form/ha-form-multi_select.ts
+++ b/src/components/ha-form/ha-form-multi_select.ts
@@ -1,17 +1,18 @@
-import { mdiMenuDown, mdiMenuUp } from "@mdi/js";
import type { PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
-import { customElement, property, query, state } from "lit/decorators";
+import { customElement, property, query } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import "../ha-check-list-item";
import "../ha-checkbox";
import type { HaCheckbox } from "../ha-checkbox";
+import "../ha-dropdown";
+import "../ha-dropdown-item";
import "../ha-formfield";
import "../ha-icon-button";
-import "../ha-md-button-menu";
-import "../ha-md-menu-item";
-import "../ha-textfield";
+import "../ha-picker-field";
+import type { HaDropdown } from "../ha-dropdown";
+import type { HaDropdownItem } from "../ha-dropdown-item";
import type {
HaFormElement,
HaFormMultiSelectData,
@@ -36,16 +37,12 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
@property() public label!: string;
- @property({ type: Boolean }) public disabled = false;
+ @property({ type: Boolean, reflect: true }) public disabled = false;
- @state() private _opened = false;
-
- @query("ha-md-button-menu") private _input?: HTMLElement;
+ @query("ha-dropdown") private _dropdown!: HaDropdown;
public focus(): void {
- if (this._input) {
- this._input.focus();
- }
+ this._dropdown?.focus();
}
protected render(): TemplateResult {
@@ -74,13 +71,14 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
}
return html`
-
-
-
+ hide-clear-icon
+ >
+
${options.map((item: string | [string, string]) => {
const value = optionValue(item);
const selected = data.includes(value);
- return html`
-
${optionLabel(item)}
- `;
+ `;
})}
-
+
`;
}
- protected _keydown(ev) {
- if (ev.code === "Space" || ev.code === "Enter") {
- ev.preventDefault();
- this._toggleItem(ev);
- }
- }
+ protected _toggleItem(ev: CustomEvent<{ item: HaDropdownItem }>) {
+ ev.preventDefault(); // keep the dropdown open
+ const value = ev.detail.item.value;
+ const action = (ev.detail.item as any).action;
- protected _toggleItem(ev) {
const oldData = this.data || [];
let newData: string[];
- if (ev.currentTarget.action === "add") {
- newData = [...oldData, ev.currentTarget.value];
+ if (action === "add") {
+ newData = [...oldData, value];
} else {
- newData = oldData.filter((d) => d !== ev.currentTarget.value);
+ newData = oldData.filter((d) => d !== value);
}
fireEvent(this, "value-changed", {
value: newData,
});
}
- protected firstUpdated() {
- this.updateComplete.then(() => {
- const { formElement, mdcRoot } =
- this.shadowRoot?.querySelector("ha-textfield") || ({} as any);
- if (formElement) {
- formElement.style.textOverflow = "ellipsis";
- }
- if (mdcRoot) {
- mdcRoot.style.cursor = "pointer";
- }
- });
- }
-
protected updated(changedProps: PropertyValues): void {
if (changedProps.has("schema")) {
this.toggleAttribute(
@@ -194,25 +163,28 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
});
}
- private _handleOpen(ev: Event): void {
- ev.stopPropagation();
- this._opened = true;
- this.toggleAttribute("opened", true);
+ private _showDropdown(ev) {
+ if (this.disabled) {
+ ev.preventDefault();
+ }
+ this.style.setProperty(
+ "--dropdown-width",
+ `${this._dropdown.offsetWidth}px`
+ );
}
- private _handleClose(ev: Event): void {
- ev.stopPropagation();
- this._opened = false;
- this.toggleAttribute("opened", false);
+ private _handleKeydown(ev) {
+ if ((ev.code === "Space" || ev.code === "Enter") && this._dropdown) {
+ this._dropdown.open = true;
+ }
}
static styles = css`
:host([own-margin]) {
margin-bottom: 5px;
}
- ha-md-button-menu {
+ ha-dropdown {
display: block;
- cursor: pointer;
}
ha-formfield {
display: block;
@@ -239,9 +211,15 @@ export class HaFormMultiSelect extends LitElement implements HaFormElement {
:host([opened]) ha-icon-button {
color: var(--primary-color);
}
- :host([opened]) ha-md-button-menu {
- --mdc-text-field-idle-line-color: var(--input-hover-line-color);
- --mdc-text-field-label-ink-color: var(--primary-color);
+
+ ha-dropdown::part(menu) {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ width: var(--dropdown-width);
+ }
+
+ :host([disabled]) ha-dropdown ha-picker-field {
+ cursor: not-allowed;
}
`;
}
diff --git a/src/components/ha-md-button-menu.ts b/src/components/ha-md-button-menu.ts
deleted file mode 100644
index 4e07f40bee..0000000000
--- a/src/components/ha-md-button-menu.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import type { TemplateResult } from "lit";
-import { css, html, LitElement } from "lit";
-import { customElement, property, query } from "lit/decorators";
-import { fireEvent } from "../common/dom/fire_event";
-import { FOCUS_TARGET } from "../dialogs/make-dialog-manager";
-import type { HaButton } from "./ha-button";
-import type { HaIconButton } from "./ha-icon-button";
-import "./ha-md-menu";
-import type { HaMdMenu } from "./ha-md-menu";
-
-@customElement("ha-md-button-menu")
-export class HaMdButtonMenu extends LitElement {
- protected readonly [FOCUS_TARGET];
-
- @property({ type: Boolean }) public disabled = false;
-
- @property() public positioning?: "fixed" | "absolute" | "popover";
-
- @property({ attribute: "anchor-corner" }) public anchorCorner:
- | "start-start"
- | "start-end"
- | "end-start"
- | "end-end" = "end-start";
-
- @property({ attribute: "menu-corner" }) public menuCorner:
- | "start-start"
- | "start-end"
- | "end-start"
- | "end-end" = "start-start";
-
- @property({ type: Boolean, attribute: "has-overflow" }) public hasOverflow =
- false;
-
- @property({ type: Boolean }) public quick = false;
-
- @query("ha-md-menu", true) private _menu!: HaMdMenu;
-
- public get items() {
- return this._menu.items;
- }
-
- public override focus() {
- if (this._menu.open) {
- this._menu.focus();
- } else {
- this._triggerButton?.focus();
- }
- }
-
- protected render(): TemplateResult {
- return html`
-
-
-
-
-
-
- `;
- }
-
- private _handleOpening(): void {
- fireEvent(this, "opening", undefined, { composed: false });
- }
-
- private _handleClosing(): void {
- fireEvent(this, "closing", undefined, { composed: false });
- }
-
- private _handleClick(): void {
- if (this.disabled) {
- return;
- }
- this._menu.anchorElement = this;
- if (this._menu.open) {
- this._menu.close();
- } else {
- this._menu.show();
- }
- }
-
- private get _triggerButton() {
- return this.querySelector(
- 'ha-icon-button[slot="trigger"], ha-button[slot="trigger"], ha-assist-chip[slot="trigger"]'
- ) as HaIconButton | HaButton | null;
- }
-
- private _setTriggerAria() {
- if (this._triggerButton) {
- this._triggerButton.ariaHasPopup = "menu";
- }
- }
-
- static styles = css`
- :host {
- display: inline-block;
- position: relative;
- }
- ::slotted([disabled]) {
- color: var(--disabled-text-color);
- }
- `;
-}
-
-declare global {
- interface HTMLElementTagNameMap {
- "ha-md-button-menu": HaMdButtonMenu;
- }
-}
-
-declare global {
- interface HASSDomEvents {
- opening: undefined;
- closing: undefined;
- }
-}
diff --git a/src/dialogs/voice-assistant-setup/voice-assistant-setup-dialog.ts b/src/dialogs/voice-assistant-setup/voice-assistant-setup-dialog.ts
index 1cc04ab578..23bbadad6d 100644
--- a/src/dialogs/voice-assistant-setup/voice-assistant-setup-dialog.ts
+++ b/src/dialogs/voice-assistant-setup/voice-assistant-setup-dialog.ts
@@ -8,8 +8,10 @@ import { computeDomain } from "../../common/entity/compute_domain";
import { formatLanguageCode } from "../../common/language/format_language";
import "../../components/chips/ha-assist-chip";
import "../../components/ha-dialog";
+import "../../components/ha-dropdown";
+import "../../components/ha-dropdown-item";
+import type { HaDropdownItem } from "../../components/ha-dropdown-item";
import { getLanguageOptions } from "../../components/ha-language-picker";
-import "../../components/ha-md-button-menu";
import type { AssistSatelliteConfiguration } from "../../data/assist_satellite";
import { fetchAssistSatelliteConfiguration } from "../../data/assist_satellite";
import { getLanguageScores } from "../../data/conversation";
@@ -169,9 +171,9 @@ export class HaVoiceAssistantSetupDialog extends LitElement {
>`
: this._step === STEP.PIPELINE
? this._language
- ? html`
- html`
${lang.primary}
- `
+ `
)}
- `
+ `
: nothing
: nothing}
@@ -328,10 +328,8 @@ export class HaVoiceAssistantSetupDialog extends LitElement {
}
}
- private _handlePickLanguage(ev) {
- if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") return;
-
- this._language = ev.target.value;
+ private _handlePickLanguage(ev: CustomEvent<{ item: HaDropdownItem }>) {
+ this._language = ev.detail.item.value;
}
private _languageChanged(ev: CustomEvent) {
@@ -401,7 +399,7 @@ export class HaVoiceAssistantSetupDialog extends LitElement {
margin: 24px;
display: block;
}
- ha-md-button-menu {
+ ha-dropdown {
height: 48px;
display: flex;
align-items: center;
@@ -409,6 +407,13 @@ export class HaVoiceAssistantSetupDialog extends LitElement {
margin-inline-end: 12px;
margin-inline-start: initial;
}
+ ha-dropdown-item.selected {
+ border: 1px solid var(--primary-color);
+ font-weight: var(--ha-font-weight-medium);
+ color: var(--primary-color);
+ background-color: var(--ha-color-fill-primary-quiet-resting);
+ --icon-primary-color: var(--primary-color);
+ }
`,
];
}
diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts
index 8aa7cacad3..3b5e5a8bf1 100644
--- a/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts
+++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts
@@ -4,6 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { firstWeekdayIndex } from "../../../../../common/datetime/first_weekday";
import { fireEvent } from "../../../../../common/dom/fire_event";
+import { computeDomain } from "../../../../../common/entity/compute_domain";
import type { LocalizeFunc } from "../../../../../common/translations/localize";
import "../../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../../components/ha-form/types";
@@ -11,7 +12,6 @@ import type { TimeTrigger } from "../../../../../data/automation";
import type { FrontendLocaleData } from "../../../../../data/translation";
import type { HomeAssistant } from "../../../../../types";
import type { TriggerElement } from "../ha-automation-trigger-row";
-import { computeDomain } from "../../../../../common/entity/compute_domain";
const MODE_TIME = "time";
const MODE_ENTITY = "entity";
diff --git a/src/panels/profile/ha-refresh-tokens-card.ts b/src/panels/profile/ha-refresh-tokens-card.ts
index f960a43cc7..1e575f2708 100644
--- a/src/panels/profile/ha-refresh-tokens-card.ts
+++ b/src/panels/profile/ha-refresh-tokens-card.ts
@@ -20,7 +20,6 @@ import "../../components/ha-dropdown-item";
import "../../components/ha-icon-button";
import "../../components/ha-label";
import "../../components/ha-list-item";
-import "../../components/ha-md-button-menu";
import "../../components/ha-md-menu-item";
import "../../components/ha-settings-row";
import { deleteAllRefreshTokens } from "../../data/auth";