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 8 files (#29070)

Migrates the following files from ha-button-menu to ha-dropdown component:
- ha-config-backup-details.ts
- ha-config-areas-dashboard.ts
- ha-config-dashboard.ts
- ha-panel-history.ts
- ha-scene-editor.ts
- ha-config-integrations-dashboard.ts
- thread-config-panel.ts
- ha-panel-developer-tools.ts

Changes:
- Replace ha-button-menu with ha-dropdown
- Replace ha-list-item with ha-dropdown-item
- Change @action event handlers to @wa-select
- Change slot="graphic" to slot="icon" for icons
- Update event handlers from index-based to value-based selection
- Replace <li divider role="separator"> with <wa-divider>
- Update CSS selectors from ha-button-menu to ha-dropdown
- Use type="checkbox" for checkbox dropdown items in integrations dashboard
- Remove unused li[role="separator"] CSS styles

Contributes to #26537

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Wendelin
2026-01-19 12:11:29 +01:00
committed by GitHub
parent 829cd96e9b
commit 081b0a0222
8 changed files with 201 additions and 184 deletions

View File

@@ -1,4 +1,4 @@
import type { ActionDetail } from "@material/mwc-list";
import "@home-assistant/webawesome/dist/components/divider/divider";
import {
mdiDelete,
mdiDotsVertical,
@@ -24,10 +24,11 @@ import {
type AreasFloorHierarchy,
} from "../../../common/areas/areas-floor-hierarchy";
import { formatListWithAnds } from "../../../common/string/format-list";
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
import "../../../components/ha-fab";
import "../../../components/ha-floor-icon";
import "../../../components/ha-icon-button";
import "../../../components/ha-list-item";
import "../../../components/ha-sortable";
import type { HaSortableOptions } from "../../../components/ha-sortable";
import "../../../components/ha-svg-icon";
@@ -195,44 +196,45 @@ export class HaConfigAreasDashboard extends LitElement {
${floor.name}
</h2>
<div class="actions">
<ha-button-menu
<ha-dropdown
.floor=${floor}
@action=${this._handleFloorAction}
@wa-select=${this._handleFloorAction}
>
<ha-icon-button
slot="trigger"
.path=${mdiDotsVertical}
.label=${this.hass.localize("ui.common.menu")}
></ha-icon-button>
<ha-list-item graphic="icon"
<ha-dropdown-item value="reorder"
><ha-svg-icon
.path=${mdiSort}
slot="graphic"
slot="icon"
></ha-svg-icon
>${this.hass.localize(
"ui.panel.config.areas.picker.reorder"
)}</ha-list-item
)}</ha-dropdown-item
>
<li divider role="separator"></li>
<ha-list-item graphic="icon"
<wa-divider></wa-divider>
<ha-dropdown-item value="edit"
><ha-svg-icon
.path=${mdiPencil}
slot="graphic"
slot="icon"
></ha-svg-icon
>${this.hass.localize(
"ui.panel.config.areas.picker.floor.edit_floor"
)}</ha-list-item
)}</ha-dropdown-item
>
<ha-list-item class="warning" graphic="icon"
<ha-dropdown-item value="delete" class="warning"
><ha-svg-icon
class="warning"
.path=${mdiDelete}
slot="graphic"
slot="icon"
></ha-svg-icon
>${this.hass.localize(
"ui.panel.config.areas.picker.floor.delete_floor"
)}</ha-list-item
)}</ha-dropdown-item
>
</ha-button-menu>
</ha-dropdown>
</div>
</div>
<ha-sortable
@@ -272,23 +274,24 @@ export class HaConfigAreasDashboard extends LitElement {
)}
</h2>
<div class="actions">
<ha-button-menu
@action=${this._handleUnassignedAreasAction}
<ha-dropdown
@wa-select=${this._handleUnassignedAreasAction}
>
<ha-icon-button
slot="trigger"
.path=${mdiDotsVertical}
.label=${this.hass.localize("ui.common.menu")}
></ha-icon-button>
<ha-list-item graphic="icon"
<ha-dropdown-item value="reorder"
><ha-svg-icon
.path=${mdiSort}
slot="graphic"
slot="icon"
></ha-svg-icon
>${this.hass.localize(
"ui.panel.config.areas.picker.reorder"
)}</ha-list-item
)}</ha-dropdown-item
>
</ha-button-menu>
</ha-dropdown>
</div>
</div>
<ha-sortable
@@ -532,23 +535,27 @@ export class HaConfigAreasDashboard extends LitElement {
}, time);
}
private _handleFloorAction(ev: CustomEvent<ActionDetail>) {
private _handleFloorAction(ev: CustomEvent<{ item: { value: string } }>) {
const floor = (ev.currentTarget as any).floor;
switch (ev.detail.index) {
case 0:
const action = ev.detail.item.value;
switch (action) {
case "reorder":
this._showReorderDialog();
break;
case 1:
case "edit":
this._editFloor(floor);
break;
case 2:
case "delete":
this._deleteFloor(floor);
break;
}
}
private _handleUnassignedAreasAction(ev: CustomEvent<ActionDetail>) {
if (ev.detail.index === 0) {
private _handleUnassignedAreasAction(
ev: CustomEvent<{ item: { value: string } }>
) {
const action = ev.detail.item.value;
if (action === "reorder") {
this._showReorderDialog();
}
}

View File

@@ -1,4 +1,3 @@
import type { ActionDetail } from "@material/mwc-list";
import {
mdiDelete,
mdiDotsVertical,
@@ -14,11 +13,11 @@ import { computeDomain } from "../../../common/entity/compute_domain";
import { navigate } from "../../../common/navigate";
import "../../../components/ha-alert";
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-fade-in";
import "../../../components/ha-icon-button";
import "../../../components/ha-list-item";
import "../../../components/ha-md-list";
import "../../../components/ha-md-list-item";
import "../../../components/ha-spinner";
@@ -114,21 +113,21 @@ class HaConfigBackupDetails extends LitElement {
.header=${this._backup?.name ||
this.hass.localize("ui.panel.config.backup.details.header")}
>
<ha-button-menu slot="toolbar-icon" @action=${this._handleAction}>
<ha-dropdown slot="toolbar-icon" @wa-select=${this._handleAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item graphic="icon">
<ha-svg-icon slot="graphic" .path=${mdiDownload}></ha-svg-icon>
<ha-dropdown-item value="download">
<ha-svg-icon slot="icon" .path=${mdiDownload}></ha-svg-icon>
${this.hass.localize("ui.common.download")}
</ha-list-item>
<ha-list-item graphic="icon" class="warning">
<ha-svg-icon slot="graphic" .path=${mdiDelete}></ha-svg-icon>
</ha-dropdown-item>
<ha-dropdown-item value="delete" class="warning">
<ha-svg-icon slot="icon" .path=${mdiDelete}></ha-svg-icon>
${this.hass.localize("ui.common.delete")}
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
<div class="content">
${this._error &&
html`<ha-alert alert-type="error">${this._error}</ha-alert>`}
@@ -252,9 +251,9 @@ class HaConfigBackupDetails extends LitElement {
${
success
? html`
<ha-button-menu
<ha-dropdown
slot="end"
@action=${this._handleAgentAction}
@wa-select=${this._handleAgentAction}
.agent=${agentId}
fixed
>
@@ -265,16 +264,16 @@ class HaConfigBackupDetails extends LitElement {
)}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item graphic="icon">
<ha-dropdown-item value="download">
<ha-svg-icon
slot="graphic"
slot="icon"
.path=${mdiDownload}
></ha-svg-icon>
${this.hass.localize(
"ui.panel.config.backup.details.locations.download"
)}
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
`
: nothing
}
@@ -312,18 +311,19 @@ class HaConfigBackupDetails extends LitElement {
}
}
private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
private _handleAction(ev: CustomEvent<{ item: { value: string } }>) {
const action = ev.detail.item.value;
switch (action) {
case "download":
this._downloadBackup();
break;
case 1:
case "delete":
this._deleteBackup();
break;
}
}
private _handleAgentAction(ev: CustomEvent<ActionDetail>) {
private _handleAgentAction(ev: CustomEvent<{ item: { value: string } }>) {
const button = ev.currentTarget;
const agentId = (button as any).agent;
this._downloadBackup(agentId);

View File

@@ -1,4 +1,3 @@
import type { ActionDetail } from "@material/mwc-list";
import {
mdiCloudLock,
mdiDotsVertical,
@@ -13,11 +12,11 @@ import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import "../../../components/chips/ha-assist-chip";
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-icon-next";
import "../../../components/ha-list-item";
import "../../../components/ha-menu-button";
import "../../../components/ha-svg-icon";
import "../../../components/ha-tip";
@@ -226,25 +225,25 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) {
.path=${mdiMagnify}
@click=${this._showQuickBar}
></ha-icon-button>
<ha-button-menu slot="actionItems" @action=${this._handleMenuAction}>
<ha-dropdown slot="actionItems" @wa-select=${this._handleMenuAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item graphic="icon">
<ha-dropdown-item value="check-updates">
${this.hass.localize("ui.panel.config.updates.check_updates")}
<ha-svg-icon slot="graphic" .path=${mdiRefresh}></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiRefresh}></ha-svg-icon>
</ha-dropdown-item>
<ha-list-item graphic="icon">
<ha-dropdown-item value="restart">
${this.hass.localize(
"ui.panel.config.system_dashboard.restart_homeassistant"
)}
<ha-svg-icon slot="graphic" .path=${mdiPower}></ha-svg-icon>
</ha-list-item>
</ha-button-menu>
<ha-svg-icon slot="icon" .path=${mdiPower}></ha-svg-icon>
</ha-dropdown-item>
</ha-dropdown>
<ha-config-section
.narrow=${this.narrow}
@@ -378,12 +377,15 @@ class HaConfigDashboard extends SubscribeMixin(LitElement) {
});
}
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
private async _handleMenuAction(
ev: CustomEvent<{ item: { value: string } }>
) {
const action = ev.detail.item.value;
switch (action) {
case "check-updates":
checkForEntityUpdates(this, this.hass);
break;
case 1:
case "restart":
showRestartDialog(this);
break;
}

View File

@@ -1,4 +1,3 @@
import type { ActionDetail } from "@material/mwc-list";
import { mdiFilterVariant, mdiPlus } from "@mdi/js";
import type { IFuseOptions } from "fuse.js";
import Fuse from "fuse.js";
@@ -18,9 +17,9 @@ import { caseInsensitiveStringCompare } from "../../../common/string/compare";
import { extractSearchParam } from "../../../common/url/search-params";
import { nextRender } from "../../../common/util/render-status";
import "../../../components/ha-button";
import "../../../components/ha-button-menu";
import "../../../components/ha-check-list-item";
import "../../../components/ha-checkbox";
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
import "../../../components/ha-svg-icon";
@@ -408,24 +407,32 @@ class HaConfigIntegrationsDashboard extends KeyboardShortcutMixin(
${!this._showDisabled && this.narrow && disabledConfigEntries.length
? html`<span class="badge">${disabledConfigEntries.length}</span>`
: ""}
<ha-button-menu multi @action=${this._handleMenuAction}>
<ha-dropdown multi @wa-select=${this._handleMenuAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiFilterVariant}
>
</ha-icon-button>
<ha-check-list-item left .selected=${this._showIgnored}>
<ha-dropdown-item
type="checkbox"
.checked=${this._showIgnored}
value="show-ignored"
>
${this.hass.localize(
"ui.panel.config.integrations.ignore.show_ignored"
)}
</ha-check-list-item>
<ha-check-list-item left .selected=${this._showDisabled}>
</ha-dropdown-item>
<ha-dropdown-item
type="checkbox"
.checked=${this._showDisabled}
value="show-disabled"
>
${this.hass.localize(
"ui.panel.config.integrations.disable.show_disabled"
)}
</ha-check-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
</div>
${this.narrow
? html`
@@ -768,12 +775,13 @@ class HaConfigIntegrationsDashboard extends KeyboardShortcutMixin(
});
}
private _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
private _handleMenuAction(ev: CustomEvent<{ item: { value: string } }>) {
const action = ev.detail.item.value;
switch (action) {
case "show-ignored":
this._showIgnored = !this._showIgnored;
break;
case 1:
case "show-disabled":
this._toggleShowDisabled();
break;
}
@@ -979,7 +987,7 @@ class HaConfigIntegrationsDashboard extends KeyboardShortcutMixin(
:host([narrow]) hass-tabs-subpage {
--main-title-margin: 0;
}
ha-button-menu {
ha-dropdown {
margin-left: 8px;
margin-inline-start: 8px;
margin-inline-end: initial;
@@ -1077,7 +1085,7 @@ class HaConfigIntegrationsDashboard extends KeyboardShortcutMixin(
margin-inline-start: 16px;
margin-inline-end: initial;
}
ha-button-menu {
ha-dropdown ha-icon-button {
color: var(--primary-text-color);
}
`,

View File

@@ -1,4 +1,3 @@
import type { ActionDetail } from "@material/mwc-list";
import {
mdiCellphoneKey,
mdiDeleteOutline,
@@ -14,9 +13,9 @@ import { isComponentLoaded } from "../../../../../common/config/is_component_loa
import { stringCompare } from "../../../../../common/string/compare";
import { extractSearchParam } from "../../../../../common/url/search-params";
import "../../../../../components/ha-button";
import "../../../../../components/ha-button-menu";
import "../../../../../components/ha-card";
import "../../../../../components/ha-list-item";
import "../../../../../components/ha-dropdown";
import "../../../../../components/ha-dropdown-item";
import { getSignedPath } from "../../../../../data/auth";
import { getConfigEntryDiagnosticsDownloadUrl } from "../../../../../data/diagnostics";
import type { OTBRInfo, OTBRInfoDict } from "../../../../../data/otbr";
@@ -76,10 +75,11 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
return html`
<hass-subpage .narrow=${this.narrow} .hass=${this.hass} header="Thread">
<ha-button-menu slot="toolbar-icon">
<ha-dropdown slot="toolbar-icon">
<ha-icon-button
.path=${mdiDotsVertical}
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
></ha-icon-button>
<a
href=${getConfigEntryDiagnosticsDownloadUrl(
@@ -88,23 +88,23 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
target="_blank"
@click=${this._signUrl}
>
<ha-list-item>
<ha-dropdown-item>
${this.hass.localize(
"ui.panel.config.integrations.config_entry.download_diagnostics"
)}
</ha-list-item>
</ha-dropdown-item>
</a>
<ha-list-item @click=${this._addTLV}
<ha-dropdown-item @click=${this._addTLV}
>${this.hass.localize(
"ui.panel.config.thread.add_dataset_from_tlv"
)}</ha-list-item
)}</ha-dropdown-item
>
<ha-list-item @click=${this._addOTBR}
<ha-dropdown-item @click=${this._addOTBR}
>${this.hass.localize(
"ui.panel.config.thread.add_open_thread_border_router"
)}</ha-list-item
)}</ha-dropdown-item
>
</ha-button-menu>
</ha-dropdown>
<div class="content">
<h1>${this.hass.localize("ui.panel.config.thread.my_network")}</h1>
${networks.preferred
@@ -242,12 +242,12 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
)}
></ha-svg-icon>`
: ""}
<ha-button-menu
<ha-dropdown
slot="meta"
.network=${network}
.router=${router}
.otbr=${otbr}
@action=${this._handleRouterAction}
@wa-select=${this._handleRouterAction}
>
<ha-icon-button
.label=${this.hass.localize(
@@ -257,7 +257,10 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
slot="trigger"
></ha-icon-button>
${showDefaultRouter
? html`<ha-list-item .disabled=${isDefaultRouter}>
? html`<ha-dropdown-item
value="set-default"
.disabled=${isDefaultRouter}
>
${isDefaultRouter
? this.hass.localize(
"ui.panel.config.thread.default_router"
@@ -265,28 +268,28 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
: this.hass.localize(
"ui.panel.config.thread.set_default_router"
)}
</ha-list-item>`
</ha-dropdown-item>`
: ""}
${otbr
? html`<ha-list-item>
? html`<ha-dropdown-item value="reset-router">
${this.hass.localize(
"ui.panel.config.thread.reset_border_router"
)}</ha-list-item
)}</ha-dropdown-item
>
<ha-list-item>
<ha-dropdown-item value="change-channel">
${this.hass.localize(
"ui.panel.config.thread.change_channel"
)}</ha-list-item
)}</ha-dropdown-item
>
${network.dataset?.preferred
? ""
: html`<ha-list-item>
: html`<ha-dropdown-item value="add-to-network">
${this.hass.localize(
"ui.panel.config.thread.add_to_my_network"
)}
</ha-list-item>`}`
</ha-dropdown-item>`}`
: ""}
</ha-button-menu>`
</ha-dropdown>`
: ""}
</ha-list-item>`;
})}`
@@ -480,24 +483,22 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
});
}
private _handleRouterAction(ev: CustomEvent<ActionDetail>) {
private _handleRouterAction(ev: CustomEvent<{ item: { value: string } }>) {
const network = (ev.currentTarget as any).network as ThreadNetwork;
const router = (ev.currentTarget as any).router as ThreadRouter;
const otbr = (ev.currentTarget as any).otbr as OTBRInfo;
const index = network.dataset
? Number(ev.detail.index)
: Number(ev.detail.index) + 1;
switch (index) {
case 0:
const action = ev.detail.item.value;
switch (action) {
case "set-default":
this._setPreferredBorderAgent(network.dataset!, router);
break;
case 1:
case "reset-router":
this._resetBorderRouter(otbr);
break;
case 2:
case "change-channel":
this._changeChannel(otbr);
break;
case 3:
case "add-to-network":
this._setDataset(otbr);
break;
}
@@ -713,7 +714,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
ha-svg-icon[slot="meta"] {
width: 24px;
}
ha-button-menu a {
ha-dropdown a {
text-decoration: none;
}
.routers {

View File

@@ -1,6 +1,6 @@
import "@home-assistant/webawesome/dist/components/divider/divider";
import { consume } from "@lit/context";
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import {
mdiCog,
mdiContentDuplicate,
@@ -32,13 +32,13 @@ import "../../../components/entity/ha-entities-picker";
import "../../../components/ha-alert";
import "../../../components/ha-area-picker";
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-fab";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-picker";
import "../../../components/ha-list";
import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import "../../../components/ha-textfield";
import { fullEntitiesContext } from "../../../data/context";
@@ -227,9 +227,9 @@ export class HaSceneEditor extends PreventUnsavedMixin(
? computeStateName(this._scene)
: this.hass.localize("ui.panel.config.scene.editor.default_name")}
>
<ha-button-menu
<ha-dropdown
slot="toolbar-icon"
@action=${this._handleMenuAction}
@wa-select=${this._handleMenuAction}
activatable
>
<ha-icon-button
@@ -238,67 +238,64 @@ export class HaSceneEditor extends PreventUnsavedMixin(
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item
graphic="icon"
<ha-dropdown-item
value="apply"
.disabled=${!this.sceneId || this._mode === "live"}
>
${this.hass.localize("ui.panel.config.scene.picker.apply")}
<ha-svg-icon slot="graphic" .path=${mdiPlay}></ha-svg-icon>
</ha-list-item>
<ha-list-item graphic="icon" .disabled=${!this.sceneId}>
<ha-svg-icon slot="icon" .path=${mdiPlay}></ha-svg-icon>
</ha-dropdown-item>
<ha-dropdown-item value="show-info" .disabled=${!this.sceneId}>
${this.hass.localize("ui.panel.config.scene.picker.show_info")}
<ha-svg-icon
slot="graphic"
slot="icon"
.path=${mdiInformationOutline}
></ha-svg-icon>
</ha-list-item>
<ha-list-item graphic="icon" .disabled=${!this.sceneId}>
</ha-dropdown-item>
<ha-dropdown-item value="show-settings" .disabled=${!this.sceneId}>
${this.hass.localize(
"ui.panel.config.automation.picker.show_settings"
)}
<ha-svg-icon slot="graphic" .path=${mdiCog}></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiCog}></ha-svg-icon>
</ha-dropdown-item>
<ha-list-item graphic="icon" .disabled=${!this.sceneId}>
<ha-dropdown-item value="edit-category" .disabled=${!this.sceneId}>
${this.hass.localize(
`ui.panel.config.scene.picker.${this._getCategory(this._entityRegistryEntries, this._scene?.entity_id) ? "edit_category" : "assign_category"}`
)}
<ha-svg-icon slot="graphic" .path=${mdiTag}></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiTag}></ha-svg-icon>
</ha-dropdown-item>
<ha-list-item graphic="icon">
<ha-dropdown-item value="toggle-yaml">
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${this._mode !== "yaml" ? "yaml" : "ui"}`
)}
<ha-svg-icon slot="graphic" .path=${mdiPlaylistEdit}></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiPlaylistEdit}></ha-svg-icon>
</ha-dropdown-item>
<li divider role="separator"></li>
<wa-divider></wa-divider>
<ha-list-item .disabled=${!this.sceneId} graphic="icon">
<ha-dropdown-item value="duplicate" .disabled=${!this.sceneId}>
${this.hass.localize(
"ui.panel.config.scene.picker.duplicate_scene"
)}
<ha-svg-icon
slot="graphic"
.path=${mdiContentDuplicate}
></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiContentDuplicate}></ha-svg-icon>
</ha-dropdown-item>
<ha-list-item
<ha-dropdown-item
value="delete"
.disabled=${!this.sceneId}
class=${classMap({ warning: Boolean(this.sceneId) })}
graphic="icon"
>
${this.hass.localize("ui.panel.config.scene.picker.delete_scene")}
<ha-svg-icon
class=${classMap({ warning: Boolean(this.sceneId) })}
slot="graphic"
slot="icon"
.path=${mdiDelete}
>
</ha-svg-icon>
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
${this._errors ? html` <div class="errors">${this._errors}</div> ` : ""}
${this._mode === "yaml" ? this._renderYamlMode() : this._renderUiMode()}
<ha-fab
@@ -652,24 +649,27 @@ export class HaSceneEditor extends PreventUnsavedMixin(
}
}
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
private async _handleMenuAction(
ev: CustomEvent<{ item: { value: string } }>
) {
const action = ev.detail.item.value;
switch (action) {
case "apply":
activateScene(this.hass, this._scene!.entity_id);
break;
case 1:
case "show-info":
fireEvent(this, "hass-more-info", { entityId: this._scene!.entity_id });
break;
case 2:
case "show-settings":
showMoreInfoDialog(this, {
entityId: this._scene!.entity_id,
view: "settings",
});
break;
case 3:
case "edit-category":
this._editCategory(this._scene!);
break;
case 4:
case "toggle-yaml":
if (this._mode === "yaml") {
this._initEntities(this._config!);
this._exitYamlMode();
@@ -677,10 +677,10 @@ export class HaSceneEditor extends PreventUnsavedMixin(
this._enterYamlMode();
}
break;
case 5:
case "duplicate":
this._duplicate();
break;
case 6:
case "delete":
this._deleteTapped();
break;
}
@@ -1289,9 +1289,6 @@ export class HaSceneEditor extends PreventUnsavedMixin(
justify-content: center;
align-items: center;
}
li[role="separator"] {
border-bottom-color: var(--divider-color);
}
ha-list-item.entity {
padding-right: 28px;
}

View File

@@ -1,12 +1,11 @@
import type { ActionDetail } from "@material/mwc-list";
import { mdiDotsVertical } from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { navigate } from "../../common/navigate";
import "../../components/ha-button-menu";
import "../../components/ha-dropdown";
import "../../components/ha-dropdown-item";
import "../../components/ha-icon-button";
import "../../components/ha-list-item";
import "../../components/ha-menu-button";
import "../../components/ha-tab-group";
import "../../components/ha-tab-group-tab";
@@ -40,16 +39,16 @@ class PanelDeveloperTools extends LitElement {
<div class="main-title">
${this.hass.localize("panel.developer_tools")}
</div>
<ha-button-menu slot="actionItems" @action=${this._handleMenuAction}>
<ha-dropdown slot="actionItems" @wa-select=${this._handleMenuAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item>
<ha-dropdown-item value="debug">
${this.hass.localize("ui.panel.developer-tools.tabs.debug.title")}
</ha-list-item>
</ha-button-menu>
</ha-dropdown-item>
</ha-dropdown>
</div>
<ha-tab-group @wa-tab-show=${this._handlePageSelected}>
<ha-tab-group-tab slot="nav" panel="yaml" .active=${page === "yaml"}>
@@ -122,11 +121,12 @@ class PanelDeveloperTools extends LitElement {
}
}
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
navigate(`/developer-tools/debug`);
break;
private async _handleMenuAction(
ev: CustomEvent<{ item: { value: string } }>
) {
const action = ev.detail.item.value;
if (action === "debug") {
navigate(`/developer-tools/debug`);
}
}

View File

@@ -1,4 +1,3 @@
import type { ActionDetail } from "@material/mwc-list";
import {
mdiDotsVertical,
mdiDownload,
@@ -27,11 +26,11 @@ import {
import { MIN_TIME_BETWEEN_UPDATES } from "../../components/chart/ha-chart-base";
import "../../components/chart/state-history-charts";
import type { StateHistoryCharts } from "../../components/chart/state-history-charts";
import "../../components/ha-button-menu";
import "../../components/ha-date-range-picker";
import "../../components/ha-dropdown";
import "../../components/ha-dropdown-item";
import "../../components/ha-icon-button";
import "../../components/ha-icon-button-arrow-prev";
import "../../components/ha-list-item";
import "../../components/ha-menu-button";
import "../../components/ha-spinner";
import "../../components/ha-target-picker";
@@ -148,23 +147,23 @@ class HaPanelHistory extends LitElement {
></ha-icon-button>
`
: ""}
<ha-button-menu slot="actionItems" @action=${this._handleMenuAction}>
<ha-dropdown slot="actionItems" @wa-select=${this._handleMenuAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-list-item graphic="icon" .disabled=${this._isLoading}>
<ha-dropdown-item value="download" .disabled=${this._isLoading}>
${this.hass.localize("ui.panel.history.download_data")}
<ha-svg-icon slot="graphic" .path=${mdiDownload}></ha-svg-icon>
</ha-list-item>
<ha-svg-icon slot="icon" .path=${mdiDownload}></ha-svg-icon>
</ha-dropdown-item>
<ha-list-item graphic="icon" .disabled=${this._isLoading}>
<ha-dropdown-item value="add-card" .disabled=${this._isLoading}>
${this.hass.localize("ui.panel.history.add_card")}
<ha-svg-icon slot="graphic" .path=${mdiImagePlus}></ha-svg-icon>
</ha-list-item>
</ha-button-menu>
<ha-svg-icon slot="icon" .path=${mdiImagePlus}></ha-svg-icon>
</ha-dropdown-item>
</ha-dropdown>
<div class="flex content">
<div class="filters">
@@ -477,12 +476,15 @@ class HaPanelHistory extends LitElement {
navigate(`/history?${createSearchParam(params)}`, { replace: true });
}
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
private async _handleMenuAction(
ev: CustomEvent<{ item: { value: string } }>
) {
const action = ev.detail.item.value;
switch (action) {
case "download":
this._downloadHistory();
break;
case 1:
case "add-card":
this._suggestCard();
break;
}