* Add dependency review workflow with npm metadata checks
* Temporarily run dependency review on push
* Remove temporary push trigger from dependency review
* Encode the full package name in npm registry URLs
* Check optional/peer dependencies and fail on npm registry errors
Co-authored-by: timmo001 <28114703+timmo001@users.noreply.github.com>
* Convert npm metadata check to TypeScript
* Type workflow scripts with Node 24 types instead of DOM
* Detect npm alias target changes as new dependencies
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* Show four avatars in a cluster bubble before counting
A bubble capped at three avatars added a +1 chip for the fourth
member, taking a fourth slot to hide one avatar. Four members now show
as four avatars; from five on, three avatars and a count fill the same
four slots.
* Open the new zone dialog on every visit to /config/zone/new
The route was only handled in firstUpdated. The config panel is kept
alive between visits and the router reuses the zone page when it is
already the current one, so "Create zone from current location" did
nothing once the zone list had been opened earlier in the session. The
route is now handled on every route change, like /edit/ already was.
The dialog also opened before the more-info dialog it was launched
from had finished leaving the history, and that departure closed the
new dialog again. The page now awaits the replace navigation, which
waits for closing dialogs, before opening it.
* Hide the map overview while the dashboard is being edited
In panel view edit mode the map card kept rendering its overview. On
phones that is a bottom sheet fixed over the bottom of the screen,
which covered the card's edit bar and the view's add button, so the
map dashboard could not be edited in portrait. The overview is for
using the map, not configuring it, so it is left out while editing.
* Show only the overview tabs that have something to list
People and Zones were always offered, with an empty message when the
map card's entities held none of them; only Devices was hidden when
empty. All three now appear only with entries, the first remaining tab
takes over when the selected one empties, and the overview tells the
card so its marker filter follows. The empty-tab messages are gone
with the empty tabs.
* List the person of the current user first, as "Me"
The overview's People tab sorted everyone alike. The person linked to
the user looking at the map now comes first and is named "Me" in the
list and the detail header, through a localized string. Their initials
still come from their real name.
* Draw the overview activity as a timeline
The activity list reused logbook rows: the person's name on every row,
the state pushed to the right, dividers between rows. It is now a
timeline of its own. Each row names where the person went, with the
clock time and how long ago underneath, hung off a dot in the zone's
color with a rail to the next row. A zone's rows name who came or
left and where they are. Five rows show at first, with a "Show more"
button for the rest. The overview no longer needs the broad hass
object, which only the logbook row took.
* Fit the map to its zones when they are all it shows
Zones only joined the auto-fit with the fit_zones option. The panel
map does not set it, so on the Zones tab, with no people or devices
left, the fit found nothing and jumped straight to the home
coordinates at the default zoom. Zones now stand in whenever nothing
else is on the map, which goes through the animated fit like the
other tabs. With fit_zones they still join a fit of people and devices.
* Add store panel as a copy of the HACS frontend
Verbatim copy of src/ from hacs/frontend at d97dce0 into src/panels/store. Imports still point at the HACS submodule layout and the iframe shell is still present; this is the baseline for the port.
* Rewrite store panel imports and drop the iframe shell
Every import that pointed at the old `homeassistant-frontend` submodule now
resolves inside this repository's `src/` tree. Five components were renamed or
removed upstream, so they point at their current equivalents: `ha-button-menu`
and `ha-menu` to `ha-dropdown`, `ha-md-menu-item` to `ha-dropdown-item`,
`ha-fab` to `ha-button`, and `ha-circular-progress` to `ha-spinner`. The
`@material/mwc-button` and `@material/mwc-linear-progress` side-effect imports
are gone with them; those packages are no longer dependencies here.
`main.ts` becomes `ha-panel-store.ts` and registers `ha-panel-store`. It now
receives `hass`, `narrow`, `route` and `panel` from the panel resolver, so
everything that only made sense inside an iframe is removed: applying themes to
the parent element, forwarding haptic and keydown events to the main window,
bridging `location-changed`, the document-level navigation click handler, the
dialog manager, the injected body stylesheet, and the redirect to the default
route. `entrypoint.ts`, `extra.ts`, `html/` and `version.ts` are deleted for the
same reason.
* Move store panel translations into the frontend translation tree
The panel's own translation bundle is gone. Its keys now live under
`ui.panel.store` in `src/translations/en.json`, and `panel.store` gives the
sidebar its "Community store" title. Every `hacs.localize("some.key")` call
became `hass.localize("ui.panel.store.some.key")`, which means the `localize`
member on the `Hacs` interface, the `HacsLocalizeKeys` type and the localize
bootstrap in `HacsElement` are no longer needed. `TranslationDict` is derived
straight from `en.json`, so the moved keys type-check without any casts.
`dialog_about.frontend_version` did not come along: its only consumer was the
frontend version constant that went away with the iframe shell.
* Hold store panel state in the panel instead of a HACS mixin
The panel element now owns the repository list and the info payload as
internal state, loads both on first update and refreshes them from the
store/subscribe signals through SubscribeMixin. That drops the
HacsElement base class and its logger, so the hacs object handed to the
child components is plain data. Children that used to patch that object
with an update-hacs event now fire store-refresh instead and let the
panel refetch.
Also moves every WebSocket command over to the store/ prefix and trims
the info payload to what the backend still returns.
* Update the store panel to current frontend components
Rebuilds the panel on the components the frontend ships today: the
dialogs get their heading from ha-dialog itself and their buttons from
ha-dialog-footer, the overflow menus become ha-dropdown with
ha-dropdown-item, the download action becomes a fab-slotted ha-button,
and the progress and spinner indicators move to ha-progress-bar and
ha-spinner. brandsUrl loses the dropped useFallback option.
Also clears the eslint backlog the panel came in with: no arrow
functions in templates, no console calls, alt text on the brand images,
and private members named consistently.
* Register the store panel and route old HACS paths
Add the store panel to the panel resolver so the backend can serve it,
and move every internal navigation path in the panel from /hacs to
/store. The /hacsfiles static prefix stays, the backend serves it.
Repoint the hacs_repository my-redirect at the store panel and add a
store_repository alias next to it. Both keep the same target, so the
owner, repository, and category parameters still reach the panel's
redirect handler. Existing README badges keep working.
* Rename HACS to Community store in the store panel
Bring the ported panel in line with the repository conventions: panel
parts are ha-*, dialogs are dialog-* with a matching show-dialog-*
helper, and the typo in the overflow menu filename is fixed.
Rename the code identifiers to match, so the panel talks about a store
instead of HACS: StoreData, StoreInfo, StoreDispatchEvent, a store
property on the child elements, storeStyles and --store-* custom
properties.
Reword every user-facing string that named HACS. Backend names stay put:
the hacs_dispatch_* signal values, the /hacsfiles static prefix, the
hacs_repository my-redirect key, and the hacs.xyz documentation and
catalog infrastructure.
The stale HACS-REPOSITORY-PANEL nodeName check now matches the element
it was always meant to match, so removing a repository from its own page
navigates back again.
* Show a message when the store panel is opened without the integration
The panel is registered on every install while the integration is only set up on some, so an empty store must not try to talk to a backend that is not there.
* Link the Community store from the Settings dashboard
The store panel is hidden from the sidebar, so reach it from the Settings dashboard instead and give its pages a way back.
* Fit the store pages into the main layout
The repository page still sized itself to the viewport and the router recoloured the header with sidebar colours, both leftovers from running inside an iframe. Next to the sidebar that made the page a sidebar-width too wide, pushing the toolbar menu off-screen and un-centering the card.
* Let the quick bar create My links for store repositories
The repository page listened for the "m" key on the document body and opened a My link itself, which fought the quick bar's own "m" shortcut once the panel stopped living in an iframe. The quick bar now resolves a store repository page to the hacs_repository redirect by looking up the repository name, and the panel's handler is gone. The reload after installing a dashboard resource no longer goes through the main window helper, and unused scrollbar styles are dropped.
* Remove the external links from the store menu
The About dialog, the issue tracker link and the link to the HACS GitHub organisation pointed at a project outside Home Assistant. The store is part of Home Assistant now, so they go. The documentation link stays until the documentation moves.
* Fix runtime bugs in the store panel
* Remove external HACS leftovers from the store panel
* Tidy types and conventions in the store panel
* Clean up the store panel translations
* Give the store redirect error screen its hass and narrow properties
Without them the screen's back and refresh buttons render without labels.
* Use the store signal names and local resource URLs
The backend renames these in lockstep: the dispatcher signals lose their
`hacs_dispatch_` prefix, and downloaded dashboard resources are served
from `/local/community/` with a `v` cache-busting parameter instead of
the store-owned `/hacsfiles/` route and `hacstag`.
* Drop the disabled reasons the store backend no longer reports
Setup failures now surface through the config entry state instead of a disabled store, so only the runtime reasons remain.
* Rename the Community store to Marketplace
The panel, its elements, dialogs, data types, WebSocket commands,
dispatcher signals and translations now use marketplace, matching the
renamed backend domain. The hacs_repository My link keeps its slug.
* Finish the Marketplace panel
* Confirm replacing a built-in integration with the download
* Fix README links, older versions and grouping in the Marketplace panel
* Handle list continuations and placeholder characters in Marketplace READMEs
- Indented lines inside a list item are treated as text, so their links and issue references get rewritten.
- A README that already contains the private placeholder characters is left alone.
* Keep indented code inside list items literal in Marketplace READMEs
* Fix the warning title, icon colors and dead subscriptions in the Marketplace panel
- The warning takes its title from the Marketplace translations, it is not empty on a direct visit.
- Icons keep the colors of the menu or chip they are in.
- Dismissing new repositories is offered whatever the filters show.
- The dialogs no longer subscribe to an error signal the backend never sends.
- The custom repositories list names the category in the language of the user.
* Handle the edges of the Marketplace panel more carefully
- The warning can be continued again when the panel did not take over.
- Only a query with an owner and a repository opens a repository as a My link.
- Links to /hacs inside Home Assistant open the Marketplace.
- A rate limit after the download dialog closed opens nothing.
- A removed entry takes its catalog with it.
- The quick bar says why it could not make a My link for a repository.
* Type the Marketplace panel against the backend contract
- The data types match what the backend sends.
- Errors are caught as unknown and read through one helper.
- Events are typed from their declarations.
- Spacing uses the theme tokens.
* Make the wording of Marketplace actions clearer
* Leave the way back from the Marketplace warning to the header
* Show the download progress in the Marketplace download dialog
* Offer to set up a newly downloaded integration right away
* Make the Marketplace download dialog plainer and move other versions to the menu
- One sentence says what the download or update does, no paths or technical details.
- Warnings span the top of the dialog, like in the more-info dialog.
- The progress shows where the update dialog shows it, and the button shows it is busy.
- A restart is only mentioned for updates of integrations.
- Choosing another version moved to the repository menu, it opens on its own when the newest version is too new.
* Use the consume decorator of the frontend in the Marketplace dialogs
* Save the Marketplace search, and keep search and filters per session
* Lay out the Marketplace repository page like the other Settings detail pages
* Bring the Marketplace list page in line with the other Settings lists
* Use the standard Settings dialogs, styles and strings in the Marketplace
* Name the Marketplace data helpers like the rest of the frontend and drop the global refresh event
* Center the Marketplace warning and say how long accepting it lasts
* Call it installing in the Marketplace, and set up right after installing
* Use the uninstall command of the Marketplace
* Fix the row menu, the failed setup screen and README links in the Marketplace panel
* Guide uninstalling an integration that is in use, and offer it after deleting the last entry
* Fix reinstalling, filters, stale pages and README handling in the Marketplace panel
* Explain why an integration in use can not be uninstalled
* Test that accepting the warning and uninstalling in use really happen
* Point HACS links and icons at the Marketplace, and clarify its copy
* Share the error message and menu rendering of the Marketplace panel
* Split the long renders of the Marketplace panel
* Treat Marketplace repository ids as strings
* Guide the user after installing or uninstalling from the Marketplace
* Count down before the Marketplace warning can be accepted, and show it only once
* Show what to do next and who made it on the Marketplace repository page
* Title the Marketplace repository page Marketplace and keep signals one line
* Say which Home Assistant a Marketplace repository requires
"Works with Home Assistant 2025.1 or newer" read as a promise it had been tried there. It is a minimum the repository asks for, so say it that way.
* Explain adding to the Marketplace from a GitHub link
The dialog was called "Custom repositories" and opened on a list of them. Someone adding their first one saw an empty list and two bare fields.
It now says what it is for, and that what is added this way is made by the community like everything else in the Marketplace. Both fields say what they want. The list of what was added from links comes after that, under its own heading, and only once there is any.
* Give the Marketplace Discover, Browse and Installed tabs
The Marketplace was one long table, grouped by status. Finding what you have installed, or what waits for an update, meant scrolling past everything else.
Discover opens with what is popular and what changed lately. Each section links to Browse, sorted and filtered the way the section picked from it. The sorting and filters are in that link, so it works in a new tab or when shared too. Browse is the full table, without the grouping. Installed lists only what is installed, and its tab says how many updates wait.
On the tables, the icon shows a check for what is installed and an arrow for what waits for an update. The search says how many items it looks through. Adding from a GitHub link also got its own button in the toolbar.
Tabs take an optional badge for the update count.
* Find out what is added from a link in the Marketplace
The dialog asks only for the link. What it holds is found out when it is added, and only when that does not settle it, the dialog asks for the type, from what it might be.
* Fix races and lost answers in the Marketplace panel
The add from link dialog could add another link than the one it looked at, a See all link followed a second time kept the filters of the first, Retry did not retry a My link, and a My link that finished late replaced the repository opened meanwhile. A /hacs link from a dashboard showed the Marketplace without its translations. Uninstalling after deleting the last entry could hang when it failed, and a failed removal from the list closed as if it worked. Code inside a quote in a README got issue links.
* Tidy up small things in the Marketplace panel
The README was prepared again for every change of an entity, a screen reader heard the name of a tab but not its badge, and four exports and a type member were left from before.
* Show Marketplace errors in the language of the user and refresh less
Errors from the backend are translated with their key and placeholders in
the panel and when offering to uninstall after deleting an entry, with the
message of Home Assistant as fallback. The repository page reloads after
updating its information, since the list does not carry everything it
shows. Repository signals share one list request, with one more after it
when anything changed meanwhile, and Discover parses each date once.
* Fix the Marketplace strings that showed placeholders and wrong plurals
The add repository question showed {repository} literally, the quotes
around it escaped the placeholder. Seconds, downloads, stars and issues
now say one instead of ones, the status names match across the list and
the repository page, and the GitHub and log messages read the same as
the rest.
* Handle the review of the Marketplace panel
Links to /hacs reach beforeRender again, a route alias was resolved
before it. A refetch on a signal no longer opens the GitHub dialog by
itself, a failed release list is told once, and a failed first load is
translated without logging to the console. Deleting an entry only offers
the uninstall for custom integrations, after the restart and credential
prompts. The YAML resource address carries the version and is encoded.
Applied links mark their history entry instead of listening on the
window, and the last updated column sorts on a number.
* Rewrite Marketplace README addresses once they are rendered
ha-markdown gets an optional rewriteUrl, which runs over every link and
image of the rendered HTML in an inert template, before anything loads.
The README of a repository uses it, so reference links, entities and
unquoted attributes no longer slip through as addresses on Home
Assistant. The regular expressions that set aside links and addresses
for issue references only start where those can start, a README with a
long word or many unclosed links no longer freezes the page.
* Replace ha-ripple Material base with own implementation
* Remove ha-ripple origin comment
* Restore ha-ripple control setter and CSS zoom handling
* Defer ha-ripple forced-colors check to event handling
* Move pickers onto the new list components
Pickers, the quick bar, the automation element search and the card
picker entity tree now use ha-list-base and its item family instead of
Material Web list items.
- Add a virtual-focus mode to ha-list-base and ha-list-virtualized:
focus stays in a search field and the list marks the active row.
- Render picker rows as ha-list-item-option, with the current value as
the selected option.
- Make ha-combo-box-item a presentational row layout on ha-row-item.
- Render ha-picker-field as a native button with the clear button next
to it.
- Let held arrow keys repeat in pickers and the automation search.
- Fix list items not unregistering after they leave the DOM, and an
unhandled rejection when a virtualized list is removed mid-layout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Fix section titles
* fix e2e
* mage entity tree search like picker and automation
* remove comments
* fix picker field aria label
* fix disabled field style selector
* Update src/components/ha-picker-combo-box.ts
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
The persistent cache version still hashed `.yarn/patches`, which moved to
`patches/` in #54392. The lookup is guarded by `existsSync`, so it failed
silently and patch contents stopped contributing to the version at all.
That hash is the only thing that notices a patch change: a patch alters a
package's files but not its version, which is all rspack's node_modules
snapshot checks. Editing a patch therefore left the cache version
identical and the build reused stale compiled modules.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* Give tentative calendar events a striped background
A tentative bar gets a light fill in its calendar color with diagonal stripes in the text color, instead of the outline alone. A tentative dot keeps its color and size and gets stripes in the calendar's contrast color. The stripes set a tentative event apart from past days, which are already drawn faded. They repeat on whole pixels, so every stripe looks the same.
* Strengthen tentative dot stripes and add a forced-colors fallback
The stripes on a tentative dot are its only cue, so they now reach at least 3:1 against the dot. In forced colors the stripes and the dot's fill are dropped, so a tentative bar falls back to a dashed border and a tentative dot to a ring of the same size.
---------
Co-authored-by: 1358 <1583407+1358@users.noreply.github.com>
The landing page bundle includes the Intl polyfill. When a browser
needs a polyfill, it loads locale data from /static/locale-data/.
The landing page build never copied that directory, so these requests
returned 404. The language picker then showed raw language codes.
Fixeshome-assistant/landingpage#216
* Fade scrolling badges only where content is hidden
* Add tests for the scroll fade controller
* Ignore Safari overscroll when fading scrolling badges
* Migrate chips from Material to Web Awesome
* Fix button mock for chip inheritance in config flow tests
* Reflect chip disabled state and test chip interaction contracts
Co-authored-by: timmo001 <28114703+timmo001@users.noreply.github.com>
* Delete test/components/chips.test.ts
* Restore legend chip sizing in chart and distribution card
* Skip chip set arrow navigation with a single chip
* Import ha-svg-icon in filter chip
* Improve chip disabled states, icon sizing and focus after removal
* Use toolbar role for chip sets only when labelled
* Drop href from disabled link chips
* Restore toolbar role for chip sets
* Forward referrerPolicy to link chips
Co-authored-by: timmo001 <28114703+timmo001@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* Migrate from Yarn to pnpm
Switch the package manager to pnpm 11, keeping every resolved
dependency version from yarn.lock.
- Move resolutions to pnpm overrides and Yarn patches to patches/
- Enable supply-chain protection: 3 day minimum release age,
trust policy that blocks provenance downgrades, and dependency
build scripts denied by default
- Declare dependencies that were imported but only available through
Yarn's hoisting: zrender, @lezer/common, zxing-wasm,
@babel/helper-compilation-targets, core-js-compat, @types/geojson
- Look up pinned license overrides in pnpm's node_modules layout
- Update CI, scripts, git hooks, Renovate, and documentation
* Cache the pnpm store with node_modules in CI
Jobs that restore the shared node_modules cache skip the install, so
the pnpm store is empty there. The license file generation runs
`pnpm licenses list`, which reads package metadata from the store and
fails without it.
* Point the demo e2e comment at the real test:e2e:demo script
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add an ESPHome device setup checklist on the device page.
Surface advertised proxy capabilities in a banner and dialog so users can continue Bluetooth, audio, Z-Wave, and serial setup after the device is added.
* Harden the ESPHome setup wizard after review feedback.
Show cached capabilities while offline, wait for user data before the banner, and expose setup status to assistive tech.
* Mark ESPHome serial setup completed when a UART port is in use.
* Mark ESPHome Z-Wave setup completed when zwave_js matches the proxy home ID.
* Align the ESPHome setup wizard with Sendspin audio and the existing add-integration dialog.
Music stays incomplete until Music Assistant is installed and Sendspin is on, and serial setup no longer offers a hardcoded integration list.
* Fix storage chart size labels after bidirectional isolate
bidiIsolate can return undefined, so the gigabyte formatter needs a string fallback for the type check.
* Show the ESPHome setup banner only for music, Z-Wave, or serial devices, and use the finished headline once nothing remains to set up.
* Let the ESPHome music row finish once Music Assistant is installed.
The Sendspin switch is optional and matched by object id, a finished checklist uses the reminder, and the storage chart label matches dev after the bidiIsolate change.
* Give ESPHome music setup its own sequence so Sendspin is enabled after the Music Assistant offer.
* Show ESPHome audio install progress after the offer buttons hide, and drop the guest PIN step until that switch exists.
* Keep ESPHome setup on the device's own Z-Wave and music steps when discovery already started or Music Assistant is cancelled.
A detected controller was treated as not started, cancelling the Music Assistant dialog still enabled Sendspin, and a missing discovery flow opened a generic Z-Wave flow.
* Keep ESPHome setup honest when USB usage or Z-Wave flow lookup fails.
A failed USB scan was shown as unused ports, overlapping capability requests could overwrite a newer result, and a rejected Z-Wave flow lookup never showed the retry error.
* Use the repo consume decorator in the ESPHome setup UI.
* Mark tentative calendar events
A tentative event is drawn hollow: a ring instead of a dot and an outline instead of a filled block. The event dialog names the status. Confirmed events and events without a status look as before.
* Remove the tests for tentative events
---------
Co-authored-by: 1358 <1583407+1358@users.noreply.github.com>