-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Migrate ha-button-menu and ha-md-menu to ha-dropdown in config panel #28368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
… network panels Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
…ning class Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
… menus Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot rework this file. there are still .clickActions and some ha-dropdown don't have a @wa-select
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0b88a78. Replaced all .clickAction on ha-dropdown-item elements with proper value attributes and added @wa-select handlers on parent ha-dropdown elements. The remaining .clickAction patterns are on ha-md-menu-item inside ha-md-menu which is a different component pattern for the row-level overflow menu.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot thanks, I don't think ha-submenu should be used here. Checkout the webawesome dropdown docs and fix the submenu using ha-dropdown-item
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in a1c7f91. Replaced ha-sub-menu with the native Web Awesome dropdown submenu pattern using slot="submenu" on child ha-dropdown-item elements, following the pattern from the gallery documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Why is there still a ha-md-menu migrate it too!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 44fcb72. Migrated the row-level overflow menu from ha-md-menu to ha-dropdown by:
- Replaced programmatic menu opening with inline dropdown pattern
- Each data table row now has its own
ha-dropdownwith the overflow button as trigger - Removed all
ha-md-menu,ha-md-menu-item, andha-md-dividerimports and usage - Updated action methods to accept
AutomationEntitydirectly instead of extracting from menu context - Added
_handleRowOverflowMenuhandler with value-based dispatch logic
…ndlers Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
…/migrate-overflow-menus-to-ha-dropdown
| return html`<ha-md-menu-item | ||
| return html`<ha-dropdown-item | ||
| .value=${label.label_id} | ||
| .action=${selected ? "remove" : "add"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot I would use data-action here since it's a string. And then in _handleBulkLabel event.currentTarget.data.action.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fd9bac. Changed from .action property binding to data-action HTML attribute, and updated the handler to access it via ev.currentTarget.dataset.action.
Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
| this.narrow | ||
| ></ha-icon-button>`} | ||
| ${this.narrow | ||
| ? html`<ha-sub-menu> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot migrate submenu too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 0a8c0c1. Replaced ha-sub-menu with native Web Awesome submenu pattern using slot="submenu" on child ha-dropdown-item elements, matching the pattern in other migrated files.
…ce ha-sub-menu, move class to button Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
…keep-open, has-overflow, replace ha-sub-menu with native submenu pattern Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
… handlers and replace ha-sub-menu with native submenu Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
| .value=${area.area_id} | ||
| .clickAction=${this._handleBulkArea} | ||
| > | ||
| html`<ha-dropdown-item .value=${area.area_id}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot value should be "select area" or smth and then we should add another attribute data-area-id=...., so we can be sure what is selected
| ${this._labels?.map((label) => { | ||
| const color = label.color ? computeCssColor(label.color) : undefined; | ||
| const selected = this._selected.every((deviceId) => | ||
| this.hass.devices[deviceId]?.labels.includes(label.label_id) | ||
| ); | ||
| const partial = | ||
| !selected && | ||
| this._selected.some((deviceId) => | ||
| this.hass.devices[deviceId]?.labels.includes(label.label_id) | ||
| ); | ||
| return html`<ha-dropdown-item | ||
| slot="submenu" | ||
| .value=${label.label_id} | ||
| data-action=${selected ? "remove" : "add"} | ||
| @click=${this._handleBulkLabel} | ||
| keep-open | ||
| > | ||
| <ha-checkbox | ||
| slot="icon" | ||
| .checked=${selected} | ||
| .indeterminate=${partial} | ||
| reducedTouchTarget | ||
| ></ha-checkbox> | ||
| <ha-label | ||
| style=${color ? `--color: ${color}` : ""} | ||
| .description=${label.description} | ||
| > | ||
| ${label.icon | ||
| ? html`<ha-icon slot="icon" .icon=${label.icon}></ha-icon>` | ||
| : nothing} | ||
| ${label.name} | ||
| </ha-label> | ||
| </ha-dropdown-item>`; | ||
| })} | ||
| <wa-divider slot="submenu"></wa-divider> | ||
| <ha-dropdown-item | ||
| slot="submenu" | ||
| value="__create_label__" | ||
| @click=${this._bulkCreateLabel} | ||
| > | ||
| ${this.hass.localize("ui.panel.config.labels.add_label")} | ||
| </ha-dropdown-item> | ||
| </ha-dropdown-item>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot checkout ha-automation-picker how I implemented the submenu. Way easier than you did it!
| ${Object.values(this.hass.areas).map( | ||
| (area) => | ||
| html`<ha-dropdown-item slot="submenu" .value=${area.area_id}> | ||
| ${area.icon | ||
| ? html`<ha-icon slot="icon" .icon=${area.icon}></ha-icon>` | ||
| : html`<ha-svg-icon | ||
| slot="icon" | ||
| .path=${mdiTextureBox} | ||
| ></ha-svg-icon>`} | ||
| ${area.name} | ||
| </ha-dropdown-item>` | ||
| )} | ||
| <ha-dropdown-item slot="submenu" value="__no_area__"> | ||
| ${this.hass.localize( | ||
| "ui.panel.config.devices.picker.bulk_actions.no_area" | ||
| )} | ||
| </ha-dropdown-item> | ||
| <wa-divider slot="submenu"></wa-divider> | ||
| <ha-dropdown-item slot="submenu" value="__create_area__"> | ||
| ${this.hass.localize( | ||
| "ui.panel.config.devices.picker.bulk_actions.add_area" | ||
| )} | ||
| </ha-dropdown-item> | ||
| </ha-dropdown-item> | ||
| <wa-divider></wa-divider>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot fix submenu like in ha-automation-picker
| const item = ev.detail.item as HaDropdownItem; | ||
| switch (item.value) { | ||
| case "__no_area__": | ||
| this._bulkAddArea(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Argument of type 'null' is not assignable to parameter of type 'string'.
| this._bulkCreateLabel(); | ||
| break; | ||
| case "__no_area__": | ||
| this._bulkAddArea(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot Argument of type 'null' is not assignable to parameter of type 'string'.
| private _handleBulkArea = (item) => { | ||
| const area = item.value; | ||
| this._bulkAddArea(area); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot not used anymore
| ${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`<ha-dropdown-item | ||
| slot="submenu" | ||
| .value=${label.label_id} | ||
| data-action=${selected ? "remove" : "add"} | ||
| keep-open | ||
| > | ||
| <ha-checkbox | ||
| slot="icon" | ||
| .checked=${selected} | ||
| .indeterminate=${partial} | ||
| reducedTouchTarget | ||
| ></ha-checkbox> | ||
| <ha-label | ||
| style=${color ? `--color: ${color}` : ""} | ||
| .description=${label.description} | ||
| > | ||
| ${label.icon | ||
| ? html`<ha-icon slot="icon" .icon=${label.icon}></ha-icon>` | ||
| : nothing} | ||
| ${label.name} | ||
| </ha-label> | ||
| </ha-dropdown-item>`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot fix submenu like I did in ha-automation-picker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot !
| ${this._categories?.map( | ||
| (category) => | ||
| html`<ha-dropdown-item | ||
| slot="submenu" | ||
| .value=${category.category_id} | ||
| > | ||
| ${category.icon | ||
| ? html`<ha-icon slot="icon" .icon=${category.icon}></ha-icon>` | ||
| : html`<ha-svg-icon slot="icon" .path=${mdiTag}></ha-svg-icon>`} | ||
| ${category.name} | ||
| </ha-dropdown-item>` | ||
| )} | ||
| <ha-dropdown-item slot="submenu" value="__no_category__"> | ||
| ${this.hass.localize( | ||
| "ui.panel.config.automation.picker.bulk_actions.no_category" | ||
| )} | ||
| </ha-dropdown-item> | ||
| <wa-divider slot="submenu"></wa-divider> | ||
| <ha-dropdown-item slot="submenu" value="__create_category__"> | ||
| ${this.hass.localize("ui.panel.config.category.editor.add")} | ||
| </ha-dropdown-item> | ||
| </ha-dropdown-item>` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot fix submenu like I did it in ha-automation-picker
…omation picker Co-authored-by: wendevlin <12148533+wendevlin@users.noreply.github.com>
|
@copilot You solved the submenu change in several files wrong. Do it like I did it in |
Fixed in the latest commits. All files now use the same submenu pattern as
|
Breaking change
Proposed change
Migrates all overflow menus in
src/panels/config/from legacyha-button-menu/ha-md-button-menuandha-md-menucomponents to the newha-dropdowncomponent, following the pattern established in PR #28293.Files Migrated:
areas/ha-config-area-page.tsareas/ha-config-areas-dashboard.tsdashboard/ha-config-dashboard.tscloud/cloud-login-panel.tscloud/cloud-account.tsnetwork/supervisor-network.tsscene/ha-scene-editor.tsscene/ha-scene-dashboard.tscore/ha-config-section-updates.tsautomation/ha-automation-picker.ts(including row-level overflow menus)devices/ha-config-devices-dashboard.tsentities/ha-config-entities.tshelpers/ha-config-helpers.tsscript/ha-script-picker.tsMigration Pattern Applied:
<ha-button-menu>/<ha-md-button-menu>/<ha-md-menu>with<ha-dropdown><ha-list-item>(inside menus) /<ha-md-menu-item>with<ha-dropdown-item>@actionto@wa-selectevent handlers.clickActiononha-dropdown-itemwithvalueattributes and@wa-selecthandlers on parentev.detail.item.valueslot="graphic"/slot="start"withslot="icon"class="warning"withvariant="danger"<ha-md-divider>and<li divider>with<wa-divider><ha-sub-menu>with native Web Awesome submenu pattern usingslot="submenu"on childha-dropdown-itemelements_renderLabelItems(submenu),_renderAreaItems(submenu)) with conditional slot assignment (.slot=${submenu ? "submenu" : ""}) for cleaner submenu implementationsdata-*HTML attributes for custom data (e.g.,data-area-id,data-action) following web standards"select-area") instead of IDs asvalueattributes for clarityhas-overflowandkeep-openthat don't exist in Web Awesome dropdown APItype="checkbox"onha-dropdown-itemfor toggleable menu items in picker pages (automation, script, scene), while keeping@clickhandlers with embeddedha-checkboxelements for label/area bulk selection menus (following automation picker pattern)ha-dropdownto trigger element (e.g.,ha-button) where appropriateha-md-menu,HaMdMenu,ha-md-menu-item,HaMdMenuItem,ha-md-divider,ha-sub-menu,ha-check-list-item) after migrationHaDropdownItemha-dropdowncomponents (e.g., row-level overflow menus)Type of change
Example configuration
Additional information
Checklist
If user exposed functionality or configuration variables are added/changed:
Original prompt
Objective
Migrate all overflow menus in src/panels/config/ from legacy ha-button-menu/ha-md-button-menu components to the new ha-dropdown component, following the pattern established in PR #28293.
Except src/panels/config/logs/ha-config-logs.ts that is already migrated in another PR.
Files to Migrate
Search for and migrate ALL files in src/panels/config/ that contain either:
ha-button-menu (with ha-list-item)
ha-md-button-menu (with ha-md-menu-item)
ha-dropdown-item API Reference
Based on the webawesome source code, ha-dropdown-item has the following:
Available Slots
Slot
Description
(default)
The dropdown item's label
icon
An optional icon to display before the label
details
Additional content to display after the label
submenu
Submenu items for nested menus
Available Properties
Property
Type
Description
value
string
Value for identifying the item in wa-select event
type
'normal' | 'checkbox'
Set to 'checkbox' for checkable items
checked
boolean
Whether checkbox is checked (only when type="checkbox")
disabled
boolean
Disables the item
variant
'default' | 'danger'
Visual variant for danger/warning items
CSS Parts
Part
Description
checkmark
The checkmark icon for checkbox items
icon
Container for icon slot
label
Container for label slot
details
Container for details slot
submenu-icon
Submenu indicator icon
submenu
Submenu container
Migration Rules
1.1 Removing Old Imports
CRITICAL: Before removing ANY import, search the ENTIRE file to verify it is ONLY used for the overflow menu being migrated.
Step-by-step verification process:
For ha-button-menu import:
Search file for all <ha-button-menu occurrences
Count total usages
If ALL are being migrated → remove import
If ANY remain → keep import
For ha-list-item import:
Search file for ALL <ha-list-item occurrences
Check EACH usage location:
Inside ? → Will be migrated
Inside ? → NOT migrated, keep import
Standalone list usage? → NOT migrated, keep import
Only remove import if ALL usages are within menus being migrated
For ha-md-button-menu import:
Same process as ha-button-menu
For ha-md-menu-item import:
Same process as ha-list-item
For ha-md-divider import:
Check if used outside of menus
Only remove if ALL usages are within menus being migrated
1.2 Adding New Imports
Import paths are RELATIVE to the current file location. Calculate the correct path!
Path calculation method:
Count directories from file location to src/
Add components/ to reach the components folder
File Location
Levels Up
Import Path Prefix
src/panels/config/logs/*. ts
3
../../../components/
src/panels/config/backup/*.ts
3
../../../components/
src/panels/config/areas/*.ts
3
../../../components/
src/panels/config/cloud/login/*.ts
4
../../../../components/
src/panels/config/cloud/account/*.ts
4
../../../../components/
src/panels/config/automation/trigger/*.ts
4
../../../../components/
src/panels/config/automation/trigger/types/*.ts
5
../../../../../components/
src/panels/config/automation/condition/*.ts
4
../../../../components/
src/panels/config/integrations/*.ts
3
../../../components/
src/panels/config/integrations/integration-panels/thread/*.ts
5
../../../../../components/
Required new imports (adjust path based on file location):
TypeScript
import "../../../components/ha-dropdown";
import "../../../components/ha-dropdown-item";
import type { HaDropdownItem } from "../../../components/ha-dropdown-item";
For wa-divider (only if dividers are used):
TypeScript
import "@home-assistant/webawesome/dist/components/divider/divider";
Note: This is an absolute package import, NOT a relative path.
Old Component
New Component
(inside menu only)
3.1 On the dropdown container (ha-dropdown)
Old Attribute
Action
Notes
positioning="fixed"
Remove
Not needed
positioning="popover"
Replace with placement="bottom-end"
Or appropriate placement
anchor-corner="..."
Replace with placement="bottom-end"
Simplify
menu-corner="..."
Replace with placement="bottom-end"
Simplify
fixed
Remove
Not needed
multi
Remove
Use type="checkbox" on items instead
@action=${handler}
Replace with @wa-select=${handler}
Update handler logic
@opened=${handler}
Replace with @wa-show=${handler}
See section 5.6
@closed=${handler}
Replace with @wa-hide=${handler}
See section 5.6
3.2 On menu items (ha-dropdown-item)
Old Attribute
New Attribute
Notes
slot="graphic"
slot="icon"
Icon slot renamed
slot="start"
...
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.