From 92a36ac6873269a82b37298dd99c37f427dd9e1e Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Fri, 16 Jan 2026 19:27:14 +0100 Subject: [PATCH] Migrate ha-button-menu to ha-dropdown in logs and forms (#29036) Migrate four components from ha-button-menu to ha-dropdown: - error-log-card: overflow menu with log view switching - system-log-card: overflow menu for full logs - ha-filter-categories: category edit/delete actions - ha-form-optional_actions: add interaction dropdown Changes: - Replace ha-button-menu with ha-dropdown - Replace ha-list-item with ha-dropdown-item - Update event handlers from @action to @wa-select - Use value-based selection instead of index-based - Add proper accessibility labels to trigger buttons Part of #26537 Co-authored-by: Claude Sonnet 4.5 --- src/components/ha-filter-categories.ts | 54 ++++++++++--------- .../ha-form/ha-form-optional_actions.ts | 26 +++++---- src/panels/config/logs/error-log-card.ts | 42 +++++++-------- src/panels/config/logs/system-log-card.ts | 31 ++++++----- 4 files changed, 78 insertions(+), 75 deletions(-) diff --git a/src/components/ha-filter-categories.ts b/src/components/ha-filter-categories.ts index 2fa5380881..ddf33287ea 100644 --- a/src/components/ha-filter-categories.ts +++ b/src/components/ha-filter-categories.ts @@ -1,4 +1,4 @@ -import type { ActionDetail, SelectedDetail } from "@material/mwc-list"; +import type { SelectedDetail } from "@material/mwc-list"; import { mdiDelete, mdiDotsVertical, @@ -25,7 +25,8 @@ import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { showCategoryRegistryDetailDialog } from "../panels/config/category/show-dialog-category-registry-detail"; import { haStyleScrollbar } from "../resources/styles"; import type { HomeAssistant } from "../types"; -import "./ha-button-menu"; +import "./ha-dropdown"; +import "./ha-dropdown-item"; import "./ha-expansion-panel"; import "./ha-icon"; import "./ha-list"; @@ -114,37 +115,36 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) { slot="graphic" >`} ${category.name} - - + ${this.hass.localize( + > + ${this.hass.localize( "ui.panel.config.category.editor.edit" - )} - + + ${this.hass.localize( + > + ${this.hass.localize( "ui.panel.config.category.editor.delete" - )} - + )} + + ` )} @@ -174,13 +174,14 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) { } } - private _handleAction(ev: CustomEvent) { + private _handleAction(ev: CustomEvent<{ item: { value: string } }>) { const categoryId = (ev.currentTarget as any).categoryId; - switch (ev.detail.index) { - case 0: + const action = ev.detail.item.value; + switch (action) { + case "edit": this._editCategory(categoryId); break; - case 1: + case "delete": this._deleteCategory(categoryId); break; } @@ -316,6 +317,9 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) { --mdc-list-side-padding-right: 4px; --mdc-icon-button-size: 36px; } + ha-dropdown-item { + font-size: var(--ha-font-size-m); + } .warning { color: var(--error-color); } diff --git a/src/components/ha-form/ha-form-optional_actions.ts b/src/components/ha-form/ha-form-optional_actions.ts index 30d58e0fd7..c883ac8b7b 100644 --- a/src/components/ha-form/ha-form-optional_actions.ts +++ b/src/components/ha-form/ha-form-optional_actions.ts @@ -7,7 +7,8 @@ import { stopPropagation } from "../../common/dom/stop_propagation"; import type { LocalizeFunc } from "../../common/translations/localize"; import type { HomeAssistant } from "../../types"; import "../ha-button"; -import "../ha-list-item"; +import "../ha-dropdown"; +import "../ha-dropdown-item"; import "../ha-svg-icon"; import "./ha-form"; import type { @@ -116,9 +117,8 @@ export class HaFormOptionalActions extends LitElement implements HaFormElement { : nothing} ${hiddenActions.length > 0 ? html` - @@ -129,26 +129,21 @@ export class HaFormOptionalActions extends LitElement implements HaFormElement { ${hiddenActions.map((action) => { const actionSchema = schemaMap.get(action); return html` - + ${this.computeLabel && actionSchema ? this.computeLabel(actionSchema) : action} - + `; })} - + ` : nothing} `; } - private _handleAddAction(ev: CustomEvent) { - const hiddenActions = this._hiddenActions( - this.schema.schema, - this._displayActions ?? NO_ACTIONS - ); - const index = ev.detail.index; - const action = hiddenActions[index]; + private _handleAddAction(ev: CustomEvent<{ item: { value: string } }>) { + const action = ev.detail.item.value; this._displayActions = [...(this._displayActions ?? []), action]; } @@ -161,6 +156,9 @@ export class HaFormOptionalActions extends LitElement implements HaFormElement { :host ha-form { display: block; } + ha-dropdown { + display: inline-block; + } `; } diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index 1c0e742240..02b9ece8d7 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -1,5 +1,3 @@ -import type { ActionDetail } from "@material/mwc-list"; - import { mdiArrowCollapseDown, mdiCircle, @@ -31,10 +29,10 @@ import "../../../components/ha-alert"; import "../../../components/ha-ansi-to-html"; import type { HaAnsiToHtml } from "../../../components/ha-ansi-to-html"; import "../../../components/ha-button"; -import "../../../components/ha-button-menu"; import "../../../components/ha-card"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; import "../../../components/ha-icon-button"; -import "../../../components/ha-list-item"; import "../../../components/ha-md-divider"; import "../../../components/ha-md-menu"; import "../../../components/ha-md-menu-item"; @@ -249,32 +247,35 @@ class ErrorLogCard extends LitElement { : nothing} ${(this.allowSwitch && this.provider === "core") || hasBoots ? html` - - - + + ${this.allowSwitch && this.provider === "core" - ? html` + ? html` ${this.hass.localize( "ui.panel.config.logs.show_condensed_logs" )} - ` + ` : nothing} ${hasBoots - ? html` + ? html` ${localize( `ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots` )} - ` + ` : nothing} - + ` : nothing} @@ -719,17 +720,14 @@ class ErrorLogCard extends LitElement { this._loadLogs(); } - private _handleOverflowAction(ev: CustomEvent) { - let index = ev.detail.index; - if (this.provider === "core") { - index--; - } - switch (index) { - case -1: + private _handleOverflowAction(ev: CustomEvent<{ item: { value: string } }>) { + const action = ev.detail.item.value; + switch (action) { + case "switch-log-view": // @ts-ignore fireEvent(this, "switch-log-view"); break; - case 0: + case "toggle-boots": this._showBootsSelect = !this._showBootsSelect; break; } diff --git a/src/panels/config/logs/system-log-card.ts b/src/panels/config/logs/system-log-card.ts index 6c858c7f99..dcaeb17fa2 100644 --- a/src/panels/config/logs/system-log-card.ts +++ b/src/panels/config/logs/system-log-card.ts @@ -5,8 +5,9 @@ import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import type { LocalizeFunc } from "../../../common/translations/localize"; import "../../../components/buttons/ha-call-service-button"; -import "../../../components/ha-button-menu"; import "../../../components/ha-card"; +import "../../../components/ha-dropdown"; +import "../../../components/ha-dropdown-item"; import "../../../components/ha-icon-button"; import "../../../components/ha-list"; import "../../../components/ha-list-item"; @@ -121,19 +122,19 @@ export class SystemLogCard extends LitElement { .label=${this.hass.localize("ui.common.refresh")} > - - - - - + + + + ${this.hass.localize( "ui.panel.config.logs.show_full_logs" )} - - + + ${this._items.length === 0 @@ -221,9 +222,11 @@ export class SystemLogCard extends LitElement { } } - private _handleOverflowAction() { - // @ts-ignore - fireEvent(this, "switch-log-view"); + private _handleOverflowAction(ev: CustomEvent<{ item: { value: string } }>) { + if (ev.detail.item.value === "show-full-logs") { + // @ts-ignore + fireEvent(this, "switch-log-view"); + } } private async _downloadLogs() {