From 6f140d30f58383f5d825b46f917a2e3728bd0ec4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 9 Dec 2025 12:12:15 +0000
Subject: [PATCH] Fix scene-dashboard and script-picker - remove .clickAction,
@click, keep-open, has-overflow, replace ha-sub-menu with native submenu
pattern
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
---
src/panels/config/scene/ha-scene-dashboard.ts | 251 +++++++++++++-----
src/panels/config/script/ha-script-picker.ts | 30 +--
2 files changed, 196 insertions(+), 85 deletions(-)
diff --git a/src/panels/config/scene/ha-scene-dashboard.ts b/src/panels/config/scene/ha-scene-dashboard.ts
index e702b3797b..d3c2bada87 100644
--- a/src/panels/config/scene/ha-scene-dashboard.ts
+++ b/src/panels/config/scene/ha-scene-dashboard.ts
@@ -6,6 +6,7 @@ import {
mdiContentDuplicate,
mdiDelete,
mdiDotsVertical,
+ mdiFloorPlan,
mdiHelpCircle,
mdiInformationOutline,
mdiMenuDown,
@@ -55,9 +56,8 @@ import "../../../components/ha-icon-overflow-menu";
import "@home-assistant/webawesome/dist/components/divider/divider";
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
-import "../../../components/ha-md-menu";
+import type { HaDropdownItem } from "../../../components/ha-dropdown-item";
import "../../../components/ha-state-icon";
-import "../../../components/ha-sub-menu";
import "../../../components/ha-svg-icon";
import "../../../components/ha-tooltip";
import { createAreaRegistryEntry } from "../../../data/area_registry";
@@ -439,8 +439,7 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
const categoryItems = html`${this._categories?.map(
(category) =>
html`
${category.icon
? html``
@@ -448,13 +447,13 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
${category.name}
`
)}
-
+
${this.hass.localize(
"ui.panel.config.automation.picker.bulk_actions.no_category"
)}
-
+
${this.hass.localize("ui.panel.config.category.editor.add")}
`;
@@ -469,17 +468,11 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
this.hass.entities[entityId]?.labels.includes(label.label_id)
);
return html`
-
`;
})}
-
+
${this.hass.localize("ui.panel.config.labels.add_label")}
`;
@@ -511,13 +504,13 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
${area.name}
`
)}
-
+
${this.hass.localize(
"ui.panel.config.devices.picker.bulk_actions.no_area"
)}
-
+
${this.hass.localize(
"ui.panel.config.devices.picker.bulk_actions.add_area"
)}
@@ -645,7 +638,7 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
>
${!this.narrow
- ? html`
+ ? html`
${labelsInOverflow
? nothing
- : html`
+ : html`
`}
${areasInOverflow
? nothing
- : html`
+ : html`
`}`
: nothing}
${this.narrow || areasInOverflow
- ? html`
+ ? html`
${this.narrow
? html``}
${this.narrow
- ? html`
-
+ ? html`
+ ${this.hass.localize(
+ "ui.panel.config.automation.picker.bulk_actions.move_category"
+ )}
+
+ ${this._categories?.map(
+ (category) =>
+ html`
+ ${category.icon
+ ? html``
+ : html``}
+ ${category.name}
+ `
+ )}
+
${this.hass.localize(
- "ui.panel.config.automation.picker.bulk_actions.move_category"
+ "ui.panel.config.automation.picker.bulk_actions.no_category"
)}
-
- ${categoryItems}
- `
+
+
+ ${this.hass.localize("ui.panel.config.category.editor.add")}
+
+ `
: nothing}
${this.narrow || labelsInOverflow
- ? html`
-
- ${this.hass.localize(
- "ui.panel.config.automation.picker.bulk_actions.add_label"
- )}
-
+ ? html`
+ ${this.hass.localize(
+ "ui.panel.config.automation.picker.bulk_actions.add_label"
+ )}
+
+ ${this._labels?.map((label) => {
+ const color = label.color ? computeCssColor(label.color) : undefined;
+ const selected = this._selected.every((entityId) =>
+ this.hass.entities[entityId]?.labels.includes(label.label_id)
+ );
+ const partial =
+ !selected &&
+ this._selected.some((entityId) =>
+ this.hass.entities[entityId]?.labels.includes(label.label_id)
+ );
+ return html`
+
+
+ ${label.icon
+ ? html``
+ : nothing}
+ ${label.name}
+
+ `;
+ })}
+
+
+ ${this.hass.localize("ui.panel.config.label_registry.editor.add")}
- ${labelItems}
- `
+ `
: nothing}
${this.narrow || areasInOverflow
- ? html`
-
+ ? html`
+ ${this.hass.localize(
+ "ui.panel.config.devices.picker.bulk_actions.move_area"
+ )}
+
+ ${this._areas?.map(
+ (area) =>
+ html`
+ ${area.icon
+ ? html``
+ : html``}
+ ${area.name}
+ `
+ )}
+
${this.hass.localize(
- "ui.panel.config.devices.picker.bulk_actions.move_area"
+ "ui.panel.config.devices.picker.bulk_actions.no_area"
)}
-
- ${areaItems}
- `
+
+
+ ${this.hass.localize("ui.panel.config.area_registry.editor.add")}
+
+ `
: nothing}
`
: nothing}
@@ -926,9 +988,77 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) {
}
}
- private _handleBulkCategory = (item) => {
- const category = item.value;
- this._bulkAddCategory(category);
+ private _handleCategoryMenuSelect = (ev: CustomEvent) => {
+ const item = ev.detail.item as HaDropdownItem;
+ if (item.value === "create-category") {
+ this._bulkCreateCategory();
+ return;
+ }
+ if (item.value === "no-category") {
+ this._bulkAddCategory(null!);
+ return;
+ }
+ this._bulkAddCategory(item.value);
+ };
+
+ private _handleLabelMenuSelect = (ev: CustomEvent) => {
+ const item = ev.detail.item as HaDropdownItem & { dataset: { action?: string } };
+ if (item.value === "create-label") {
+ this._bulkCreateLabel();
+ return;
+ }
+ const action = item.dataset.action as "add" | "remove";
+ this._bulkLabel(item.value, action);
+ };
+
+ private _handleAreaMenuSelect = (ev: CustomEvent) => {
+ const item = ev.detail.item as HaDropdownItem;
+ if (item.value === "create-area") {
+ this._bulkCreateArea();
+ return;
+ }
+ if (item.value === "no-area") {
+ this._bulkAddArea(null!);
+ return;
+ }
+ this._bulkAddArea(item.value);
+ };
+
+ private _handleOverflowMenuSelect = (ev: CustomEvent) => {
+ const item = ev.detail.item as HaDropdownItem & { dataset: { action?: string } };
+ if (item.value === "create-category") {
+ this._bulkCreateCategory();
+ return;
+ }
+ if (item.value === "no-category") {
+ this._bulkAddCategory(null!);
+ return;
+ }
+ if (item.value === "create-label") {
+ this._bulkCreateLabel();
+ return;
+ }
+ if (item.value === "create-area") {
+ this._bulkCreateArea();
+ return;
+ }
+ if (item.value === "no-area") {
+ this._bulkAddArea(null!);
+ return;
+ }
+ // Check if it's a label action
+ if (item.dataset.action) {
+ const action = item.dataset.action as "add" | "remove";
+ this._bulkLabel(item.value, action);
+ return;
+ }
+ // Check if it's an area
+ if (this.hass.areas[item.value]) {
+ this._bulkAddArea(item.value);
+ return;
+ }
+ // Otherwise it's a category
+ this._bulkAddCategory(item.value);
};
private async _bulkAddCategory(category: string) {
@@ -956,12 +1086,6 @@ ${rejected
}
}
- private async _handleBulkLabel(ev) {
- const label = ev.currentTarget.value;
- const action = ev.currentTarget.action;
- this._bulkLabel(label, action);
- }
-
private async _bulkLabel(label: string, action: "add" | "remove") {
const promises: Promise[] = [];
this._selected.forEach((entityId) => {
@@ -992,11 +1116,6 @@ ${rejected
}
}
- private _handleBulkArea = (item) => {
- const area = item.value;
- this._bulkAddArea(area);
- };
-
private async _bulkAddArea(area: string) {
const promises: Promise[] = [];
this._selected.forEach((entityId) => {
diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts
index 8cb524232d..20f1c9087e 100644
--- a/src/panels/config/script/ha-script-picker.ts
+++ b/src/panels/config/script/ha-script-picker.ts
@@ -424,8 +424,7 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
const categoryItems = html`${this._categories?.map(
(category) =>
html`
${category.icon
? html``
@@ -433,13 +432,13 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
${category.name}
`
)}
-
+
${this.hass.localize(
"ui.panel.config.automation.picker.bulk_actions.no_category"
)}
-
+
${this.hass.localize("ui.panel.config.category.editor.add")}
`;
@@ -454,17 +453,11 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
this.hass.entities[entityId]?.labels.includes(label.label_id)
);
return html`
-
`;
})}
-
+
${this.hass.localize("ui.panel.config.labels.add_label")}
`;
const areaItems = html`${Object.values(this.hass.areas).map(
(area) =>
html`
${area.icon
? html``
@@ -496,13 +488,13 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
${area.name}
`
)}
-
+
${this.hass.localize(
"ui.panel.config.devices.picker.bulk_actions.no_area"
)}
-
+
${this.hass.localize(
"ui.panel.config.devices.picker.bulk_actions.add_area"
)}