1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-02-15 07:25:54 +00:00

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 <noreply@anthropic.com>
This commit is contained in:
Wendelin
2026-01-16 19:27:14 +01:00
committed by GitHub
parent 8221ca8971
commit 92a36ac687
4 changed files with 78 additions and 75 deletions

View File

@@ -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"
></ha-svg-icon>`}
${category.name}
<ha-button-menu
<ha-dropdown
@click=${stopPropagation}
@action=${this._handleAction}
@wa-select=${this._handleAction}
slot="meta"
fixed
.categoryId=${category.category_id}
>
<ha-icon-button
.path=${mdiDotsVertical}
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
></ha-icon-button>
<ha-list-item graphic="icon"
><ha-svg-icon
<ha-dropdown-item value="edit">
<ha-svg-icon
slot="icon"
.path=${mdiPencil}
slot="graphic"
></ha-svg-icon
>${this.hass.localize(
></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.category.editor.edit"
)}</ha-list-item
>
<ha-list-item graphic="icon" class="warning"
><ha-svg-icon
class="warning"
)}
</ha-dropdown-item>
<ha-dropdown-item value="delete" variant="danger">
<ha-svg-icon
slot="icon"
.path=${mdiDelete}
slot="graphic"
></ha-svg-icon
>${this.hass.localize(
></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.category.editor.delete"
)}</ha-list-item
>
</ha-button-menu>
)}
</ha-dropdown-item>
</ha-dropdown>
</ha-list-item>`
)}
</ha-list>
@@ -174,13 +174,14 @@ export class HaFilterCategories extends SubscribeMixin(LitElement) {
}
}
private _handleAction(ev: CustomEvent<ActionDetail>) {
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);
}

View File

@@ -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`
<ha-button-menu
@action=${this._handleAddAction}
fixed
<ha-dropdown
@wa-select=${this._handleAddAction}
@closed=${stopPropagation}
>
<ha-button slot="trigger" appearance="filled" size="small">
@@ -129,26 +129,21 @@ export class HaFormOptionalActions extends LitElement implements HaFormElement {
${hiddenActions.map((action) => {
const actionSchema = schemaMap.get(action);
return html`
<ha-list-item>
<ha-dropdown-item .value=${action}>
${this.computeLabel && actionSchema
? this.computeLabel(actionSchema)
: action}
</ha-list-item>
</ha-dropdown-item>
`;
})}
</ha-button-menu>
</ha-dropdown>
`
: 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;
}
`;
}

View File

@@ -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`
<ha-button-menu @action=${this._handleOverflowAction}>
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
</ha-icon-button>
<ha-dropdown @wa-select=${this._handleOverflowAction}>
<ha-icon-button
slot="trigger"
.path=${mdiDotsVertical}
.label=${localize("ui.common.menu")}
></ha-icon-button>
${this.allowSwitch && this.provider === "core"
? html`<ha-list-item graphic="icon">
? html`<ha-dropdown-item value="switch-log-view">
<ha-svg-icon
slot="graphic"
slot="icon"
.path=${mdiFolderTextOutline}
></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.logs.show_condensed_logs"
)}
</ha-list-item>`
</ha-dropdown-item>`
: nothing}
${hasBoots
? html`<ha-list-item graphic="icon">
? html`<ha-dropdown-item value="toggle-boots">
<ha-svg-icon
slot="graphic"
slot="icon"
.path=${mdiFormatListNumbered}
></ha-svg-icon>
${localize(
`ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots`
)}
</ha-list-item>`
</ha-dropdown-item>`
: nothing}
</ha-button-menu>
</ha-dropdown>
`
: nothing}
</div>
@@ -719,17 +720,14 @@ class ErrorLogCard extends LitElement {
this._loadLogs();
}
private _handleOverflowAction(ev: CustomEvent<ActionDetail>) {
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;
}

View File

@@ -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")}
></ha-icon-button>
<ha-button-menu @action=${this._handleOverflowAction}>
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
</ha-icon-button>
<ha-list-item graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiText}
></ha-svg-icon>
<ha-dropdown @wa-select=${this._handleOverflowAction}>
<ha-icon-button
slot="trigger"
.path=${mdiDotsVertical}
.label=${this.hass.localize("ui.common.menu")}
></ha-icon-button>
<ha-dropdown-item value="show-full-logs">
<ha-svg-icon slot="icon" .path=${mdiText}></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.logs.show_full_logs"
)}
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
</div>
</div>
${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() {