Compare commits

...

278 Commits

Author SHA1 Message Date
Aidan Timson
6477330e83 Improve spacing on assist devtools 2026-04-30 10:26:55 +01:00
Aidan Timson
bc4437b3b5 Ally: Add aria labels to ha-icon-button and hui-root (#51784)
* Ally: Add aria labels to ha-icon-button and hui-root

* use aria-hidden

* Add hidden content for label to satisfy ally review

* Make fix in button instead (probably should update upstream)

* Aria label (pending wa update)
2026-04-30 09:20:56 +00:00
Wendelin
c99b43dcf3 Use input button slots for a11y (#51801)
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 09:12:23 +00:00
Bram Kragten
8945b917b3 Add tooltips for Jinja editors (#51792)
* Add descriptions to Jinja2 tags, filters, expressions, tests and variables

All standard Jinja2 tags, filters, and expression completions now carry
info and detail strings so the autocomplete info popover shows meaningful
documentation when users browse them — not just HA-specific functions.

* Add keyboard shortcut tip to the template developer tool

A ha-tip below the editor card now shows users that Ctrl+Space triggers
autocomplete, Ctrl+F opens the search panel, and F11 toggles fullscreen,
making the editor's built-in features more discoverable.

* Add hover tooltips for Jinja2 functions, filters and expressions

Hovering over a function, filter, tag, test, or variable name inside a
Jinja2 template shows a tooltip with its signature and description.
Non-tag completions also get a help-circle icon linking to the
corresponding Home Assistant template-functions documentation page.

The tooltip is rendered as a custom Lit element (ha-code-editor-jinja-hover)
that takes the Completion object and an optional docUrl as properties.

The tooltip source (haJinjaHoverSource) is wired into ha-code-editor
via CodeMirror's hoverTooltip extension. The documentationUrl() helper
is used so the link points to the correct subdomain (www / rc / next)
based on the running HA version.

* Add hover tooltips for Jinja2 hover + arg value tooltips for entity/device/area

Wire haJinjaHoverSource into ha-code-editor via CodeMirror hoverTooltip.
Two types of hover are now shown in jinja2/yaml mode:

- Hovering a function/filter/tag/expression name shows its signature,
  description, and a doc-link icon (non-tags only).
- Hovering a string-literal argument of a known HA Jinja function (e.g.
  states(), device_name(), area_entities()) shows the friendly name,
  current state, device, and area for entity_id arguments; the device
  name and area for device_id arguments; and the area name for area_id
  arguments. The same applies to states["entity_id"] subscripts.

The arg-value tooltip reuses CompletionItem / ha-code-editor-completion-items
(the same component used for autocomplete info popovers) via a new
ha-code-editor-jinja-arg-hover element. HA registry data is passed from
ha-code-editor via a HassArgHoverContext interface to keep jinja_ha_completions.ts
free of HomeAssistant type imports.

* only add tip for autocomplete

* review
2026-04-30 12:07:50 +03:00
Bram Kragten
4d75ea5198 Add inline YAML linting to the yaml code editor (#51791) 2026-04-30 08:42:12 +00:00
Wendelin
ba3a63f856 Fix ha-select undefined value (#51800)
Fix ha-select undefined

Co-authored-by: Copilot <copilot@github.com>
2026-04-30 10:25:26 +03:00
renovate[bot]
fd25d38be6 Update dependency jsdom to v29.1.0 (#51798)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-30 10:18:18 +03:00
Wendelin
ac22374a00 Hide tooltip on mobile clients in ha-sidebar component (#51799) 2026-04-30 10:17:44 +03:00
AlCalzone
de529cc26b Expose Z-Wave exclusion instructions when removing device (#51788)
* Expose Z-Wave exclusion instructions when removing device

* text tweaks

* Apply suggestion from @MindFreeze

* Apply suggestions from code review

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* bring back comment

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-30 06:06:21 +00:00
Aidan Timson
126db3e8df Refactor events devtools tab layout and events output card (#51789)
* Only show events output when there are any, types and margin

* Refactor to use pagination

* Fix

* Simplify, remove pinning and auto-follow, stay on event 1 and allow the user to move around manually

* Show info why only 30 events are keps

* Increase bufffer limit to 100, add explainer and tip when rolls over

* Update disclaimer

* Use buffer position and total instead of event id + total in counter

* Use fixed height and constrain editor

* Cleanup

* Cleanup

* Fix narrow layouts
2026-04-30 08:42:30 +03:00
Matthias de Baat
ed6fd59968 Move preview device analytics button to card (#51787)
* Move preview device analytics button to card

* Add icon back
2026-04-29 17:36:06 +02:00
Paul Bottein
962e941ec9 Merge branch 'master' into dev
# Conflicts:
#	build-scripts/gulp/download-translations.js
#	pyproject.toml
#	src/components/chart/ha-network-graph.ts
#	src/components/date-picker/date-range-picker.ts
#	src/components/date-picker/styles.ts
#	src/components/entity/ha-entity-name-picker.ts
#	src/components/ha-gauge.ts
#	src/components/ha-selector/ha-selector-numeric-threshold.ts
#	src/components/ha-toast.ts
#	src/components/input/ha-input.ts
#	src/data/icons.ts
#	src/dialogs/make-dialog-manager.ts
#	src/panels/config/automation/action/ha-automation-action-row.ts
#	src/panels/config/automation/add-automation-element-dialog.ts
#	src/panels/config/automation/condition/ha-automation-condition-row.ts
#	src/panels/config/automation/condition/types/ha-automation-condition-platform.ts
#	src/panels/config/automation/target/ha-automation-row-targets.ts
#	src/panels/config/automation/trigger/ha-automation-trigger-row.ts
#	src/panels/config/automation/trigger/types/ha-automation-trigger-platform.ts
#	src/panels/config/developer-tools/action/developer-tools-action.ts
#	src/panels/config/devices/ha-config-device-page.ts
#	src/panels/config/entities/entity-registry-settings-editor.ts
#	src/panels/config/ha-panel-config.ts
#	src/panels/config/integrations/integration-panels/zha/zha-device-card.ts
#	src/panels/lovelace/card-features/hui-trend-graph-card-feature.ts
#	src/panels/lovelace/cards/hui-gauge-card.ts
#	src/panels/lovelace/cards/hui-history-graph-card.ts
#	src/panels/lovelace/cards/hui-map-card.ts
#	src/panels/lovelace/sections/hui-section.ts
#	src/panels/lovelace/views/hui-view-footer.ts
#	src/state/quick-bar-mixin.ts
#	yarn.lock
2026-04-29 16:30:58 +02:00
Paul Bottein
31495b2de9 Bumped version to 20260429.0 2026-04-29 16:17:10 +02:00
Bram Kragten
f71dcaeac1 Add automation behavior selector (#30322)
* Add automation behavior selector

* Use mode option instead

* update design

* remove label

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <norbert@rittel.de>

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <norbert@rittel.de>

---------

Co-authored-by: Wendelin <w@pe8.at>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
Co-authored-by: Norbert Rittel <norbert@rittel.de>
2026-04-29 16:12:17 +02:00
Wendelin
26b1bfbe20 Automations: Flatten triggers/conditions list in pickers (#51785)
* Flat add trigger condition collections

* fix list order

Co-authored-by: Copilot <copilot@github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-29 16:11:42 +02:00
Tom Carpenter
c6026507a5 Fix errors loading the demo site (#51695) 2026-04-29 12:04:51 +01:00
Bram Kragten
53b5b43c33 Remove domain prefix from actions (#51278)
* Remove domain prefix from actions

* Only do it for entity domains

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-29 10:44:20 +00:00
Marcin Bauer
cb31afa432 config-flow: rename "Device created" heading to "Name and assign" (#51782)
The old heading "Device created" was a past-tense status message that didn't
communicate what the user needs to do next. The dialog contains a name field
and an area picker, so "Name and assign" better reflects the user's actual
task at this step.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 13:39:26 +03:00
Wendelin
d5deff34ea Redesign automation row indicators (#51737)
add new triggered, test and ran chips
2026-04-29 12:04:27 +02:00
Marcin Bauer
1aed9f8b1f Add Ctrl/Cmd+Click legend solo shortcut to shortcuts dialog (#51781)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 08:17:09 +00:00
Petar Petrov
34ec052568 Open more-info from energy devices detail graph legend (#51778)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-29 07:16:01 +00:00
Petar Petrov
65f11ebc3f Fix duplicate ha-panel-custom on first mount (#51779) 2026-04-29 08:52:25 +02:00
ildar170975
36cadeef40 hui-gauge-card: fix displayed value & unit (#51751)
* Create compute_entity_unit_display.ts

* use computeEntityUnitDisplay()

* fix displayed value & unit

* use value AND valueText

* Update src/common/entity/compute_entity_unit_display.ts

Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-29 06:16:14 +00:00
Bram Kragten
1ed1b7bfda Check for unknown value every render if value is unknown (#51760)
* Check for unknown value every render if value is unknown

* fix race in pickers that add items from the picker

* fix: use value imports for LitElement, html, nothing from lit
2026-04-29 08:55:03 +03:00
ildar170975
e7d9b5348e Dev tools -> Template: align buttons (#51775)
* align buttons

* prettier
2026-04-29 08:53:22 +03:00
Simone Chemelli
fa2c0278cb Add UPTIME sensor device class (#51716)
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 07:20:40 +02:00
Wendelin
fdd0636d9a Media player more info add controls tooltips (#51765)
Add tooltips to media player controls for improved accessibility

Co-authored-by: Copilot <copilot@github.com>
2026-04-29 07:20:02 +02:00
karwosts
39d1173a98 Copy new automation trace picker for scripts (#51776)
* Copy new automation trace picker for scripts

* Use shared component
2026-04-29 07:17:48 +02:00
Bram Kragten
907687c16d Don't just check system domains, for usage, but any domain (#51746) 2026-04-28 21:51:10 +02:00
Joep Meindertsma
3e17779550 feat: Split legend interaction (click vs label) with hover effects (#28517)
* feat: Split legend interaction (click vs label) with icons and hover effects

* Address review feedback on chart legend split

- Rename `externalHiddenState` to `clickLabelForMoreInfo` and the event
  `chart-legend-click` to `legend-label-click` (the `chart-` prefix is
  reserved for echarts-proxy events).
- Use proper translation keys
  `ui.components.history_charts.{toggle_visibility,show_more_info}`
  instead of `ui.common.*` which don't exist.
- Drop the redundant tooltip on the label when it would duplicate the
  icon's "Toggle visibility" tooltip.
- Resolve the legend dataset id back to a real `entity_id` before
  opening more-info: strip known climate-attribute suffixes for history
  charts (`-current_temperature`, `-target_temperature*`, `-heating`/
  `-cooling`/`-drying`/`-fan`), and skip `isExternalStatistic` ids for
  statistics charts. Only fire `hass-more-info` if `hass.states[id]`
  resolves.

* Address followup review feedback on chart legend

- Restore stat-type suffix stripping in statistics chart. When the chart
  has a single entity, ha-chart-base falls back to raw series ids
  (`${statistic_id}-${type}`) for the legend, so clicking
  "sensor.foo (max)" otherwise tries to open `sensor.foo-max`.
- Cover humidifier multi-attribute datasets in the entity-id resolver
  alongside climate / water_heater (`-current_humidity`,
  `-target_humidity`, `-humidifying`, `-on`; `-drying` is already
  contributed by CLIMATE_MODE_CONFIGS). Rename the constant to
  ENTITY_DATASET_SUFFIXES to reflect the broader scope.
- Convert the two legend click targets to `<button type="button">` so
  Tab navigation, Enter/Space activation, and screen-reader semantics
  work. Add `aria-pressed` to the visibility toggle and a
  `:focus-visible` outline. Read the dataset id from `data-id` instead
  of `parentElement.id` so the handlers don't depend on DOM nesting.
- Scope the label hover underline to `.label-clickable` so charts that
  don't opt into more-info (network, sankey, sunburst, energy) keep the
  legacy non-underlined toggle behavior. Render the "Show more info"
  tooltip only when the click will actually fire.
- Drop the redundant physical `margin-right: 0` on the legend toggle;
  `margin-inline-end: 0` alone preserves the click-area extension on
  the start side in RTL.

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-28 21:41:42 +02:00
Paul Bottein
c91802d552 Use full width name field for heading badge editor (#51769) 2026-04-28 21:37:02 +02:00
renovate[bot]
40f3d68f8b Update dependency @rspack/dev-server to v2.0.1 (#51764)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-28 21:30:29 +02:00
Paul Bottein
3aa2352f03 Reorder built-in summaries and custom shortcuts in one list (#51763)
* Reorder built-in summaries and custom shortcuts in one list

* Use summary term
2026-04-28 21:29:10 +02:00
puddly
cc98634fad Add recommended ports to serial selector (#51773)
* Allow ha-form to forward context to selectors

* Categorize ports into recommended/not recommended

* Utilize the interface description

* Ignore copy/pasted product -> interface description
2026-04-28 14:46:28 -04:00
ildar170975
d61829e4d4 Dev tools -> Templates: add ha-scrollbar to render-pane (#51770) 2026-04-28 15:39:29 +00:00
Wendelin
95ce9cb8c1 Add input number unit picker (#51768)
Add unit of measurement options and integrate selector in input number form

Co-authored-by: Copilot <copilot@github.com>
2026-04-28 17:25:32 +02:00
Paul Bottein
846a20dd13 Revert global change from tooltip PR (#51766) 2026-04-28 17:06:54 +02:00
Aidan Timson
36031c7365 Fix capitalisation of integration on system log detail (#51762) 2026-04-28 13:27:18 +02:00
Paulus Schoutsen
f99d95232a Show all the power buttons when media player is in assumed state (#51740) 2026-04-28 11:26:06 +02:00
Petar Petrov
5b4c08ad04 Add color and current temperature options to forecast features (#51761) 2026-04-28 11:20:31 +02:00
Petar Petrov
b0b2d84287 Add precipitation visualization to forecast tile features (#51733) 2026-04-28 08:28:15 +01:00
Wendelin
0a43c29fea Simplify and fix target entity count (#51739)
* Simplify and fix target entity count

* Review

Co-authored-by: Copilot <copilot@github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-28 06:31:36 +00:00
arcsur
61a8df1fa9 Modified the chart legend for climate temperature data sets (#51719)
* Modified the chart legend for climate temperature data sets to display the temperature value, not the overall entity state (previously hvac_mode).

* Use the helper computeAttributeValueDisplay in src/common/entity/compute_attribute_display.ts to format the temperature attribute values.

Co-authored-by: Copilot <copilot@github.com>

* Update src/components/chart/state-history-chart-line.ts

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-28 06:29:45 +00:00
mwolter805
ba3b335f47 Fix ha-panel-custom not restoring after suspendWhenHidden disconnect (#51727)
* fix: rebuild ha-panel-custom on reconnect after suspendWhenHidden

Why:
HA's PartialPanelResolver._onHidden() starts a 5-minute timer when a tab
is backgrounded. When it fires, non-iframe / non-app custom panels
(component_name="custom" without embed_iframe) are removed from the DOM,
which triggers ha-panel-custom.disconnectedCallback() -> _cleanupPanel().
That nulls _setProperties and destroys the child custom-panel element.

When the user returns, _onVisible() re-appends the same <ha-panel-custom>
element. ReactiveElement's base connectedCallback schedules an update,
but update() only calls _createPanel(this.panel) when
changedProps.has("panel") && !deepEqual(oldPanel, this.panel) -- the
panel reference hasn't changed, so nothing happens. _setProperties is
also undefined, so the property-forwarding branch exits early too.
Result: <ha-panel-custom> is present in the DOM but empty -- the user
sees a blank panel until they hard-reload.

Add a connectedCallback() override that rebuilds when the element was
previously cleaned up. Three guards keep it scoped to the recovery path:
  - !this._setProperties: sentinel for "_cleanupPanel ran".
    _setProperties is set inside _createPanel's success paths and only
    nulled in _cleanupPanel.
  - !this.hasChildNodes(): defends against the async window inside
    loadCustomPanel(config).then(...) for non-iframe panels, where a
    rapid detach->attach cycle could otherwise call _createPanel twice
    and append duplicate elements.
  - this.panel: skips first-mount, when the router hasn't assigned a
    panel yet. The existing update() path handles initial _createPanel
    via the changedProps.has("panel") branch.

Mirrors the existing disconnectedCallback override for symmetry.
10 lines + comment, no other file changes.

Affects every non-iframe sidebar custom panel in the HACS ecosystem
(Alarmo, Browser Mod, Homematic(IP) Local, MeshCore, others -- ~60k
combined HA-analytics installs). Reopens dormant home-assistant/frontend
issue #14510 (filed 2022-12-02, stale-bot closed without a fix).

Tests:
- yarn build succeeds locally; the affected chunk is captured for the
  pre-PR local-test on a real HA host.
- Manual repro on user's HA host (10.10.21.221) with the MeshCore
  custom panel: baseline (no patch) reproduces the blank-panel symptom
  after a 6-minute backgrounded tab. Patched chunk: panel rebuilds
  within ~2 seconds of returning. Exemption paths (iframe panel, app
  panel, custom panel with embed_iframe=true) verified to remain
  unaffected. Original chunk restored after testing.
- yarn lint and yarn test pass before PR submission (run before
  Phase 9).

* chore: trigger CLA recheck after author-email link
2026-04-28 08:34:00 +03:00
Wendelin
5449f31162 Fix target picker secondary entities support (#51729)
Add support for secondary entity filtering in target picker
2026-04-28 08:25:41 +03:00
Aidan Timson
1a992aa5f7 Change media browser player to generic picker component (#51734)
* Change media browser player to generic picker component

* Add disabled item support

* Use disabled items

* Sort as original

* Fix divider styling

* Cleanup

Co-authored-by: Copilot <copilot@github.com>

* Remove memo

Co-authored-by: Copilot <copilot@github.com>

* Typing

Co-authored-by: Copilot <copilot@github.com>

* Dont allow disabled items

---------

Co-authored-by: Copilot <copilot@github.com>
2026-04-28 08:24:29 +03:00
ildar170975
6303affe17 Dialogs: call "enlarge" on a wider area (#51750)
* increase an active "enlarge" area

Added a class to make the title span enlargeable.

* increase an active "enlarge" area

* increase an active "enlarge" area
2026-04-28 08:18:30 +03:00
karwosts
fc0ac85223 More detailed trace selector via generic-picker (#51752) 2026-04-28 08:14:32 +03:00
dependabot[bot]
2efc1a658f Bump brace-expansion from 1.1.12 to 1.1.14 (#51753)
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.12 to 1.1.14.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.12...v1.1.14)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.14
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-28 08:13:32 +03:00
renovate[bot]
371642ef3f Update formatjs monorepo (#51747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-28 06:54:17 +02:00
Wendelin
aff9ec4345 Improve debug callWs logs (#51741) 2026-04-27 17:36:58 +02:00
Paul Bottein
80e37e7136 Use current entity in state card conditions (#51708) 2026-04-27 14:59:05 +01:00
Yosi Levy
54a234debd Toast location RTL fix (#51735) 2026-04-27 14:04:33 +01:00
Wendelin
eeb0fb3e4d Automation editor: Fix no target set in some actions (#51642)
Refactor target extraction in HaAutomationActionRow for improved legacy support
2026-04-27 14:45:34 +03:00
JLo
d5dc40fa1f Add entity context to media browser player picker (#51732)
* Add entity context to media browser player picker

Show area and device as a secondary line in both the active player pill
and the player picker dropdown, so users can identify speakers when
multiple players share similar names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update src/panels/media-browser/ha-bar-media-player.ts

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-27 10:32:39 +00:00
Paul Bottein
df12232e93 Add attribute support for numeric state and state (#51706) 2026-04-27 10:11:25 +01:00
Wendelin
1a2e63a5ba Add floor/area: Replace popover with dropdown (#51730) 2026-04-27 08:43:05 +01:00
karwosts
581ba23f4e Stabilize more-info group rendering (#51725) 2026-04-27 08:20:23 +03:00
renovate[bot]
5dda82a8ac Update dependency terser-webpack-plugin to v5.5.0 (#51728)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-27 05:53:31 +02:00
Petar Petrov
5a296fadec Minimize Sankey flow crossings with barycenter sort (#51682)
* Minimize Sankey flow crossings with barycenter sort

* Cache section id-index maps across barycenter sweeps

* Thread graph edges through to sortNodesInSections
2026-04-26 21:42:26 +02:00
dependabot[bot]
5dc99a3dbd Bump actions/setup-node from 6.3.0 to 6.4.0 (#51722)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to 6.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](53b83947a5...48b55a011b)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 13:53:02 +02:00
dependabot[bot]
2f36c64a21 Bump github/codeql-action from 4.35.1 to 4.35.2 (#51721)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.35.1 to 4.35.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](c10b8064de...95e58e9a2c)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.35.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 13:52:59 +02:00
dependabot[bot]
59cfc82e7a Bump actions/cache from 5.0.4 to 5.0.5 (#51720)
Bumps [actions/cache](https://github.com/actions/cache) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](668228422a...27d5ce7f10)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 5.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 13:52:56 +02:00
Paul Bottein
edc36b28a6 Refactor home panel editor (#51701) 2026-04-25 15:48:12 +02:00
Logan Rosen
7b58162f81 Drop eslint-config-airbnb-base and cherry-pick rules (#51627)
Remove the unmaintained eslint-config-airbnb-base dependency (last
updated Nov 2021, no flat config support) along with its FlatCompat
shim infrastructure.

Replace with js.configs.recommended as the base config and explicitly
cherry-pick ~40 high-value safety and style rules from airbnb-base
that aren't already covered by other configs.

Remove 27 rule disables that only existed to suppress airbnb opinions,
and 5 dead TypeScript rule disables for rules no longer in the config.

Fix 4 real bugs caught by the newly added no-constant-binary-expression
rule where template literals were always truthy, making fallback values
unreachable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 14:16:53 +03:00
dependabot[bot]
9e9f247c79 Bump vite from 8.0.2 to 8.0.9 (#51707)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
2026-04-24 21:16:28 +02:00
Bram Kragten
b95fce5f24 Bumped version to 20260325.8 2026-04-24 17:26:41 +02:00
karwosts
f6abbe80a2 Remove spurious map in original-states view (#51696) 2026-04-24 17:24:44 +02:00
Wendelin
71301ef5be Remove allow-mode-change in quick search (#51634)
Remove allow-mode-change attribute from ha-adaptive-dialog in QuickBar component
2026-04-24 17:24:43 +02:00
ildar170975
4af618ac6f Gauge card: fix a height in Horizontal stack (#51626)
remove styles for ":host"
2026-04-24 17:24:42 +02:00
Simon Lamon
5a21ef67cd Adjust gauge again (#51613) 2026-04-24 17:24:41 +02:00
karwosts
251b9a1b94 Fix gauge missing label on load (#51584) 2026-04-24 17:24:40 +02:00
karwosts
cadaa47bf0 Fix gauge segmentLabels, cleanup sorting (#51583) 2026-04-24 17:24:39 +02:00
Jan Čermák
7ec864dc6d Fix rendering of select with multiple options in SupervisorAppConfig (#51585)
If the app config contains a schema field like this one:

```
privileges:
  - "list(ALTER|CREATE|...|UPDATE)?"
```

it was rendered incorrectly as a drop-down where only one item can be
selected - but this is wrong because of the preceding `-` denoting it
should be a list containing the listed values. Supervisor translated
this to an entry of type `select` with `multiple: true`. The `multiple`
flag wasn't passed along, with the flag set the field renders as
expected.

Fixes #51533
2026-04-24 17:08:12 +02:00
Wendelin
680ceb73e9 ha-select allow number values (#51564) 2026-04-24 17:08:11 +02:00
Wendelin
ab31771055 Improve view footer card visibility handling (#51549) 2026-04-24 17:08:10 +02:00
Wendelin
07b9a6e287 Hide footer if card is not visible (#51544)
* Fix footer visibility logic in render method

* use card-visibility-changed
2026-04-24 17:08:09 +02:00
Wendelin
be2c90cd1c Fix register admin quick search shortcuts (#51540) 2026-04-24 17:08:08 +02:00
Raphael Hehl
2af4ff7c8f Fix history/sensor cards stuck loading after backend restart (#51531)
* Fix history/sensor cards stuck loading after backend restart

- Add { resubscribe: false } to history subscriptions to prevent
  corrupt HistoryStream state on auto-resubscription
- Add connection-status handlers to re-subscribe on reconnect
- Add sentinel pattern to prevent re-entrant async subscriptions
- Add shouldUpdate/updated retry when components become available
- Clear sensor device classes cache on WS error
- Clear _error on reconnect so cards can retry
- Add .catch() on unsubscribe to handle dead subscriptions

* Fix type annotation for callWS in getSensorNumericDeviceClasses

* Address review: type connection-status handlers, add reconnect to history panel

- Use HASSDomEvent<ConnectionStatus> instead of (ev as CustomEvent).detail
  for proper type safety on all connection-status handlers
- Add connection-status handler to ha-panel-history so it re-subscribes
  after backend restart (addresses concern about resubscribe: false)

* Address review: sentinel pattern, reconnect handling, stale data reset

- Add sentinel pattern to ha-more-info-history, ha-panel-history,
  hui-history-graph-card to prevent re-entrant subscription races
- Refactor hui-trend-graph-card-feature from SubscribeMixin to manual
  subscription management with connection-status reconnect support
- Reset stale history/statistics data on reconnect in
  hui-history-graph-card and hui-map-card before re-subscribing
- Wrap fetchStatistics and getSensorNumericDeviceClasses calls in
  ha-panel-history with try/catch to handle errors gracefully
- Chain .catch directly on subscribeHistoryStatesTimeWindow in
  hui-trend-graph-card-feature to avoid detached-promise race condition

* Centralize history stream reconnect handling in data layer

Move the reconnect logic from every consumer into `subscribeHistoryStream`
in data/history.ts. The helper listens to the connection's `ready` event
itself, and on reconnect creates a fresh `HistoryStream` and rebuilds
params (so `start_time` for the time-window variant is re-anchored to
"now"). `resubscribe: false` stays as an internal implementation detail.

Removes the duplicated `_handleConnectionStatus` boilerplate and
`connection-status` window listeners from all six history consumers.

* Render subscription errors and make _error reactive

`_error` was declared as a plain string field in hui-graph-header-footer
and ha-more-info-history (non-reactive) and typed as Error/string while
being assigned the WS error object. hui-trend-graph-card-feature had it
reactive but never rendered it.

Align all three with the hui-history-graph-card pattern: reactive
`{ code, message }` and a user-visible error branch in render(). Without
this, a failed subscription would leave the component stuck on a spinner
forever.

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-24 17:08:07 +02:00
Paulus Schoutsen
8139b60248 Add radio_frequency domain entity platform (#51693)
Co-authored-by: balloob <1444314+balloob@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-04-24 15:34:08 +01:00
Wendelin
386372ad00 Use control switch for entity toggle (#51654) 2026-04-24 16:12:33 +02:00
Petar Petrov
9151b200a1 Add energy grid balance card (#51480)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-24 14:04:15 +02:00
renovate[bot]
f449c6c1c1 Update dependency @codemirror/search to v6.7.0 (#51704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 14:47:13 +03:00
renovate[bot]
d1eb3fd162 Update vitest monorepo to v4.1.5 (#51703)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 14:46:32 +03:00
pcan08
71648078d8 Home dashboard: enable/disable entities suggestion (#51407)
* Allow showing/hiding welcome message on home overview

Add a toggle in the edit overview dialog to show or hide the
"Welcome, [user]" greeting header on the home overview page,
following the same pattern as the existing summary enable/disable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Move welcome message toggle into its own section in home editor

The welcome message is a greeting header, not a summary card, so it
now lives in a separate "Greeting" section above the "Summaries" section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* rename hidden_welcome_message to hide_welcome_message

* Use ha-form boolean selector for welcome message toggle

Replace manual label/ha-switch markup with ha-form using a boolean
selector for better accessibility and consistency with the rest of
the codebase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add helper text to welcome message toggle in home editor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Remove greeting section header

* Allow enabling/disabling suggested entities on home overview

Add a toggle in the Overview edit dialog to show or hide the
usage-predicted entities that fill remaining slots alongside favorites.
When disabled, the usage prediction fetch is skipped entirely.
The favorites entities helper text is updated to no longer reference
suggestions, which now have their own dedicated toggle and description.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Use ha-input-helper-text for suggested entities description

Replace the raw <p class="section-description"> with ha-input-helper-text
for the suggested entities toggle description, using the proper HA
component for helper text styling instead of custom CSS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Rename show_suggested_entities to hide_suggested_entities

Aligns with the hidden_summaries naming convention used elsewhere.
Logic is inverted accordingly: undefined means shown (default),
true means hidden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Use ha-form boolean selector for suggested entities toggle

Replace the manual label+switch+helper-text with ha-form using a boolean
selector.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Refine suggested entities toggle label and callback signatures

Drop unused schema parameter from computeLabel/computeHelper callbacks
and shorten the label from "Show suggested entities" to "Suggested entities"
since the boolean checkbox already conveys the enabled/disabled intent.

* Group favorite entities picker and suggested toggle in expandable panel

Wrap ha-entities-picker and the suggested entities boolean in an outlined
ha-expansion-panel with a star-outline icon. Move the welcome message
toggle above the panel. Use "Favorite entities" as the panel header and
remove the redundant picker label.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Update entities description to use "include" instead of "show"

* Fix expansion panel content leaking when collapsed

Move inner padding from --expansion-panel-content-padding to a wrapper
div, matching the ha-form-expandable pattern, so no content is visible
when the panel is collapsed.

* Add spacing between alert and expansion panel in home editor dialog

* Move favorites description above picker, update helper text

- Add description paragraph above ha-entities-picker explaining the feature
- Update helper text to concise behavioral note: "Entities in your favorites always appear first."

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 09:23:07 +02:00
Wendelin
a1ac0a0941 Target picker respect primaryEntitiesOnly from selector (#51677) 2026-04-24 09:14:00 +02:00
Wendelin
625cadce26 Update webawesome to 3.3.1-ha.1 (#51697) 2026-04-24 09:09:42 +02:00
karwosts
407ea0d9a7 Remove spurious map in original-states view (#51696) 2026-04-24 07:15:39 +02:00
renovate[bot]
05bb7ef409 Update dependency typescript-eslint to v8.59.0 (#51694)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-23 18:24:13 +00:00
Wendelin
b1b64fa6f4 respect rtl in ha-control-slider (#51691)
* Control slider rtl

Co-authored-by: Tom Carpenter <T.Carpenter@leeds.ac.uk>
2026-04-23 18:15:09 +00:00
Petar Petrov
bb4cf5ead7 Move Event received trigger to generic category in picker (#51675) 2026-04-23 14:51:40 +02:00
Petar Petrov
1466aff1ae Add daily forecast card feature (#51637)
* Add daily forecast card feature

* Address review feedback: validate forecast type, refresh on state change

* Use statesContext for current temp state

* Use internationalizationContext for localize

* Narrow support/resolve helpers to accept stateObj

* Use connection instead of hass for subscribeForecast

* Reduce opacity of current temp line

* Type states context consumer

* Use consumeEntityState decorator
2026-04-23 15:47:53 +03:00
Aidan Timson
867e8633f6 Adaptive popover, add to set date card feature (#51650)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-23 12:33:23 +00:00
Petar Petrov
9d393f9fc5 Remove resources from hass object (#51676) 2026-04-23 14:32:35 +02:00
Paulus Schoutsen
910276b860 Improve serial proxies look in serial port selector (#51673)
* Improve serial proxies look in serial port selector

* Use new format

* Custom renderer for value

* Update src/components/ha-selector/ha-selector-serial-port.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* format

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-23 11:33:40 +00:00
Petar Petrov
d05cc25e66 Upgrade @rspack/core and @rspack/dev-server to v2 (#51674)
* Update dependency @rspack/dev-server to v2

* Upgrade @rspack/core to 2.0.0

Pairs with the @rspack/dev-server 2.0.0 bump in #51666 — dev-server v2
declares @rspack/core ^2.0.0-0 as a peer, so the two must move together.

Patches webpackbar to defend against non-string info in Rspack 2's
ProgressPlugin handler (otherwise `parseRequest` throws `split is not a
function` during compilation).

Verified locally: yarn lint:types, yarn test, yarn lint, script/build_frontend,
and all three rspack-dev-server-{demo,cast,gallery} tasks.

* Wrap webpackbar instead of patching it

Replace the yarn patch with a small SafeWebpackBar subclass that sanitizes
the progress `details` array before the upstream parseRequest sees it.
Keeps the fix local to the Rspack config where it belongs.

* Pass moduleIdentifier to webpackbar progress

Rspack 2's progress info is `{ builtModules, moduleIdentifier? }`.
moduleIdentifier is what v1 passed as a plain string, so extract it to
keep the "active module" line in the progress bar instead of blanking it.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-23 13:16:14 +02:00
Petar Petrov
f61b6f1163 Extract consumeStateObj / consumeEntityRegistryEntry decorators (#51652)
* Extract consumeStateObj / consumeEntityRegistryEntry decorators

* Address review: rename to consume-context-entry, tighten undefined check

* Rename entityId->entityIdPath, consumeStateObj->consumeEntityState, add consumeEntityStates
2026-04-22 17:49:34 +03:00
Paulus Schoutsen
9893786682 Add activity log sidebar to security dashboard (#29901)
* Add activity log sidebar to security dashboard

Add a sidebar with a logbook card to the security domain dashboard,
filtered by security entities (cameras, locks, alarm panels, covers,
binary sensors) and person entities. The sidebar uses the sections view
sidebar layout with mobile tab support for switching between devices
and activity views on narrow screens.

https://claude.ai/code/session_01MCjuARQfuyowAbJ9fwiEnH

* Update src/panels/security/strategies/security-view-strategy.ts

* remove import

* Set max column to 3 and fix title margin

* Type fix

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-22 16:19:38 +03:00
João Palmeiro
09817d166a Fix sidebar layout to ensure all options are visible on mobile browsers (#51672) 2026-04-22 14:57:35 +02:00
ildar170975
c83177b600 hui-dialog-edit-card: independent scrollbars (#29648)
* add independent scrollbars

* resolving conflicts

* cleanup

* resolving conflicts

* fix for ha-switch overflow

* add ha-scrollbar

* Avoid !important by scoping selectors to editor and preview

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-22 12:50:22 +00:00
Aidan Timson
55670550ef Improve typing on lifestyle functions for changed props (5/5) (#51669)
* Split typing-common-funcs (5/5)

* Loosen

* Add missing typing

* Fix imports

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Restore typing + stricter

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-22 15:49:03 +03:00
Aidan Timson
b3cf298b2d Improve typing on lifestyle functions for changed props (3/5) (#51667)
* Split typing-common-funcs (3/5)

* Fix

* Apply suggestions from code review

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Loosen

* Loosen

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-22 15:47:55 +03:00
Aidan Timson
278195de04 Improve typing on lifestyle functions for changed props (2/5) (#51665)
* Split typing-common-funcs (2/5)

* Fix

* Fix

* Fix

* Restore original
2026-04-22 15:46:45 +03:00
Paulus Schoutsen
579b7bf568 Update name and look and feel of Serial Port Selector (#51655)
* Auto-refresh serial ports every 5s in serial selector

Schedules the next fetch via setTimeout once the previous response
resolves, so slow responses don't stack requests. Refreshing is
stopped when the element is disconnected and restarted on reconnect.

* Refresh serial ports only while picker dropdown is open

Emit a picker-opened event from ha-generic-picker and use it in the
serial selector to drive a 5s refresh loop that only runs while the
dropdown is open. The initial load still happens on firstUpdated so
the dropdown has data when the user opens it.

* Allow refreshing picker items while dropdown is open

ha-picker-combo-box caches its items on first update, so the serial
selector's auto-refresh had no effect while the dropdown was open.
Add a public refreshItems() method to re-run getItems and update the
visible list, expose it through ha-generic-picker, and call it from
the serial selector after each refresh.

* Format with prettier

* Categorize serial ports and improve item display

Group ports by type in the serial selector dropdown — integration-provided
(URI-schemed like esphome://), USB (vid/pid), built-in, and unnamed local
ports — with a section header and filter chip for each. Within each section
items are sorted by product name, and unnamed ports (no description or
manufacturer) fall to the last section so they only appear when they
actually exist, which is mostly in dev environments.

Item display now leads with the product description and manufacturer; the
device path, vid:pid, and serial number move to a less prominent secondary
line. ESPHome entries show the ESPHome logo, other integration-provided
ports get a generic connection icon, USB ports a USB icon, and embedded
ports a memory chip icon.

* Rename Unnamed serial port category to Other

* Rename serial selector to serial_port selector

Updated the selector key from `serial` to `serial_port`, renamed the
class to HaSerialPortSelector / SerialPortSelector and the custom
element to `ha-selector-serial_port`, moved translations under
`ui.components.selectors.serial_port`, and renamed the file to
`ha-selector-serial-port.ts`.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-22 08:29:56 -04:00
Aidan Timson
b6edecb888 Improve typing on lifestyle functions for changed props (4/5) (#51668)
* Split typing-common-funcs (4/5)

* Loosen

* Fix

* Fix

* Fix

* Restore
2026-04-22 15:16:57 +03:00
renovate[bot]
c7972e1c1f Update dependency lodash.template to v4.18.0 [SECURITY] (#51348)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-22 14:01:24 +03:00
Aidan Timson
442d7fe3b4 Improve typing on lifestyle functions for changed props (1/5) (#51664)
* Split typing-common-funcs (1/5)

* Fix
2026-04-22 13:37:22 +03:00
karwosts
ffcddf556d Consider entity precision in adjust-sum dialog (#51659)
* Consider entity precision in adjust sum dialog

* Adjust step selector
2026-04-22 08:08:49 +03:00
karwosts
0d3900f2cf Stop keydown events propagating from ha-textarea (#51661) 2026-04-22 08:07:21 +03:00
renovate[bot]
37b14a68b2 Update dependency @codemirror/view to v6.41.1 (#51660)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-22 08:03:41 +03:00
João Palmeiro
10e8189d5b Fix focus ring for HaFilterChip (#51657) 2026-04-21 19:24:28 +00:00
renovate[bot]
365b54b4fd Update dependency marked to v18.0.2 (#51653)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-21 17:14:37 +03:00
Jeremy Cook
b5a479b07e Add use_entity_picture option to picture-entity card (#51553)
* Add use_entity_picture option to picture-entity card

Allow picture-entity cards to display the entity's entity_picture attribute instead of requiring a manually configured image URL. This is particularly useful for entities that dynamically set their entity_picture (e.g., update entities showing component logos, custom integrations, etc.).

The static image configuration remains as a fallback when the entity_picture attribute is not present or when use_entity_picture is not enabled.

Changes:
- Add use_entity_picture boolean option to PictureEntityCardConfig
- Implement logic to check entity_picture attribute when enabled
- Update validation to accept use_entity_picture as valid image source
- Add editor toggle with helper text
- Add translation strings for the new option

* Rename use_entity_picture to show_entity_picture and add entity_picture_local support

Address review feedback:
- Rename use_entity_picture to show_entity_picture to match tile card and badge naming
- Check entity_picture_local first before entity_picture, following tile card pattern
- Update all references in types, card implementation, editor, and translations

* Fix TypeScript error for entity_picture_local access

* Address review feedback - less technical formulation

* Drop unnecessary cast in picture-entity card

Widen stateObj to HassEntity so entity_picture_local is accessible
without an inline cast, matching the tile-card pattern.

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-21 09:22:06 +00:00
Wendelin
389ac06e35 Use home-assistant.io/socials (#51649) 2026-04-21 08:21:49 +00:00
MikeDev96
c8459eb781 Add paste above/below buttons in automation editor (#51495)
* Add paste above/below buttons in automation editor

* Removed paste above option and renamed paste below to paste

* Added shortcut hint to paste options
2026-04-21 09:27:11 +02:00
Aidan Timson
74fd7b61f1 Add missing actions permission to stale workflow (#51638)
* Add missing actions permission to stale workflow

* Prioritise oldest updated items

* Don't change ordering
2026-04-21 08:45:10 +03:00
renovate[bot]
5d32bf338b Update dependency eslint to v10.2.1 (#51648)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-21 08:44:10 +03:00
Stefan Agner
4848e939b4 Fix supervisor My redirects for Container installs (#51645)
The supervisor_* My redirects (supervisor_store, supervisor_addons,
supervisor_app, supervisor_addon, supervisor_add_addon_repository) had
no component gate, so on Container installations they silently
navigated to broken pages. Gate them on the hassio component and route
the missing-hassio case through the existing no_supervisor error
message, which now links directly to the installation docs.

Also remove the unreachable /hassio/_my_redirect/ fallback that was
left behind by the standalone hassio panel removal (#29132), and
update the no_supervisor string: Home Assistant Supervised is no
longer a supported installation method (see architecture discussion
home-assistant/architecture#1198), only Home Assistant OS.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 18:32:30 +02:00
Stefan Agner
23acfc729c Remove dead /hassio URL references (#51643)
The standalone hassio panel at /hassio was removed in #29132 and
replaced by the apps panel under /config/apps in #28245. A couple of
references to the old URL path were missed: a dead branch in the
quick-bar My-link builder and a /hassio/ startsWith check that kept
the configuration sidebar item highlighted.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 18:13:06 +02:00
Paul Bottein
93110b1d70 Fix section config not propagating to layout element (#51640) 2026-04-20 15:29:16 +02:00
Wendelin
541c112159 Automation add TCA: Auto-expand single floor values (#51639)
Auto-expand floor section if only one floor is present
2026-04-20 14:06:58 +02:00
Aidan Timson
84382fdf0d Support scrolling on heading cards (#51567)
* Clean

* Scrollable option

* Refactor

* Remove wrap

* Restore

* Show grab cursor when dragging

* Overflow handling

* Remove extra space on start and end item

* Shrink title

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>

* Increase min width of title, set var

* More specific

* Use 120px min on small layouts

* Try to fix sizing

* No unnessasary vars

* Format

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-20 14:00:12 +02:00
Marcin Bauer
591057b80d Tooltip styling and sidebar tooltips (#30386)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Wendelin <w@pe8.at>
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-20 11:37:48 +00:00
Wendelin
d220725e5b ha-switch webawesome (#51507) 2026-04-20 13:19:53 +02:00
renovate[bot]
fdb4de9aa8 Update dependency @rsdoctor/rspack-plugin to v1.5.9 (#51636)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-20 13:09:24 +03:00
Aidan Timson
c3b768c111 Allow for decimals in cover and valve favorites (#51633)
* Allow for decimals in cover and valve favorites

* Merge normalise functions
2026-04-20 12:43:38 +03:00
Wendelin
7d9874adfa Remove allow-mode-change in quick search (#51634)
Remove allow-mode-change attribute from ha-adaptive-dialog in QuickBar component
2026-04-20 12:33:29 +03:00
renovate[bot]
64ad41a533 Update Yarn to v4.14.1 (#51631)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-20 09:16:38 +03:00
renovate[bot]
520739dd0e Update formatjs monorepo (#51601)
* Update formatjs monorepo

* Fix types

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-20 06:07:59 +00:00
Aidan Timson
30f70e179a Fix inconsistency with template binary sensors (#51486)
Fix inconsistency with template binary sensors with template options flow
2026-04-20 08:35:49 +03:00
Paulus Schoutsen
e66564ff65 Add apps group to navigation picker with all web UI addons (#51572)
* Add apps navigation group with ingress add-on panels

Add an "Apps" section to the navigation picker that shows all add-ons
with ingress support. Uses the /ingress/panels supervisor endpoint via
a cached collection to fetch add-on titles and icons in a single call.

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Fix no-shadow lint error for panels variable

Rename subscribe callback parameter from `panels` to `data` to avoid
shadowing the outer `panels` variable in _loadNavigationItems.

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Use subscribeOne helper for ingress panels collection

Replace hand-rolled Promise/subscribe/unsub pattern with the existing
subscribeOne utility for cleaner one-shot collection consumption.

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Add explicit type parameter to subscribeOne call

TypeScript cannot infer the generic type through the collection
subscribe chain, resulting in unknown type for panel entries.

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Add subscribeOneCollection helper for collection one-shot reads

Add a new subscribeOneCollection utility that takes a collection
directly instead of requiring the (conn, onChange) function pattern.
Use it in the navigation picker for cleaner ingress panel fetching.

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Use Collection type instead of custom Subscribable interface

https://claude.ai/code/session_01F8dUzfSWj8ZwDByVZ45BNj

* Add ingress panel support to subscribeNavigationPathInfo

* Use app panel variable

* Add tests

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-20 08:28:01 +03:00
Paulus Schoutsen
70ac14ed52 Allow disabling the maintenance summary from the home editor (#51622)
https://claude.ai/code/session_01FkRan4yxJzdjJJmjSRtoY1

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-20 08:27:14 +03:00
renovate[bot]
e0d881ff53 Update dependency marked to v18.0.1 (#51630)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-20 06:50:50 +02:00
Logan Rosen
61c0b7394e Remove core-only development checklist from PR template (#51624)
The PR template includes a checklist item linking to the development
checklist page, but that page only covers core/Python-specific items
(pypi, requirements_all.txt, CODEOWNERS, .strict-typing, Ruff). None
of these apply to the frontend repository.

No frontend-specific development checklist exists, so remove the item
entirely rather than link to irrelevant documentation. The "perfect PR
recommendations" checklist item already covers general PR best practices.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 06:50:33 +02:00
ildar170975
34b2509a76 Gauge card: fix a height in Horizontal stack (#51626)
remove styles for ":host"
2026-04-20 06:46:28 +02:00
renovate[bot]
7d03ef6dfc Update dependency typescript to v6.0.3 (#51628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-20 06:41:27 +02:00
renovate[bot]
96b59c6171 Update Yarn to v4.14.0 (#51621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-19 22:18:04 +02:00
renovate[bot]
7691d2ca4a Update dependency @codemirror/lang-jinja to v6.0.1 (#51618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-19 22:17:47 +02:00
Simon Lamon
da1c2bdee4 Adjust gauge again (#51613) 2026-04-19 08:55:54 +03:00
renovate[bot]
509443fbb2 Update dependency @bundle-stats/plugin-webpack-filter to v4.22.1 (#51610)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-18 09:02:13 +02:00
renovate[bot]
07992286b5 Update dependency prettier to v3.8.3 (#51611)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-18 09:01:52 +02:00
renovate[bot]
cf7274b0ba Update dependency @rsdoctor/rspack-plugin to v1.5.8 (#51605)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-17 18:53:54 +02:00
Paulus Schoutsen
501c72d203 Add config sub-routes to navigation picker (#51597)
Add Automations, Scenes, Scripts, Developer Tools, Integrations,
Devices, and Entities to the "Other routes" section of the navigation
picker. Also resolve these paths with proper labels and icons in
computeNavigationPathInfo so they display correctly everywhere
(shortcut cards, edit overview, etc.).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 08:20:03 +03:00
karwosts
a0ad488579 Fix gauge missing label on load (#51584) 2026-04-17 08:18:16 +03:00
renovate[bot]
ead2d1296f Update dependency hls.js to v1.6.16 (#51599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-17 07:09:15 +02:00
renovate[bot]
5ba5408e78 Update dependency typescript-eslint to v8.58.2 (#51600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-17 07:08:59 +02:00
Paulus Schoutsen
eecca1fa55 Add ESPHome logo (#51598) 2026-04-16 12:38:53 -04:00
Jeremy Cook
f2ba0fca73 Add per-section theme support (#29745)
* Add per-section theme support

* Fix linting errors: rename property parameter and use dot notation

* Fix TypeScript error: cast to any for __themes property

* Refactor theme application logic for race condition on first load, missing reconnect handling, and the fragile _applyTheme internals https://github.com/home-assistant/frontend/pull/29745

* correct formatting with prettier --write

* Fix theme application logic on reconnect by checking for theme configuration

* Pass section theme to background component for theme variable access

Section backgrounds now receive the section's theme and hass properties,
allowing them to apply the theme via applyThemesOnElement(). This enables
background components to access CSS variables from the section's theme,
particularly --ha-section-background-color when using the 'Default' color option.

Previously, the background component was rendered as a sibling to the section
element and couldn't access theme variables from the section's applied theme.
Now the theme is explicitly passed from hui-sections-view and applied to the
background component itself, making theme cascading work correctly.

* Reorder section settings: theme before background

* Add helper text support to theme selector

Theme selectors can now display helper text below the dropdown. Added helper property to ha-selector-theme and ha-theme-picker components, which is passed through to ha-select. Updated section theme label and added helper text to explain its purpose.

* Address PR review feedback: move theme to end and simplify label

- Move theme selector to end of form (after background section)
- Change label from 'Section theme' to 'Theme' as context is already clear

* Handle theme removal for background

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-16 15:20:08 +00:00
Paulus Schoutsen
fc448ab3a7 Add serial selector to initial form data (#51595)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 15:46:11 +01:00
Paul Bottein
9269c1ff0a Redesign lawn mower more info dialog (#51596) 2026-04-16 16:45:21 +02:00
Petar Petrov
b7dcbd559e Add hourly forecast card feature for weather entities (#51594) 2026-04-16 14:42:10 +01:00
Paul Bottein
80e0c098f8 Redesign vacuum more info dialog (#51380)
Co-authored-by: Claude <noreply@anthropic.com>
2026-04-16 14:11:07 +02:00
Aidan Timson
364c793ee6 Support suggested name and icon for dashboards, add to map (#51592) 2026-04-16 14:03:44 +02:00
Aidan Timson
99f36e1aad Refactor weather forecast card to scroll (#51580)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-16 11:42:06 +00:00
Aidan Timson
25dcaa4eb8 Device and browser environment for debug tools (#51568)
* Add viewpoer environment card to debug tools

* Move

* Cleanup

* Remove

* Remove scroll listener

* Update translation

* Output as yaml

* Apply suggestion

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Finish

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-16 13:32:29 +03:00
Wendelin
d92f7e14b4 ha-checkbox with webawesome (#51581)
* ha-checkbox with webawesome

* Fix checkboxes

* remove mwc-checkbox

* Copilot review

* Fix data table range checkbox select
2026-04-16 13:12:04 +03:00
renovate[bot]
2c1bf3369d Update Node.js to v24.15.0 (#51590)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-16 11:45:13 +03:00
Paulus Schoutsen
81d57cf43c Add SerialSelector (#51573)
* Add SerialSelector

* Address comments
2026-04-16 10:45:45 +03:00
Paulus Schoutsen
09053533ff Add custom pages summaries (#51506)
* Add custom pages to home page summaries

* Address comments

* Extract helper

* Update UI editor and use shortcut card

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-16 10:02:11 +03:00
Aidan Timson
7df61f239f Offset toast position, apply for automation/script editor (#51575)
* Alllow setting of toast position

* Switch to use offset

* Create wrapper for toast to offset with automation editor

* Use wrapper

* Add for clipboard pastes

* Make automation toasts dismissable

* Apply for script editor

* Rename
2026-04-16 09:57:06 +03:00
Paulus Schoutsen
f89eace462 Resolve add-on name and icon for shortcut card /app/ navigation (#51587)
* Resolve add-on name and icon for shortcut card /app/ navigation paths

When a shortcut card or badge navigates to /app/{slug}, fetch the add-on's
panel info (title and icon) from the supervisor ingress panels endpoint and
display it instead of the generic "app" panel fallback.

Adds a cached collection for ingress panel data (title and icon per add-on)
using getCollection, so the data is fetched once per connection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Simplify

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 09:41:36 +03:00
Wendelin
52956eefc6 ha-select allow number values (#51564) 2026-04-16 08:29:03 +02:00
Tom Carpenter
1fbbeba083 Correct statistic graph chart types to sentence case (#51579)
Correct statistic chart types to sentence case
2026-04-16 08:48:22 +03:00
Jan Čermák
4e0d2e290a Fix rendering of select with multiple options in SupervisorAppConfig (#51585)
If the app config contains a schema field like this one:

```
privileges:
  - "list(ALTER|CREATE|...|UPDATE)?"
```

it was rendered incorrectly as a drop-down where only one item can be
selected - but this is wrong because of the preceding `-` denoting it
should be a list containing the listed values. Supervisor translated
this to an entry of type `select` with `multiple: true`. The `multiple`
flag wasn't passed along, with the flag set the field renders as
expected.

Fixes #51533
2026-04-16 08:47:48 +03:00
Paulus Schoutsen
641773d5c4 Add Music Assistant icon (#51586)
* Add Music Assistant fallback domain icon

Add mdiMusic as the fallback icon for the music_assistant domain
in FALLBACK_DOMAIN_ICONS, so the integration has a proper icon
when dynamic icons are unavailable.

https://claude.ai/code/session_01GfNQCZL3dF1GXLRfhNRt25

* Revert "Add Music Assistant fallback domain icon"

This reverts commit 130d6eddee.

* Add Music Assistant logo as injectable mdi icon

Add the Music Assistant logo SVG as a special named icon, following
the same pattern as the Home Assistant logo (mdi:home-assistant).
This allows referencing mdi:music-assistant anywhere in the frontend
(e.g., add-on sidebar icon) and it resolves to the Music Assistant
logo SVG path.

https://claude.ai/code/session_01GfNQCZL3dF1GXLRfhNRt25

* Simplify logic to add more in future

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-15 19:28:20 -04:00
karwosts
3b53867216 Fix gauge segmentLabels, cleanup sorting (#51583) 2026-04-15 16:57:17 +03:00
Paul Bottein
7ea936088c Add shortcut badge (#51569)
* Add shortcut badge

* Fix label

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <norbert@rittel.de>

* Update card description

* Feedbacks

---------

Co-authored-by: Norbert Rittel <norbert@rittel.de>
2026-04-15 16:54:19 +03:00
Aidan Timson
4281240383 Add grab cursor to more info weather forecast (#51582) 2026-04-15 14:58:19 +02:00
Timothy
6b6203986d Increase height of HAInputSearch (#51576) 2026-04-15 13:53:55 +01:00
renovate[bot]
6997ffa580 Update dependency globals to v17.5.0 (#51574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-15 12:47:24 +03:00
Raphael Hehl
2d2558db40 Fix history/sensor cards stuck loading after backend restart (#51531)
* Fix history/sensor cards stuck loading after backend restart

- Add { resubscribe: false } to history subscriptions to prevent
  corrupt HistoryStream state on auto-resubscription
- Add connection-status handlers to re-subscribe on reconnect
- Add sentinel pattern to prevent re-entrant async subscriptions
- Add shouldUpdate/updated retry when components become available
- Clear sensor device classes cache on WS error
- Clear _error on reconnect so cards can retry
- Add .catch() on unsubscribe to handle dead subscriptions

* Fix type annotation for callWS in getSensorNumericDeviceClasses

* Address review: type connection-status handlers, add reconnect to history panel

- Use HASSDomEvent<ConnectionStatus> instead of (ev as CustomEvent).detail
  for proper type safety on all connection-status handlers
- Add connection-status handler to ha-panel-history so it re-subscribes
  after backend restart (addresses concern about resubscribe: false)

* Address review: sentinel pattern, reconnect handling, stale data reset

- Add sentinel pattern to ha-more-info-history, ha-panel-history,
  hui-history-graph-card to prevent re-entrant subscription races
- Refactor hui-trend-graph-card-feature from SubscribeMixin to manual
  subscription management with connection-status reconnect support
- Reset stale history/statistics data on reconnect in
  hui-history-graph-card and hui-map-card before re-subscribing
- Wrap fetchStatistics and getSensorNumericDeviceClasses calls in
  ha-panel-history with try/catch to handle errors gracefully
- Chain .catch directly on subscribeHistoryStatesTimeWindow in
  hui-trend-graph-card-feature to avoid detached-promise race condition

* Centralize history stream reconnect handling in data layer

Move the reconnect logic from every consumer into `subscribeHistoryStream`
in data/history.ts. The helper listens to the connection's `ready` event
itself, and on reconnect creates a fresh `HistoryStream` and rebuilds
params (so `start_time` for the time-window variant is re-anchored to
"now"). `resubscribe: false` stays as an internal implementation detail.

Removes the duplicated `_handleConnectionStatus` boilerplate and
`connection-status` window listeners from all six history consumers.

* Render subscription errors and make _error reactive

`_error` was declared as a plain string field in hui-graph-header-footer
and ha-more-info-history (non-reactive) and typed as Error/string while
being assigned the WS error object. hui-trend-graph-card-feature had it
reactive but never rendered it.

Align all three with the hui-history-graph-card pattern: reactive
`{ code, message }` and a user-visible error branch in render(). Without
this, a failed subscription would leave the component stuck on a spinner
forever.

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-15 11:34:13 +03:00
Paul Bottein
039fc45532 Add shortcut card (#51562)
* Add shortcut card

* Improve action support
2026-04-15 08:53:08 +03:00
renovate[bot]
209e6f8def Update dependency sinon to v21.1.2 (#51571)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-14 20:44:08 +02:00
Yosi Levy
f6a19eb6c4 Fix entity ID orientation in device editor (#51560)
* Fix entity ID orientation

* Apply suggestions from code review

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>

* Fix indentation in entity-registry-settings-editor.ts

---------

Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-14 17:49:39 +00:00
karwosts
ceb9967deb Make picture elements editor sortable (#51563)
* Make picture elements editor sortable

* Update src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Update src/panels/lovelace/editor/hui-picture-elements-card-row-editor.ts

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-04-14 15:00:07 +00:00
Tom Carpenter
b2015465fb Add stacked chart types to Statistics Graph Card (#51530)
* Add stacked mode to statistics-chart

Allows displaying the entries as stacked lines or stacked bars. This means we can create charts similar to the energy graph cards but with alternate entities.

* Move fillDataGapsAndRoundCaps to components/chart

Now used in statistics-chart too, so move to common chart location.
Re-export in energy-chart-options.ts to minimise changes throughout energy cards.

* Correct order of line/bar in statistics graph card editor

Line and Bar options were unintentionally reversed in the displayed list.

* Support unstacked bar charts in fillDataGapsAndRoundCaps
2026-04-14 17:45:47 +03:00
karwosts
8e4c99049f Adjust outlier detection algorithm when partial 5minute data exists (#51561) 2026-04-14 16:44:12 +03:00
Petar Petrov
5a5b8c0bbd Add controls option to media player playback card feature (#30338)
* Add controls option to media player playback card feature

Allow users to configure which playback controls are shown and in what
order. When controls are explicitly configured, each selected control
is rendered as its own button in the specified order. When no controls
are configured, the original default behavior is preserved.

Also adds a configuration editor for the feature and fixes inline
feature padding in the tile card container.

* Revert padding changes to ha-tile-container

* Use computeMediaControls for default playback buttons

Reuse the shared computeMediaControls function for the default (no
explicit controls) path instead of duplicating the logic. Apply the
narrow filter to both paths via a shared _filterNarrow method.
2026-04-14 16:29:57 +03:00
Petar Petrov
b60d189a69 Remove invalid dependabot cooldown option (#51558) 2026-04-14 10:28:35 +02:00
Aidan Timson
19ed00c677 Combine all entity modes card feature editors with shared base class (#51543)
* Combine all entity modes card feature editors with shared base class

* Remove hass from schema memo
2026-04-14 11:26:55 +03:00
Bram Kragten
b92775ea2d Improve code editors (#51555)
* Update YAML and Jinja code editor support, support Jinja in YAML

* add autocomplete for ha jinja functions

* Use snippets and better autocomplete for jinja

* Add autocomplete for devices

* Add area, floor, label autocomplete

* Add yaml scalar type highlighter

* Add autocomplete for `states` var

* Add autocomplete for attributes

* Make autocomplete work on id and name

* Add missing functions that can also be used as filter
2026-04-14 09:19:37 +03:00
renovate[bot]
b5bacf85dd Update dependency sinon to v21.1.1 (#51557)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-14 08:42:37 +03:00
Yosi Levy
8f4fe9ba4e Fix date picker header (#51552) 2026-04-13 22:02:36 +02:00
Wendelin
9179218336 Improve view footer card visibility handling (#51549) 2026-04-13 17:12:57 +02:00
JamesFromIT
274ec50dbd Make dialog title a semantic heading element (#51521)
* Make dialog title a semantic heading element

* Move away from inheriting everything from modal title parent

* Update src/dialogs/generic/dialog-box.ts

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
2026-04-13 12:38:31 +00:00
Wendelin
2629881a18 Hide footer if card is not visible (#51544)
* Fix footer visibility logic in render method

* use card-visibility-changed
2026-04-13 14:00:44 +02:00
dependabot[bot]
d7f143a65a Bump actions/github-script from 8.0.0 to 9.0.0 (#51539)
Bumps [actions/github-script](https://github.com/actions/github-script) from 8.0.0 to 9.0.0.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](ed597411d8...3a2844b7e9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 13:17:21 +02:00
Wendelin
9cce20bad1 Enhance sun condition automation: add 'between' option and improve duration formatting (#51502) 2026-04-13 11:58:20 +02:00
Aidan Timson
c9ad84b234 Register custom dashboard strategies (#51310)
* Allow custom dashboard strategies to register for the add dashboard dialog

Adds a window.customDashboardStrategies registration mechanism (mirroring
window.customCards) so third-party strategies can appear in the new dashboard
picker. Only dashboard-level strategies are surfaced; view and section
strategies are excluded. Custom strategies appear in their own section and
are included in search results.

https://claude.ai/code/session_019MXBdWUQrFQfH54QVjbq8y

* Rename custom dashboards heading to community dashboards

https://claude.ai/code/session_019MXBdWUQrFQfH54QVjbq8y

* Consolidate into a single customStrategies registry for all strategy types

The window.customStrategies array now accepts entries with a strategyType
field (dashboard, view, or section). The dialog filters for dashboard
strategies. This allows future use of the same registry for view and
section strategy registration.

https://claude.ai/code/session_019MXBdWUQrFQfH54QVjbq8y

* Space tokens

* Space tokens

* Add support for images

* Allow single image from custom strategy

* Load needed resources for new dashboard dialog

* Preload custom strategies

* Catch potential error

* Reset if error

* Improve typing

* Cache module resources to avoid duplicate loads

* Revert "Cache module resources to avoid duplicate loads"

This reverts commit 87bbcc0451.

* Set a max height for dashboard images (match max height of current core images)

* Remove image support

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-13 11:57:59 +02:00
Wendelin
cb89b8aea8 Use wa-tag for target picker chips (#51482) 2026-04-13 11:57:46 +02:00
dependabot[bot]
a5f4885d95 Bump home-assistant/actions from 5752577ea7cc5aefb064b0b21432f18fe4d6ba90 to f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b (#51535)
Bump home-assistant/actions

Bumps [home-assistant/actions](https://github.com/home-assistant/actions) from 5752577ea7cc5aefb064b0b21432f18fe4d6ba90 to f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b.
- [Release notes](https://github.com/home-assistant/actions/releases)
- [Commits](5752577ea7...f6f29a7ee3)

---
updated-dependencies:
- dependency-name: home-assistant/actions
  dependency-version: f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 11:08:45 +02:00
Aidan Timson
e2e114cb4e Add shared editor for all more info hints, add lights (#51542)
* Add more info redirect editor for light favorites

* Merge all hint feature editors to one shared component

* Fix
2026-04-13 11:07:55 +02:00
dependabot[bot]
4a0284455d Bump pypa/gh-action-pypi-publish from 1.13.0 to 1.14.0 (#51537)
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.13.0 to 1.14.0.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](ed0c53931b...cef221092e)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-version: 1.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 11:06:10 +02:00
JamesFromIT
d220eba9f7 Make history page title a semantic heading (#51527) 2026-04-13 08:39:50 +00:00
Paul Bottein
2edb0325aa Improve box shadow design tokens with multi-layer shadows (#51378) 2026-04-13 10:36:17 +02:00
dependabot[bot]
2e1582a9c1 Bump actions/upload-artifact from 7.0.0 to 7.0.1 (#51538)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 09:36:01 +01:00
dependabot[bot]
006cdf088a Bump release-drafter/release-drafter from 7.1.1 to 7.2.0 (#51536)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 09:35:46 +01:00
Bram Kragten
f7e92b484a Bumped version to 20260325.7 2026-04-10 17:44:15 +02:00
Aidan Timson
9fab7bafdb Allow quick search for non-admins, while hiding inaccessible areas (#51456)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-10 17:40:25 +02:00
Petar Petrov
0dabb02007 Fix dialog show animation broken by connectedCallback _open sync (#51450) 2026-04-10 17:38:06 +02:00
Petar Petrov
5b73e86786 Fix toast race condition causing stuck notifications (#51447) 2026-04-10 17:38:05 +02:00
Timothy
144d7c5c3f Android externalAppV2 (#51446) 2026-04-10 17:37:08 +02:00
Petar Petrov
8b396dc640 Preserve browser back/forward keyboard shortcuts in tab group (#51439) 2026-04-10 17:33:34 +02:00
Aidan Timson
9bf48d30ab Handle lazy loaded entity registry when editing scripts from more info (#51438)
* Handle lazy loaded entity registry when editing scripts from more info

* Remove extra check

* Fix type of mixin
2026-04-10 17:33:33 +02:00
GeorgeZ83
35fee46f5b Fix media browser dialog window (#51423)
Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
2026-04-10 17:33:32 +02:00
Niccolò Betto
9ac6636029 Fix code input dialog undefined value concatenation (#51399) 2026-04-10 17:33:31 +02:00
Simon Lamon
136462114d Increase gauge thickness for accessibility reasons (#51382)
Increase thickness for accessability reasons
2026-04-10 17:33:30 +02:00
Bram Kragten
cf542197e0 Bumped version to 20260325.6 2026-04-03 13:01:51 +02:00
Bram Kragten
5c2627624a Always add options object to triggers and conditions (#51394) 2026-04-03 13:01:42 +02:00
Petar Petrov
698ded9d85 Only use inflight map for pending fragment translation loads (#51393) 2026-04-03 13:01:42 +02:00
Tim Ittermann
9a7fb96873 fix: null value error on ha-form-integer (#51385)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2026-04-03 13:01:41 +02:00
Petar Petrov
204c5b5e14 Fix fragment translation race condition returning stale localize (#51381) 2026-04-03 13:01:40 +02:00
Petar Petrov
8ea3acfa98 Load energy translations in dashboard strategy before generating view titles (#51376) 2026-04-03 13:01:39 +02:00
Wendelin
306739773e Fix login on legacy browsers (#51373) 2026-04-03 13:01:38 +02:00
Petar Petrov
8b3fa3adac Fix next_flow dialog closing immediately after rendering (#51369) 2026-04-03 13:01:37 +02:00
Petar Petrov
37a1d59a24 Fix statistics-graph card not rendering self-imported stats (#51367) 2026-04-03 13:01:37 +02:00
Trevin Chow
6812884e00 Guard against orphaned label references in device list (#51359) 2026-04-03 13:01:36 +02:00
Trevin Chow
bf7ef1f7ae Fix TypeError in Voice Assistants expose page with manual entity filters (#51357) 2026-04-03 13:01:35 +02:00
Paul Bottein
fe57f601ba Fix device page entity names not refreshing after device rename (#51355) 2026-04-03 13:01:34 +02:00
Wendelin
c89d478440 Fix input hint height (#51351) 2026-04-03 13:01:33 +02:00
Petar Petrov
fa27d26e5f Fix history-graph card not showing first value (#51350) 2026-04-03 13:01:32 +02:00
Wendelin
18f411ef53 Fix generic picker filter section padding (#51334)
Fix padding in picker section for improved layout
2026-04-03 13:01:31 +02:00
Wendelin
24826e92f0 Fix picker search padding (#51331) 2026-04-03 13:01:30 +02:00
Wendelin
ea9d369d88 Fix date input field shrink (#51330) 2026-04-03 13:01:29 +02:00
Bram Kragten
a9b026d0ef Bumped version to 20260325.5 2026-04-01 11:15:10 +02:00
Petar Petrov
35339906ec Fix layout of compare card in water/gas views (#51329) 2026-04-01 11:14:50 +02:00
Wendelin
ce23f716cc Improve dialog open logic (#51328) 2026-04-01 11:14:49 +02:00
Petar Petrov
aaf8fa199f Await energy translation fragment before generating dashboard strategy (#51327) 2026-04-01 11:14:48 +02:00
Aidan Timson
fba430d507 Fix target item loading error (#51326) 2026-04-01 11:14:47 +02:00
Petar Petrov
59361cbd38 Fix ZHA device count not including devices without entities (#51322) 2026-04-01 11:14:46 +02:00
Petar Petrov
b558117d8c Use ha-card-border-color for integration cards instead of divider-color (#51321) 2026-04-01 11:14:45 +02:00
Petar Petrov
a7c8347751 Fix Fill example data inserting incorrect datetime format (#51320) 2026-04-01 11:14:44 +02:00
Wendelin
31ca9c849a Remove target description (#51315) 2026-04-01 11:14:43 +02:00
Bram Kragten
6252d7e8f5 Bumped version to 20260325.4 2026-03-31 15:36:46 +02:00
Bram Kragten
f42986adf6 Make translation downloading async (#51314) 2026-03-31 15:36:31 +02:00
Bram Kragten
9e70ea3723 Bumped version to 20260325.3 2026-03-31 14:58:38 +02:00
Bram Kragten
de3b7bf513 Fix has target check for actions (#51309) 2026-03-31 14:58:19 +02:00
Petar Petrov
2c5f491c9e Use boundaryFilter data zoom mode only for line charts (#51307) 2026-03-31 14:58:18 +02:00
Wendelin
1ef13c5100 Fix automation add TCA dialog sometimes not opening (#51306) 2026-03-31 14:58:17 +02:00
Aidan Timson
c166335aca Fix above/below numeric state entity formatting (#51298) 2026-03-31 14:51:11 +02:00
Petar Petrov
c64ec21eca Fix x-axis labels for statistics graph month/year periods (#51295) 2026-03-31 14:51:10 +02:00
Norbert Rittel
8d62056f4a Change picker descriptions of triggers to match new style (#51294) 2026-03-31 14:51:09 +02:00
Bram Kragten
62e73608b6 Triggers/conditions Add usage and grouping to new multi domains (#51287) 2026-03-31 14:51:08 +02:00
Wendelin
aa66d8891c Improve date-range-picker mobile presets (#51285) 2026-03-31 14:51:07 +02:00
Paul Bottein
494a96c635 Hide section when all cards are hidden (#51281) 2026-03-31 14:51:06 +02:00
Petar Petrov
36d77f54ce Disable physics by default for large networks (#51277) 2026-03-31 14:51:05 +02:00
Wendelin
12fec9f580 Fix ha-dropdown z-index for legacy browsers (#51276) 2026-03-31 14:51:04 +02:00
Bram Kragten
5f1f55448a Numeric threshold selector: remove duplicate uom from input (#51275) 2026-03-31 14:51:03 +02:00
Paul Bottein
837e345ecf Reduce heading button badge font size and fix alignement (#51274)
Title: Reduce heading button badge font size and fix alignement
2026-03-31 14:51:02 +02:00
Wendelin
0929d7d18a Remove mobile-specific styles for date-range-picker (#51273)
Remove mobile-specific styles for date-picker component
2026-03-31 14:51:01 +02:00
Aidan Timson
70991d3c1e Limit ha-toast width to window, refactor CSS (#51272)
* Limit `ha-toast` width to window and use safe width

* Query assigned slots to stop actions display

* Constrain max-width

* Increase start/end padding
2026-03-31 14:51:00 +02:00
Wendelin
82e5bd62a1 Fix time input background (#51270)
Fix input color tokens
2026-03-31 14:50:59 +02:00
Wendelin
b8adf4e866 Fix date-range-picker preset selection (#51269) 2026-03-31 14:50:58 +02:00
Tom Carpenter
111be984e0 Add date range picker time validation (#51267)
* Fix base time inputs reportValidity() function

The queryAll selector returns a NodeList not not an array. Need to spread it to an array before we can use every().

* Validate the date range picker time inputs

Enable auto validation to get the nice red underline on invalid values, and then check validity before accepting the input.

* Fix automatic 24hr value conversion in AM/PM format

When using AM/PM, entering a 24 hour value will automatically convert the first time. For example 15 will become 3. However if you then enter 15 again it will stay as 15 and not update.
To fix this, make sure we trigger an update of the input field once the current update cycle is complete.

* Validate time inputs on save not value update

In the value changed callback, the update 24->12hr input correction will not have been updated and therefore they will report invalid.
2026-03-31 14:50:57 +02:00
Tom Carpenter
78a2cbb532 Fix new date-range-picker rendering on small screens (#51257) 2026-03-31 14:50:56 +02:00
ildar170975
34b09b140b Map card editor: use context in attribute selector (#30393)
use context in attribute selector
2026-03-31 14:50:55 +02:00
Simon Lamon
f173f901c5 Gauge improvements (#30368)
* Gauge last improvements

* Change needle

* Fixup

* Feedback comments

* Update src/components/ha-gauge.ts

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
2026-03-31 14:50:55 +02:00
Paul Bottein
ebb6ac8d8b Bumped version to 20260325.2 2026-03-27 22:09:10 +01:00
Wendelin
abe214a33a Fix picker field disabled background (#30385) 2026-03-27 22:08:51 +01:00
Paul Bottein
248332ae27 Revert entity naming change (#30384) 2026-03-27 22:08:50 +01:00
Wendelin
82fc2fccdc Automation add TCA: Fix classMap usage (#30380) 2026-03-27 22:08:49 +01:00
Marcin Bauer
c8f30a7ee4 Use dedicated tab copy in automation add dialogs (#30378)
Co-authored-by: Wendelin <w@pe8.at>
2026-03-27 22:08:48 +01:00
Norbert Rittel
77f48d91cd Shorten collection_key_description to fit available space (#30376) 2026-03-27 22:08:47 +01:00
Paul Bottein
caa707a7b1 Only display entity name instead of friendly name in state info (#30365) 2026-03-27 22:08:46 +01:00
Petar Petrov
0bed0fa37e Fix negative currency display on sensor card (#30359) 2026-03-27 22:08:46 +01:00
Bram Kragten
5b6309d984 Numeric threshold selector fixes (#30350)
* Update numeric threshold

* Update ha-selector-numeric-threshold.ts
2026-03-27 22:08:45 +01:00
Aidan Timson
264818bc70 Fix floating ha-toast (#30344) 2026-03-27 22:08:44 +01:00
Bram Kragten
d664ab6836 Bumped version to 20260325.1 2026-03-26 17:08:11 +01:00
Bram Kragten
a6c4184054 Replace ua-parser-js with simple regexs (#30355) 2026-03-26 17:07:45 +01:00
karwosts
cb6985eb7c Stabilize map colors (#30354) 2026-03-26 17:07:44 +01:00
Bram Kragten
d466ab63bd Add target error badge if target is missing (#30352)
* Add target error badge if target is missing

* Don't show for newly added items
2026-03-26 17:07:40 +01:00
Paul Bottein
1132cdb364 Replace computeLovelaceEntityName with hass.formatEntityName (#30351) 2026-03-26 17:07:39 +01:00
Paul Bottein
0f9d48a03d Use hardcoded label for temperature and humidity sensor in climate dashboard (#30348)
* Only use entity name for climate view sensors

* Use hardcoded text
2026-03-26 17:07:38 +01:00
Paul Bottein
7e085d9b08 Fix stack card scrollbar clipping box-shadows (#30346)
* Fix stack card scrollbar clipping box-shadows

* Remove grid options

* Remove scrollbar
2026-03-26 17:07:37 +01:00
Timothy
1a62c7296c Set tap highlight color to transparent for button (#30340) 2026-03-26 17:07:36 +01:00
Petar Petrov
be1921229c Fix energy pie chart legend showing raw data instead of formatted values (#30339) 2026-03-26 17:07:34 +01:00
Paul Bottein
640558ad35 Add composed/text mode toggle to entity name picker (#30337) 2026-03-26 17:07:33 +01:00
sir-Unknown
99636c9719 Fix calendar event description not preserving line breaks (#30329)
Add `white-space: pre-line` to the event description style so that
newlines in the calendar event description are rendered correctly
instead of being collapsed into a single line.
2026-03-26 17:07:32 +01:00
864 changed files with 24613 additions and 9484 deletions

View File

@@ -69,7 +69,6 @@
- [ ] I understand the code I am submitting and can explain how it works.
- [ ] The code change is tested and works locally.
- [ ] There is no commented out code in this PR.
- [ ] I have followed the [development checklist][dev-checklist]
- [ ] I have followed the [perfect PR recommendations][perfect-pr]
- [ ] Any generated code has been carefully reviewed for correctness and compliance with project standards.
@@ -105,6 +104,5 @@ To help with the load of incoming pull requests:
Below, some useful links you could explore:
-->
[dev-checklist]: https://developers.home-assistant.io/docs/development_checklist/
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr

View File

@@ -6,7 +6,6 @@ updates:
interval: weekly
time: "06:00"
cooldown:
default-days-before-reopen: 30
default-days: 7
open-pull-requests-limit: 10
labels:

View File

@@ -30,7 +30,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -66,7 +66,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn

View File

@@ -31,7 +31,7 @@ jobs:
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -42,7 +42,7 @@ jobs:
- name: Build resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
- name: Setup lint cache
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: |
node_modules/.cache/prettier
@@ -67,7 +67,7 @@ jobs:
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -87,7 +87,7 @@ jobs:
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -98,13 +98,13 @@ jobs:
env:
IS_TEST: "true"
- name: Upload bundle stats
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-bundle-stats
path: build/stats/*.json
if-no-files-found: error
- name: Upload frontend build
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: frontend-build
path: hass_frontend/

View File

@@ -41,14 +41,14 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -62,4 +62,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2

View File

@@ -31,7 +31,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -67,7 +67,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn

View File

@@ -24,7 +24,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn

View File

@@ -29,7 +29,7 @@ jobs:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn

View File

@@ -30,7 +30,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
cache: yarn
@@ -59,14 +59,14 @@ jobs:
run: tar -czvf translations.tar.gz translations
- name: Upload build artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: wheels
path: dist/home_assistant_frontend*.whl
if-no-files-found: error
- name: Upload translations
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: translations
path: translations.tar.gz

View File

@@ -18,6 +18,6 @@ jobs:
pull-requests: read
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@139054aeaa9adc52ab36ddf67437541f039b88e2 # v7.1.1
- uses: release-drafter/release-drafter@5de93583980a40bd78603b6dfdcda5b4df377b32 # v7.2.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -36,10 +36,10 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Verify version
uses: home-assistant/actions/helpers/verify-version@5752577ea7cc5aefb064b0b21432f18fe4d6ba90 # master
uses: home-assistant/actions/helpers/verify-version@f6f29a7ee3fa0eccadf3620a7b9ee00ab54ec03b # master
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
@@ -58,7 +58,7 @@ jobs:
script/release
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
skip-existing: true
@@ -104,7 +104,7 @@ jobs:
with:
persist-credentials: false
- name: Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: ".nvmrc"
- name: Install dependencies

View File

@@ -22,7 +22,7 @@ jobs:
|| github.event.issue.type.name == 'Opportunity'
steps:
- name: Add no-stale label
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
await github.rest.issues.addLabels({
@@ -41,7 +41,7 @@ jobs:
if: github.event.issue.type.name == 'Task'
steps:
- name: Check if user is authorized
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const issueAuthor = context.payload.issue.user.login;

View File

@@ -6,6 +6,7 @@ on:
- cron: "0 * * * *"
permissions:
actions: write
issues: write
pull-requests: write

2
.nvmrc
View File

@@ -1 +1 @@
24.14.1
24.15.0

File diff suppressed because one or more lines are too long

View File

@@ -8,4 +8,4 @@ enableGlobalCache: false
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.13.0.cjs
yarnPath: .yarn/releases/yarn-4.14.1.cjs

View File

@@ -12,7 +12,7 @@ const TerserPlugin = require("terser-webpack-plugin");
const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
const log = require("fancy-log");
// eslint-disable-next-line @typescript-eslint/naming-convention
const WebpackBar = require("webpackbar/rspack");
const SafeWebpackBar = require("./safe-webpackbar.cjs");
const paths = require("./paths.cjs");
const bundle = require("./bundle.cjs");
@@ -126,7 +126,7 @@ const createRspackConfig = ({
},
},
plugins: [
!isStatsBuild && new WebpackBar({ fancy: !isProdBuild }),
!isStatsBuild && new SafeWebpackBar({ fancy: !isProdBuild }),
new WebpackManifestPlugin({
// Only include the JS of entrypoints
filter: (file) => file.isInitial && !file.name.endsWith(".map"),

View File

@@ -0,0 +1,25 @@
// eslint-disable-next-line @typescript-eslint/naming-convention
const WebpackBar = require("webpackbar/rspack");
// Rspack 2's ProgressPlugin passes the third `info` arg as
// `{ builtModules, moduleIdentifier? }` instead of the v1 string. webpackbar@7's
// parseRequest still expects a string and crashes on `split`. Extract
// moduleIdentifier (the v1 equivalent) so progress still shows the active module.
class SafeWebpackBar extends WebpackBar {
constructor(options) {
super(options);
const inner = this.webpackbar;
const originalUpdate = inner.updateProgress.bind(inner);
inner.updateProgress = (percent, message, details = []) =>
originalUpdate(
percent,
message,
details.map((d) => {
if (typeof d === "string") return d;
return d?.moduleIdentifier ?? "";
})
);
}
}
module.exports = SafeWebpackBar;

View File

@@ -1,7 +1,7 @@
import type { ActionDetail } from "@material/mwc-list/mwc-list";
import { mdiCast, mdiCastConnected, mdiViewDashboard } from "@mdi/js";
import type { Auth, Connection } from "home-assistant-js-websocket";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { LitElement, css, html } from "lit";
import { customElement, property, state } from "lit/decorators";
import type { CastManager } from "../../../../src/cast/cast_manager";
@@ -150,7 +150,7 @@ class HcCast extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const llColl = atLeastVersion(this.connection.haVersion, 0, 107)
@@ -183,7 +183,7 @@ class HcCast extends LitElement {
});
}
protected updated(changedProps) {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
toggleAttribute(
this,

View File

@@ -12,7 +12,7 @@ import {
ERR_INVALID_HTTPS_TO_HTTP,
getAuth,
} from "home-assistant-js-websocket";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";
import type { CastManager } from "../../../../src/cast/cast_manager";
@@ -158,7 +158,7 @@ export class HcConnect extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
import("./hc-cast");

View File

@@ -1,6 +1,6 @@
import type { Auth, Connection, HassUser } from "home-assistant-js-websocket";
import { getUser } from "home-assistant-js-websocket";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -53,7 +53,7 @@ class HcLayout extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
if (this.connection) {

View File

@@ -1,3 +1,4 @@
import type { PropertyValues } from "lit";
import { html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mockHistory } from "../../../../demo/src/stubs/history";
@@ -29,7 +30,7 @@ class HcDemo extends HassElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
this._initializeHass();
}
@@ -41,7 +42,7 @@ class HcDemo extends HassElement {
this._updateHass(hassUpdate),
};
const hass = (this.hass = provideHass(this, initial));
const hass = provideHass(this, initial, true);
mockHistory(hass);

View File

@@ -1,4 +1,5 @@
import { css, html, LitElement, type TemplateResult } from "lit";
import type { PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import type { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
@@ -64,7 +65,7 @@ class HcLovelace extends LitElement {
`;
}
protected updated(changedProps) {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
if (changedProps.has("viewPath") || changedProps.has("lovelaceConfig")) {

View File

@@ -1,6 +1,6 @@
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import { createConnection, getAuth } from "home-assistant-js-websocket";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { html } from "lit";
import { customElement, state } from "lit/decorators";
import { CAST_NS } from "../../../../src/cast/const";
@@ -106,7 +106,7 @@ export class HcMain extends HassElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
import("./hc-lovelace");
import("../../../../src/resources/append-ha-style");

View File

@@ -1,5 +1,6 @@
/// <reference types="chromecast-caf-sender" />
import { mdiTelevision } from "@mdi/js";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, state } from "lit/decorators";
import type { CastManager } from "../../../src/cast/cast_manager";
@@ -37,7 +38,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
import("../../../src/cast/cast_manager").then(({ getCastManager }) =>
getCastManager().then((mgr) => {
@@ -62,7 +63,7 @@ class CastDemoRow extends LitElement implements LovelaceRow {
);
}
protected updated(changedProps) {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
this.style.display = this._castManager ? "" : "none";
}

View File

@@ -1,4 +1,4 @@
import type { CSSResultGroup } from "lit";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { until } from "lit/directives/until";
@@ -102,7 +102,7 @@ export class HADemoCard extends LitElement implements LovelaceCard {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
if (this._hidden) {
this.style.display = "none";

View File

@@ -39,7 +39,7 @@ export class HaDemo extends HomeAssistantAppEl {
this._updateHass(hassUpdate),
};
const hass = (this.hass = provideHass(this, initial));
const hass = provideHass(this, initial, true);
const localizePromise =
// @ts-ignore
this._loadFragmentTranslations(hass.language, "page-demo").then(

View File

@@ -1,4 +1,5 @@
import type { LocalizeFunc } from "../../../src/common/translations/localize";
import type { LovelaceInfo } from "../../../src/data/lovelace/resource";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import {
selectedDemoConfig,
@@ -27,6 +28,9 @@ export const mockLovelace = (
);
});
hass.mockWS("lovelace/info", () =>
Promise.resolve({ resource_mode: "storage" } as LovelaceInfo)
);
hass.mockWS("lovelace/config/save", () => Promise.resolve());
hass.mockWS("lovelace/resources", () => Promise.resolve([]));
hass.mockWS("lovelace/dashboards/list", () => Promise.resolve([]));

View File

@@ -15,7 +15,6 @@ import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
const generateMeanStatistics = (
start: Date,
end: Date,
// eslint-disable-next-line default-param-last
period: "5minute" | "hour" | "day" | "month" = "hour",
maxDiff: number
): StatisticValue[] => {
@@ -49,7 +48,6 @@ const generateMeanStatistics = (
const generateSumStatistics = (
start: Date,
end: Date,
// eslint-disable-next-line default-param-last
period: "5minute" | "hour" | "day" | "month" = "hour",
initValue: number,
maxDiff: number
@@ -86,7 +84,6 @@ const generateSumStatistics = (
const generateCurvedStatistics = (
start: Date,
end: Date,
// eslint-disable-next-line default-param-last
_period: "5minute" | "hour" | "day" | "month" = "hour",
initValue: number,
maxDiff: number,

View File

@@ -1,58 +1,56 @@
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockSensor = (hass: MockHomeAssistant) => {
hass.mockWS("sensor/numeric_device_classes", () => [
{
numeric_device_classes: [
"volume_storage",
"gas",
"data_size",
"irradiance",
"wind_speed",
"volatile_organic_compounds",
"volatile_organic_compounds_parts",
"voltage",
"frequency",
"precipitation_intensity",
"volume",
"precipitation",
"battery",
"nitrogen_dioxide",
"speed",
"signal_strength",
"pm1",
"nitrous_oxide",
"atmospheric_pressure",
"data_rate",
"temperature",
"power_factor",
"aqi",
"current",
"volume_flow_rate",
"humidity",
"duration",
"ozone",
"distance",
"pressure",
"pm25",
"weight",
"energy",
"carbon_monoxide",
"apparent_power",
"illuminance",
"energy_storage",
"moisture",
"power",
"water",
"carbon_dioxide",
"ph",
"reactive_power",
"monetary",
"nitrogen_monoxide",
"pm10",
"sound_pressure",
"sulphur_dioxide",
],
},
]);
hass.mockWS("sensor/numeric_device_classes", () => ({
numeric_device_classes: [
"volume_storage",
"gas",
"data_size",
"irradiance",
"wind_speed",
"volatile_organic_compounds",
"volatile_organic_compounds_parts",
"voltage",
"frequency",
"precipitation_intensity",
"volume",
"precipitation",
"battery",
"nitrogen_dioxide",
"speed",
"signal_strength",
"pm1",
"nitrous_oxide",
"atmospheric_pressure",
"data_rate",
"temperature",
"power_factor",
"aqi",
"current",
"volume_flow_rate",
"humidity",
"duration",
"ozone",
"distance",
"pressure",
"pm25",
"weight",
"energy",
"carbon_monoxide",
"apparent_power",
"illuminance",
"energy_storage",
"moisture",
"power",
"water",
"carbon_dioxide",
"ph",
"reactive_power",
"monetary",
"nitrogen_monoxide",
"pm10",
"sound_pressure",
"sulphur_dioxide",
],
}));
};

View File

@@ -2,10 +2,7 @@
import unusedImports from "eslint-plugin-unused-imports";
import globals from "globals";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import { configs as litConfigs } from "eslint-plugin-lit";
@@ -14,35 +11,8 @@ import { configs as a11yConfigs } from "eslint-plugin-lit-a11y";
import html from "@html-eslint/eslint-plugin";
import importX from "eslint-plugin-import-x";
const _filename = fileURLToPath(import.meta.url);
const _dirname = path.dirname(_filename);
const compat = new FlatCompat({
baseDirectory: _dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
// Load airbnb-base via FlatCompat for non-import rules only.
// eslint-plugin-import is incompatible with ESLint 10 (uses removed APIs),
// so we strip its plugin/rules/settings and use eslint-plugin-import-x instead.
const airbnbConfigs = compat.extends("airbnb-base").map((config) => {
const { plugins = {}, rules = {}, settings = {}, ...rest } = config;
return {
...rest,
plugins: Object.fromEntries(
Object.entries(plugins).filter(([key]) => key !== "import")
),
rules: Object.fromEntries(
Object.entries(rules).filter(([key]) => !key.startsWith("import/"))
),
settings: Object.fromEntries(
Object.entries(settings).filter(([key]) => !key.startsWith("import/"))
),
};
});
export default tseslint.config(
...airbnbConfigs,
js.configs.recommended,
eslintConfigPrettier,
litConfigs["flat/all"],
tseslint.configs.recommended,
@@ -86,35 +56,59 @@ export default tseslint.config(
},
rules: {
"class-methods-use-this": "off",
"new-cap": "off",
"prefer-template": "off",
"object-shorthand": "off",
"func-names": "off",
"no-underscore-dangle": "off",
strict: "off",
"no-plusplus": "off",
"no-bitwise": "error",
"comma-dangle": "off",
"vars-on-top": "off",
"no-continue": "off",
"no-param-reassign": "off",
"no-multi-assign": "off",
"no-console": "error",
radix: "off",
"no-alert": "off",
"no-nested-ternary": "off",
"prefer-destructuring": "off",
"no-restricted-globals": [2, "event"],
"prefer-promise-reject-errors": "off",
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
"object-curly-newline": "off",
"default-case": "off",
"wc/no-self-class": "off",
"no-shadow": "off",
"no-use-before-define": "off",
"array-callback-return": ["error", { allowImplicit: true }],
"block-scoped-var": "error",
"consistent-return": "error",
curly: ["error", "multi-line"],
"default-case-last": "error",
eqeqeq: ["error", "always", { null: "ignore" }],
"guard-for-in": "error",
"no-await-in-loop": "error",
"no-caller": "error",
"no-constructor-return": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-implied-eval": "error",
"no-iterator": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-promise-executor-return": "error",
"no-return-assign": ["error", "always"],
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-template-curly-in-string": "error",
"no-unreachable-loop": "error",
// import-x rules (migrated from eslint-plugin-import / airbnb-base)
"no-else-return": ["error", { allowElseIf: false }],
"no-lonely-if": "error",
"no-unneeded-ternary": ["error", { defaultAssignment: false }],
"no-useless-computed-key": "error",
"no-useless-concat": "error",
"no-useless-rename": "error",
"no-useless-return": "error",
"one-var": ["error", "never"],
"operator-assignment": ["error", "always"],
"prefer-arrow-callback": "error",
"prefer-exponentiation-operator": "error",
"prefer-object-spread": "error",
"prefer-regex-literals": ["error", { disallowRedundantWrapping: true }],
"symbol-description": "error",
yoda: "error",
// TODO: Enable once violations are fixed (43 instances as of 2026-04)
// "no-useless-assignment": "error",
"no-useless-assignment": "error",
// Project rules
"no-bitwise": "error",
"no-console": "error",
"no-restricted-globals": [2, "event"],
"no-restricted-syntax": ["error", "LabeledStatement", "WithStatement"],
"wc/no-self-class": "off",
// import-x rules
"import-x/named": "off",
"import-x/prefer-default-export": "off",
"import-x/no-default-export": "off",
@@ -146,13 +140,9 @@ export default tseslint.config(
"import-x/no-relative-packages": "error",
// TypeScript rules
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-shadow": ["error"],
"@typescript-eslint/naming-convention": [
@@ -216,7 +206,6 @@ export default tseslint.config(
"lit-a11y/role-has-required-aria-attrs": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/no-import-type-side-effects": "error",
camelcase: "off",
"@typescript-eslint/no-dynamic-delete": "off",
"@typescript-eslint/no-empty-object-type": [
"error",

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { html, LitElement, css, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
@@ -50,7 +50,7 @@ class DemoBlackWhiteRow extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,5 +1,5 @@
import { load } from "js-yaml";
import type { PropertyValueMap } from "lit";
import type { PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -60,9 +60,7 @@ class DemoCard extends LitElement {
this._size = await this._card?.getCardSize();
}
protected update(
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
): void {
protected update(_changedProperties: PropertyValues<this>): void {
super.update(_changedProperties);
this._updateSize();
}

View File

@@ -1,17 +1,22 @@
import "@material/mwc-drawer";
import "@material/mwc-top-app-bar-fixed";
import { mdiMenu } from "@mdi/js";
import { mdiMenu, mdiSwapHorizontal } from "@mdi/js";
import type { PropertyValues } from "lit";
import { LitElement, css, html } from "lit";
import { customElement, query, state } from "lit/decorators";
import { dynamicElement } from "../../src/common/dom/dynamic-element-directive";
import { setDirectionStyles } from "../../src/common/util/compute_rtl";
import "../../src/components/ha-button";
import { HaExpansionPanel } from "../../src/components/ha-expansion-panel";
import "../../src/components/ha-icon-button";
import "../../src/components/ha-svg-icon";
import "../../src/managers/notification-manager";
import { haStyle } from "../../src/resources/styles";
import { PAGES, SIDEBAR } from "../build/import-pages";
import "./components/page-description";
const RTL_STORAGE_KEY = "gallery-rtl";
const GITHUB_DEMO_URL =
"https://github.com/home-assistant/frontend/blob/dev/gallery/src/pages/";
@@ -29,6 +34,8 @@ class HaGallery extends LitElement {
document.location.hash.substring(1) ||
`${SIDEBAR[0].category}/${SIDEBAR[0].pages![0]}`;
@state() private _rtl = localStorage.getItem(RTL_STORAGE_KEY) === "true";
@query("notification-manager")
private _notifications!: HTMLElementTagNameMap["notification-manager"];
@@ -97,33 +104,43 @@ class HaGallery extends LitElement {
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
</div>
<div class="page-footer">
<div class="header">Help us to improve our documentation</div>
<div class="secondary">
Suggest an edit to this page, or provide/view feedback for this
page.
<div class="edit-docs">
<div class="header">Help us to improve our documentation</div>
<div class="secondary">
Suggest an edit to this page, or provide/view feedback for this
page.
</div>
<div>
${PAGES[this._page].description ||
Object.keys(PAGES[this._page].metadata).length > 0
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
target="_blank"
>
Edit text
</a>
`
: ""}
${PAGES[this._page].demo
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
target="_blank"
>
Edit demo
</a>
`
: ""}
</div>
</div>
<div>
${PAGES[this._page].description ||
Object.keys(PAGES[this._page].metadata).length > 0
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
target="_blank"
>
Edit text
</a>
`
: ""}
${PAGES[this._page].demo
? html`
<a
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
target="_blank"
>
Edit demo
</a>
`
: ""}
<div class="rtl-toggle">
<ha-icon-button
@click=${this._toggleRtl}
.label=${this._rtl ? "Switch to LTR" : "Switch to RTL"}
>
<ha-svg-icon .path=${mdiSwapHorizontal}></ha-svg-icon>
</ha-icon-button>
</div>
</div>
</div>
@@ -135,9 +152,11 @@ class HaGallery extends LitElement {
`;
}
firstUpdated(changedProps: PropertyValues) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
this._applyDirection();
this.addEventListener("show-notification", (ev) =>
this._notifications.showDialog({ message: ev.detail.message })
);
@@ -164,6 +183,11 @@ class HaGallery extends LitElement {
updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (changedProps.has("_rtl")) {
this._applyDirection();
}
if (!changedProps.has("_page")) {
return;
}
@@ -186,6 +210,15 @@ class HaGallery extends LitElement {
this._drawer.open = !this._drawer.open;
}
private _toggleRtl() {
this._rtl = !this._rtl;
localStorage.setItem(RTL_STORAGE_KEY, String(this._rtl));
}
private _applyDirection() {
setDirectionStyles(this._rtl ? "rtl" : "ltr", this);
}
static styles = [
haStyle,
css`
@@ -238,11 +271,16 @@ class HaGallery extends LitElement {
}
.page-footer {
display: flex;
border-radius: var(--ha-border-radius-lg);
background-color: var(--primary-background-color);
}
.edit-docs {
flex: 1;
text-align: center;
margin: 16px;
padding: 16px;
border-radius: var(--ha-border-radius-lg);
background-color: var(--primary-background-color);
}
.page-footer div {
@@ -266,6 +304,18 @@ class HaGallery extends LitElement {
margin: 0 8px;
text-decoration: none;
}
.rtl-toggle {
padding: var(--ha-space-4);
display: inline-flex;
align-items: flex-end;
margin-top: 12px !important;
}
.rtl-toggle ha-icon-button {
border: 1px solid var(--divider-color);
border-radius: var(--ha-border-radius-pill);
}
`,
];
}

View File

@@ -1,4 +1,5 @@
import { dump } from "js-yaml";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -171,7 +172,7 @@ export class DemoAutomationDescribeAction extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -1,4 +1,5 @@
import { dump } from "js-yaml";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -96,7 +97,7 @@ export class DemoAutomationDescribeCondition extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -1,4 +1,5 @@
import { dump } from "js-yaml";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -119,7 +120,7 @@ export class DemoAutomationDescribeTrigger extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -1,5 +1,6 @@
/* eslint-disable lit/no-template-arrow */
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -51,7 +52,7 @@ export class DemoAutomationTraceTimeline extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -1,5 +1,6 @@
/* eslint-disable lit/no-template-arrow */
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../../src/components/ha-card";
@@ -51,7 +52,7 @@ export class DemoAutomationTrace extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -0,0 +1,3 @@
---
title: Adaptive popover (ha-adaptive-popover)
---

View File

@@ -0,0 +1,217 @@
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";
import { mdiCog, mdiHelp } from "@mdi/js";
import "../../../../src/components/ha-adaptive-popover";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-dialog-footer";
import "../../../../src/components/ha-form/ha-form";
import "../../../../src/components/ha-icon-button";
import type { HASSDomCurrentTargetEvent } from "../../../../src/common/dom/fire_event";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import type { HomeAssistant } from "../../../../src/types";
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
const SCHEMA: HaFormSchema[] = [
{ type: "string", name: "Name", default: "", autofocus: true },
{ type: "string", name: "Email", default: "" },
];
type PopoverType = false | "basic" | "small" | "large" | "form" | "actions";
@customElement("demo-components-ha-adaptive-popover")
export class DemoHaAdaptivePopover extends LitElement {
@state() private _openPopover: PopoverType = false;
@state() private _hass?: HomeAssistant;
@state() private _dialogAnchor?: HTMLElement;
protected firstUpdated() {
this._hass = provideHass(this);
}
protected render() {
return html`
<div class="content">
<h1>Adaptive popover <code>&lt;ha-adaptive-popover&gt;</code></h1>
<p class="subtitle">
Responsive popover component that opens as an anchored popover on
desktop and falls back to adaptive dialog behavior otherwise.
</p>
<h2>Demos</h2>
<div class="buttons">
<ha-button @click=${this._handleOpenPopover("basic")}
>Basic adaptive popover</ha-button
>
<ha-button @click=${this._handleOpenPopover("small")}
>Small adaptive popover</ha-button
>
<ha-button @click=${this._handleOpenPopover("large")}
>Large adaptive popover</ha-button
>
<ha-button @click=${this._handleOpenPopover("form")}
>Adaptive popover with form</ha-button
>
<ha-button @click=${this._handleOpenPopover("actions")}
>Adaptive popover with actions</ha-button
>
</div>
<ha-card>
<div class="card-content">
<p>
<strong>Tip:</strong> On desktop, this uses the opener as the
popover anchor. On narrow screens, it falls back to adaptive
dialog behavior.
</p>
</div>
</ha-card>
<ha-adaptive-popover
.hass=${this._hass}
.open=${this._openPopover === "basic"}
.dialogAnchor=${this._dialogAnchor}
header-title="Basic adaptive popover"
header-subtitle="Anchored to the opener on desktop"
@closed=${this._handleClosed}
>
<div>
This component uses a desktop popover when an anchor is available,
and adaptive dialog behavior otherwise.
</div>
</ha-adaptive-popover>
<ha-adaptive-popover
.hass=${this._hass}
.open=${this._openPopover === "small"}
.dialogAnchor=${this._dialogAnchor}
width="small"
header-title="Small adaptive popover"
@closed=${this._handleClosed}
>
<div>This popover uses the small width preset (320px).</div>
</ha-adaptive-popover>
<ha-adaptive-popover
.hass=${this._hass}
.open=${this._openPopover === "large"}
.dialogAnchor=${this._dialogAnchor}
width="large"
header-title="Large adaptive popover"
@closed=${this._handleClosed}
>
<div>This popover uses the large width preset (1024px).</div>
</ha-adaptive-popover>
<ha-adaptive-popover
.hass=${this._hass}
.open=${this._openPopover === "form"}
.dialogAnchor=${this._dialogAnchor}
header-title="Adaptive popover with form"
header-subtitle="This is an adaptive popover with a form"
@closed=${this._handleClosed}
>
<ha-form autofocus .schema=${SCHEMA}></ha-form>
<ha-dialog-footer slot="footer">
<ha-button
@click=${this._handleClosed}
slot="secondaryAction"
variant="plain"
>Cancel</ha-button
>
<ha-button
@click=${this._handleClosed}
slot="primaryAction"
variant="accent"
>Submit</ha-button
>
</ha-dialog-footer>
</ha-adaptive-popover>
<ha-adaptive-popover
.hass=${this._hass}
.open=${this._openPopover === "actions"}
.dialogAnchor=${this._dialogAnchor}
header-title="Adaptive popover with actions"
header-subtitle="This is an adaptive popover with header actions"
@closed=${this._handleClosed}
>
<div slot="headerActionItems">
<ha-icon-button label="Settings" path=${mdiCog}></ha-icon-button>
<ha-icon-button label="Help" path=${mdiHelp}></ha-icon-button>
</div>
<div>Adaptive popover content</div>
</ha-adaptive-popover>
</div>
`;
}
private _handleOpenPopover =
(popover: PopoverType) => (ev?: HASSDomCurrentTargetEvent<HTMLElement>) => {
this._dialogAnchor = ev?.currentTarget;
this._openPopover = popover;
};
private _handleClosed = () => {
this._dialogAnchor = undefined;
this._openPopover = false;
};
static styles = [
css`
:host {
display: block;
padding: var(--ha-space-4);
}
.content {
max-width: 1000px;
margin: 0 auto;
}
h1 {
margin-top: 0;
margin-bottom: var(--ha-space-2);
}
h2 {
margin-top: var(--ha-space-6);
margin-bottom: var(--ha-space-3);
}
p {
margin: var(--ha-space-2) 0;
line-height: 1.6;
}
.subtitle {
color: var(--secondary-text-color);
font-size: 1.1em;
margin-bottom: var(--ha-space-4);
}
.buttons {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: var(--ha-space-2);
margin: var(--ha-space-4) 0;
}
.card-content {
padding: var(--ha-space-3);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-adaptive-popover": DemoHaAdaptivePopover;
}
}

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -160,7 +160,7 @@ export class DemoHaAlert extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,5 +1,5 @@
import { mdiButtonCursor, mdiHome } from "@mdi/js";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -84,7 +84,7 @@ export class DemoHaBadge extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,5 +1,5 @@
import { mdiHome } from "@mdi/js";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -118,7 +118,7 @@ export class DemoHaButton extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -9,6 +9,7 @@ import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { repeat } from "lit/directives/repeat";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-control-switch";
@@ -50,59 +51,100 @@ export class DemoHaControlSwitch extends LitElement {
protected render(): TemplateResult {
return html`
${repeat(switches, (sw) => {
const { id, label, ...config } = sw;
return html`
<ha-card>
<div class="card-content">
<label id=${id}>${label}</label>
<pre>Config: ${JSON.stringify(config)}</pre>
<ha-control-switch
.checked=${this.checked}
class=${ifDefined(config.class)}
@change=${this.handleValueChanged}
.pathOn=${mdiLightbulb}
.pathOff=${mdiLightbulbOff}
.label=${label}
?disabled=${config.disabled}
?reversed=${config.reversed}
>
</ha-control-switch>
<div class="themes">
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-control-switch ${mode}">
${repeat(switches, (sw) => {
const { id, label, ...config } = sw;
return html`
<div class="card-content">
<label id="${mode}-${id}">${label}</label>
<pre>Config: ${JSON.stringify(config)}</pre>
<ha-control-switch
.checked=${this.checked}
class=${ifDefined(config.class)}
@change=${this.handleValueChanged}
.pathOn=${mdiLightbulb}
.pathOff=${mdiLightbulbOff}
.label=${label}
?disabled=${config.disabled}
?reversed=${config.reversed}
>
</ha-control-switch>
</div>
`;
})}
<div class="card-content">
<p class="title"><b>Vertical</b></p>
<div class="vertical-switches">
${repeat(switches, (sw) => {
const { label, ...config } = sw;
return html`
<ha-control-switch
.checked=${this.checked}
vertical
class=${ifDefined(config.class)}
@change=${this.handleValueChanged}
.label=${label}
.pathOn=${mdiGarageOpen}
.pathOff=${mdiGarage}
?disabled=${config.disabled}
?reversed=${config.reversed}
>
</ha-control-switch>
`;
})}
</div>
</div>
</ha-card>
</div>
</ha-card>
`;
})}
<ha-card>
<div class="card-content">
<p class="title"><b>Vertical</b></p>
<div class="vertical-switches">
${repeat(switches, (sw) => {
const { id, label, ...config } = sw;
return html`
<ha-control-switch
.checked=${this.checked}
vertical
class=${ifDefined(config.class)}
@change=${this.handleValueChanged}
.label=${label}
.pathOn=${mdiGarageOpen}
.pathOff=${mdiGarage}
?disabled=${config.disabled}
?reversed=${config.reversed}
>
</ha-control-switch>
`;
})}
</div>
</div>
</ha-card>
`
)}
</div>
`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static styles = css`
:host {
display: block;
}
.themes {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
gap: 16px;
padding: 16px;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 16px;
border-radius: var(--ha-border-radius-md);
}
ha-card {
max-width: 600px;
margin: 24px auto;
margin: 0 auto;
}
pre {
margin-top: 0;

View File

@@ -8,7 +8,7 @@ import {
mdiContentPaste,
mdiDelete,
} from "@mdi/js";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -80,7 +80,7 @@ export class DemoHaDropdown extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,6 +1,6 @@
import { ContextProvider } from "@lit/context";
import { mdiMagnify } from "@mdi/js";
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -27,7 +27,6 @@ export class DemoHaInput extends LitElement {
constructor() {
super();
// Provides internationalizationContext for ha-input-copy, ha-input-multi and ha-input-search
// eslint-disable-next-line no-new
new ContextProvider(this, {
context: internationalizationContext,
initialValue: {
@@ -179,7 +178,7 @@ export class DemoHaInput extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -65,7 +65,7 @@ export class DemoHaProgressButton extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -51,7 +51,7 @@ export class DemoHaSlider extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -33,7 +33,7 @@ export class DemoHaSpinner extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -3,37 +3,73 @@ title: Switch / Toggle
---
<style>
ha-switch {
display: block;
.wrapper {
display: flex;
gap: 24px;
align-items: center;
}
</style>
# Switch `<ha-switch>`
A toggle switch can represent two states: on and off.
A toggle switch representing two states: on and off.
## Examples
## Implementation
Switch in on state
### Example usage
<div class="wrapper">
<ha-switch checked></ha-switch>
<ha-switch></ha-switch>
<ha-switch disabled></ha-switch>
<ha-switch disabled checked></ha-switch>
</div>
```html
<ha-switch checked></ha-switch>
Switch in off state
<ha-switch></ha-switch>
Disabled switch
<ha-switch disabled></ha-switch>
## CSS variables
<ha-switch disabled checked></ha-switch>
```
For the switch / toggle there are always two variables, one for the on / checked state and one for the off / unchecked state.
### API
The track element (background rounded rectangle that the round circular handle travels on) is set to being half transparent, so the final color will also be impacted by the color behind the track.
This component is based on the webawesome switch component.
Check the [webawesome documentation](https://webawesome.com/docs/components/switch/) for more details.
`switch-checked-color` / `switch-unchecked-color`
Set both the color of the round handle and the track behind it. If you want to control them separately, use the variables below instead.
**Properties/Attributes**
`switch-checked-button-color` / `switch-unchecked-button-color`
Color of the round handle
| Name | Type | Default | Description |
| -------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| checked | Boolean | false | The checked state of the switch. |
| disabled | Boolean | false | Disables the switch and prevents user interaction. |
| required | Boolean | false | Makes the switch a required field. |
| haptic | Boolean | false | Enables haptic vibration on toggle. Only use when the new state is applied immediately (not when save is required). |
`switch-checked-track-color` / `switch-unchecked-track-color`
Color of the track behind the round handle
**CSS Custom Properties**
- `--ha-switch-size` - The size of the switch track height. Defaults to `24px`.
- `--ha-switch-thumb-size` - The size of the thumb. Defaults to `18px`.
- `--ha-switch-width` - The width of the switch track. Defaults to `48px`.
- `--ha-switch-thumb-box-shadow` - The box shadow of the thumb. Defaults to `var(--ha-box-shadow-s)`.
- `--ha-switch-background-color` - Background color of the unchecked track.
- `--ha-switch-thumb-background-color` - Background color of the unchecked thumb.
- `--ha-switch-background-color-hover` - Background color of the unchecked track on hover.
- `--ha-switch-thumb-background-color-hover` - Background color of the unchecked thumb on hover.
- `--ha-switch-border-color` - Border color of the unchecked track.
- `--ha-switch-thumb-border-color` - Border color of the unchecked thumb.
- `--ha-switch-thumb-border-color-hover` - Border color of the unchecked thumb on hover.
- `--ha-switch-checked-background-color` - Background color of the checked track.
- `--ha-switch-checked-thumb-background-color` - Background color of the checked thumb.
- `--ha-switch-checked-background-color-hover` - Background color of the checked track on hover.
- `--ha-switch-checked-thumb-background-color-hover` - Background color of the checked thumb on hover.
- `--ha-switch-checked-border-color` - Border color of the checked track.
- `--ha-switch-checked-thumb-border-color` - Border color of the checked thumb.
- `--ha-switch-checked-border-color-hover` - Border color of the checked track on hover.
- `--ha-switch-checked-thumb-border-color-hover` - Border color of the checked thumb on hover.
- `--ha-switch-disabled-opacity` - Opacity of the switch when disabled. Defaults to `0.2`.
- `--ha-switch-required-marker` - The marker shown after the label for required fields. Defaults to `"*"`.
- `--ha-switch-required-marker-offset` - Offset of the required marker. Defaults to `0.1rem`.

View File

@@ -1 +1,95 @@
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-switch";
import type { HomeAssistant } from "../../../../src/types";
@customElement("demo-components-ha-switch")
export class DemoHaSwitch extends LitElement {
@property({ attribute: false }) hass!: HomeAssistant;
protected render(): TemplateResult {
return html`
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-switch ${mode}">
<div class="card-content">
<div class="row">
<span>Unchecked</span>
<ha-switch></ha-switch>
</div>
<div class="row">
<span>Checked</span>
<ha-switch checked></ha-switch>
</div>
<div class="row">
<span>Disabled</span>
<ha-switch disabled></ha-switch>
</div>
<div class="row">
<span>Disabled checked</span>
<ha-switch disabled checked></ha-switch>
</div>
</div>
</ha-card>
</div>
`
)}
`;
}
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static styles = css`
:host {
display: flex;
justify-content: center;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 0 50px;
margin: 16px;
border-radius: var(--ha-border-radius-md);
}
ha-card {
margin: 24px auto;
}
.card-content {
display: flex;
flex-direction: column;
gap: var(--ha-space-4);
}
.row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--ha-space-4);
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-switch": DemoHaSwitch;
}
}

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
@@ -90,7 +90,7 @@ export class DemoHaTextarea extends LitElement {
`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -1,4 +1,4 @@
import type { TemplateResult } from "lit";
import type { TemplateResult, PropertyValues } from "lit";
import { html, css, LitElement } from "lit";
import { customElement } from "lit/decorators";
import "../../../../src/components/ha-tip";
@@ -31,7 +31,7 @@ export class DemoHaTip extends LitElement {
)}`;
}
firstUpdated(changedProps) {
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),

View File

@@ -95,7 +95,7 @@ class DemoAlarmPanelEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -116,7 +116,7 @@ class DemoArea extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -77,7 +77,7 @@ class DemoConditional extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -426,7 +426,7 @@ class DemoEntities extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -81,7 +81,7 @@ class DemoButtonEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -301,7 +301,7 @@ class DemoEntityFilter extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -149,6 +149,38 @@ const CONFIGS = [
max: 1.9
unit: GBP/h`,
},
{
heading: "A lot of segments",
config: `
- type: gauge
needle: true
name: Percent gauge
entity: sensor.brightness_high
unit: "%"
min: 0
max: 100
segments:
- from: 0
color: "#db4437"
- from: 10
color: "#cc4d39"
- from: 20
color: "#bd563a"
- from: 30
color: "#ad603c"
- from: 40
color: "#9e693d"
- from: 50
color: "#8f723f"
- from: 60
color: "#807b41"
- from: 70
color: "#718442"
- from: 80
color: "#618e44"
- from: 90
color: "#43a047"`,
},
];
@customElement("demo-lovelace-gauge-card")
@@ -159,7 +191,7 @@ class DemoGaugeEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -261,7 +261,7 @@ class DemoGlanceEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -232,7 +232,7 @@ class DemoStack extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -46,7 +46,7 @@ class DemoIframe extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
provideHass(this._demos);
}

View File

@@ -87,7 +87,7 @@ class DemoLightEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -196,7 +196,7 @@ class DemoMap extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -290,7 +290,7 @@ class DemoMarkdown extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -166,7 +166,7 @@ class DemoHuiMediaControlCard extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -63,7 +63,7 @@ export class DemoLovelaceMediaPlayerRow extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -48,7 +48,7 @@ class DemoPicture extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -179,7 +179,7 @@ class DemoPictureElements extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -111,7 +111,7 @@ class DemoPictureEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -171,7 +171,7 @@ class DemoPictureGlance extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -39,7 +39,7 @@ export class DemoPlantEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -246,7 +246,7 @@ class DemoThermostatEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -359,7 +359,7 @@ class DemoTile extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -50,7 +50,7 @@ class DemoTodoListEntity extends LitElement {
return html`<demo-cards id="demos" .configs=${CONFIGS}></demo-cards>`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -0,0 +1,3 @@
---
title: Box shadow
---

View File

@@ -0,0 +1,99 @@
import type { PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
const SHADOWS = ["s", "m", "l"] as const;
@customElement("demo-misc-box-shadow")
export class DemoMiscBoxShadow extends LitElement {
protected render() {
return html`
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<h2>${mode}</h2>
<div class="grid">
${SHADOWS.map(
(size) => html`
<div
class="box"
style="box-shadow: var(--ha-box-shadow-${size})"
>
${size}
</div>
`
)}
</div>
</div>
`
)}
`;
}
firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static styles = css`
:host {
display: flex;
flex-direction: row;
gap: 48px;
padding: 48px;
}
.light,
.dark {
flex: 1;
background-color: var(--primary-background-color);
border-radius: 16px;
padding: 32px;
}
h2 {
margin: 0 0 24px;
font-size: 18px;
font-weight: 500;
color: var(--primary-text-color);
text-transform: capitalize;
}
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 32px;
}
.box {
display: flex;
align-items: center;
justify-content: center;
height: 120px;
border-radius: 12px;
background-color: var(--card-background-color);
color: var(--primary-text-color);
font-size: 16px;
font-weight: 500;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"demo-misc-box-shadow": DemoMiscBoxShadow;
}
}

View File

@@ -2,6 +2,7 @@ import type {
HassEntity,
HassEntityAttributeBase,
} from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -51,6 +52,7 @@ const SENSOR_DEVICE_CLASSES = [
"sulphur_dioxide",
"temperature",
"timestamp",
"uptime",
"volatile_organic_compounds",
"volatile_organic_compounds_parts",
"voltage",
@@ -397,7 +399,7 @@ export class DemoEntityState extends LitElement {
ENTITIES.map(createRowData)
);
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
mockIcons(hass);

View File

@@ -1,3 +1,4 @@
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import "../../../../src/components/ha-formfield";
import "../../../../src/components/ha-switch";
@@ -330,7 +331,7 @@ export class DemoIntegrationCard extends LitElement {
`;
}
protected firstUpdated(changedProps) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
const hass = provideHass(this);
hass.updateTranslations(null, "en");

View File

@@ -149,7 +149,7 @@ class DemoMoreInfoClimate extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -204,7 +204,7 @@ class DemoMoreInfoCover extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -38,7 +38,7 @@ class DemoMoreInfoFan extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -52,7 +52,7 @@ class DemoMoreInfoHumidifier extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -51,7 +51,7 @@ class DemoMoreInfoInputNumber extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -33,7 +33,7 @@ class DemoMoreInfoInputText extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -0,0 +1,3 @@
---
title: Lawn mower
---

View File

@@ -0,0 +1,98 @@
import type { PropertyValues, TemplateResult } from "lit";
import { html, LitElement } from "lit";
import { customElement, property, query } from "lit/decorators";
import "../../../../src/components/ha-card";
import "../../../../src/dialogs/more-info/more-info-content";
import type { MockHomeAssistant } from "../../../../src/fake_data/provide_hass";
import { provideHass } from "../../../../src/fake_data/provide_hass";
import "../../components/demo-more-infos";
import { LawnMowerEntityFeature } from "../../../../src/data/lawn_mower";
const ALL_FEATURES =
LawnMowerEntityFeature.START_MOWING +
LawnMowerEntityFeature.PAUSE +
LawnMowerEntityFeature.DOCK;
const ENTITIES = [
{
entity_id: "lawn_mower.full_featured",
state: "docked",
attributes: {
friendly_name: "Full featured mower",
supported_features: ALL_FEATURES,
},
},
{
entity_id: "lawn_mower.mowing",
state: "mowing",
attributes: {
friendly_name: "Mowing",
supported_features: ALL_FEATURES,
},
},
{
entity_id: "lawn_mower.returning",
state: "returning",
attributes: {
friendly_name: "Returning",
supported_features:
LawnMowerEntityFeature.START_MOWING +
LawnMowerEntityFeature.PAUSE +
LawnMowerEntityFeature.DOCK,
},
},
{
entity_id: "lawn_mower.paused",
state: "paused",
attributes: {
friendly_name: "Paused",
supported_features: ALL_FEATURES,
},
},
{
entity_id: "lawn_mower.error",
state: "error",
attributes: {
friendly_name: "Error",
supported_features:
LawnMowerEntityFeature.START_MOWING + LawnMowerEntityFeature.DOCK,
},
},
{
entity_id: "lawn_mower.basic",
state: "docked",
attributes: {
friendly_name: "Basic mower",
supported_features: LawnMowerEntityFeature.START_MOWING,
},
},
];
@customElement("demo-more-info-lawn-mower")
class DemoMoreInfoLawnMower extends LitElement {
@property({ attribute: false }) public hass!: MockHomeAssistant;
@query("demo-more-infos") private _demoRoot!: HTMLElement;
protected render(): TemplateResult {
return html`
<demo-more-infos
.hass=${this.hass}
.entities=${ENTITIES.map((ent) => ent.entity_id)}
></demo-more-infos>
`;
}
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
}
declare global {
interface HTMLElementTagNameMap {
"demo-more-info-lawn-mower": DemoMoreInfoLawnMower;
}
}

View File

@@ -187,7 +187,7 @@ class DemoMoreInfoLight extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -40,7 +40,7 @@ class DemoMoreInfoLock extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -25,7 +25,7 @@ class DemoMoreInfoMediaPlayer extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -77,7 +77,7 @@ class DemoMoreInfoNumber extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -40,7 +40,7 @@ class DemoMoreInfoScene extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -33,7 +33,7 @@ class DemoMoreInfoTimer extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -241,7 +241,7 @@ class DemoMoreInfoUpdate extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -8,18 +8,101 @@ import { provideHass } from "../../../../src/fake_data/provide_hass";
import "../../components/demo-more-infos";
import { VacuumEntityFeature } from "../../../../src/data/vacuum";
const ALL_FEATURES =
VacuumEntityFeature.STATE +
VacuumEntityFeature.START +
VacuumEntityFeature.PAUSE +
VacuumEntityFeature.STOP +
VacuumEntityFeature.RETURN_HOME +
VacuumEntityFeature.FAN_SPEED +
VacuumEntityFeature.BATTERY +
VacuumEntityFeature.STATUS +
VacuumEntityFeature.LOCATE +
VacuumEntityFeature.CLEAN_SPOT +
VacuumEntityFeature.CLEAN_AREA;
const ENTITIES = [
{
entity_id: "vacuum.first_floor_vacuum",
entity_id: "vacuum.full_featured",
state: "docked",
attributes: {
friendly_name: "First floor vacuum",
friendly_name: "Full featured vacuum",
supported_features: ALL_FEATURES,
battery_level: 85,
battery_icon: "mdi:battery-80",
fan_speed: "balanced",
fan_speed_list: ["silent", "standard", "balanced", "turbo", "max"],
status: "Charged",
},
},
{
entity_id: "vacuum.cleaning_vacuum",
state: "cleaning",
attributes: {
friendly_name: "Cleaning vacuum",
supported_features: ALL_FEATURES,
battery_level: 62,
battery_icon: "mdi:battery-60",
fan_speed: "turbo",
fan_speed_list: ["silent", "standard", "balanced", "turbo", "max"],
status: "Cleaning bedroom",
},
},
{
entity_id: "vacuum.returning_vacuum",
state: "returning",
attributes: {
friendly_name: "Returning vacuum",
supported_features:
VacuumEntityFeature.STATE +
VacuumEntityFeature.START +
VacuumEntityFeature.PAUSE +
VacuumEntityFeature.STOP +
VacuumEntityFeature.RETURN_HOME +
VacuumEntityFeature.BATTERY,
battery_level: 23,
battery_icon: "mdi:battery-20",
status: "Returning to dock",
},
},
{
entity_id: "vacuum.error_vacuum",
state: "error",
attributes: {
friendly_name: "Error vacuum",
supported_features:
VacuumEntityFeature.STATE +
VacuumEntityFeature.START +
VacuumEntityFeature.STOP +
VacuumEntityFeature.RETURN_HOME +
VacuumEntityFeature.LOCATE,
status: "Stuck on obstacle",
},
},
{
entity_id: "vacuum.basic_vacuum",
state: "docked",
attributes: {
friendly_name: "Basic vacuum",
supported_features:
VacuumEntityFeature.START +
VacuumEntityFeature.STOP +
VacuumEntityFeature.RETURN_HOME,
},
},
{
entity_id: "vacuum.paused_vacuum",
state: "paused",
attributes: {
friendly_name: "Paused vacuum",
supported_features: ALL_FEATURES,
battery_level: 45,
battery_icon: "mdi:battery-40",
fan_speed: "standard",
fan_speed_list: ["silent", "standard", "balanced", "turbo", "max"],
status: "Paused",
},
},
];
@customElement("demo-more-info-vacuum")
@@ -37,7 +120,7 @@ class DemoMoreInfoVacuum extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -61,7 +61,7 @@ class DemoMoreInfoWaterHeater extends LitElement {
`;
}
protected firstUpdated(changedProperties: PropertyValues) {
protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);
const hass = provideHass(this._demoRoot);
hass.updateTranslations(null, "en");

View File

@@ -117,7 +117,7 @@ class LandingPageLogs extends LitElement {
`;
}
protected firstUpdated(changedProps: PropertyValues): void {
protected firstUpdated(changedProps: PropertyValues<this>): void {
super.firstUpdated(changedProps);
this._scrolledToBottomController.observe(this._scrollBottomMarkerElement!);

View File

@@ -4,7 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import { extractSearchParam } from "../../src/common/url/search-params";
import "../../src/components/ha-alert";
import "../../src/components/ha-button";
import "../../src/components/ha-fade-in";
import "../../src/components/animation/ha-fade-in";
import "../../src/components/ha-spinner";
import "../../src/components/ha-svg-icon";
import "../../src/components/progress/ha-progress-bar";
@@ -115,7 +115,7 @@ class HaLandingPage extends LandingPageBaseElement {
`;
}
protected firstUpdated(changedProps: PropertyValues) {
protected firstUpdated(changedProps: PropertyValues<this>) {
super.firstUpdated(changedProps);
makeDialogManager(this);

Some files were not shown because too many files have changed in this diff Show More