Skip to main content

Frontend component updates in 2026.5

· 4 min read

Component updates

ha-progress-bar

A new component replaces mwc-progress-bar in our codebase and is fully themeable. Check out this PR for a fully custom progress bar.

New component specific tokens:

--ha-progress-bar-indicator-color
--ha-progress-bar-indicator-background
--ha-progress-bar-track-color
--ha-progress-bar-track-height
--ha-progress-bar-border-radius
--ha-progress-bar-animation-duration
--ha-progress-bar-indicator-highlight-image
--ha-progress-bar-indicator-highlight-width
--ha-progress-bar-indicator-highlight-height

ha-switch

ha-switch was migrated to webawesome. It now has many CSS properties to make customization easier. We also removed some tokens from the old switch:

Removed tokens:

--switch-unchecked-button-color
--switch-unchecked-track-color
--switch-unchecked-color
--switch-checked-button-color
--switch-checked-track-color
--switch-checked-color

New component specific tokens:

--ha-switch-size
--ha-switch-thumb-size
--ha-switch-width
--ha-switch-background-color
--ha-switch-thumb-background-color
--ha-switch-background-color-hover
--ha-switch-thumb-background-color-hover
--ha-switch-checked-background-color
--ha-switch-checked-thumb-background-color
--ha-switch-checked-background-color-hover
--ha-switch-checked-thumb-background-color-hover
--ha-switch-border-color
--ha-switch-thumb-border-color
--ha-switch-thumb-border-color-hover
--ha-switch-checked-border-color
--ha-switch-checked-thumb-border-color
--ha-switch-checked-border-color-hover
--ha-switch-checked-thumb-border-color-hover
--ha-switch-thumb-box-shadow
--ha-switch-disabled-opacity
--ha-switch-required-marker
--ha-switch-required-marker-offset

ha-checkbox

ha-checkbox was also migrated to webawesome and got new CSS properties. You can no longer use MDC tokens for it, but we added a set of tokens to customize the new checkbox.

New component specific tokens:

--ha-checkbox-size
--ha-checkbox-border-color
--ha-checkbox-border-color-hover
--ha-checkbox-background-color
--ha-checkbox-background-color-hover
--ha-checkbox-checked-background-color
--ha-checkbox-checked-background-color-hover
--ha-checkbox-checked-icon-color
--ha-checkbox-checked-icon-scale
--ha-checkbox-border-radius
--ha-checkbox-border-width
--ha-checkbox-required-marker
--ha-checkbox-required-marker-offset

ha-textarea

ha-textarea was migrated to webawesome and got new CSS properties. You can no longer use MDC tokens for it, but we added a set of tokens to customize the new textarea.

The API changed slightly. To make your textarea grow in size, set the resize prop to auto.

ha-adaptive-popover

You might already know the (fairly new) ha-adaptive-dialog component. It combines a dialog and bottom sheet by showing a dialog on desktop and a bottom sheet on mobile. We added ha-adaptive-popover as the popover counterpart to the adaptive dialog. It shows a popover on desktop and a bottom sheet on mobile. It is based on ha-adaptive-dialog and is currently used in the tile card date picker feature.

Removed ha-fab

ha-fab was removed, we use just a normal ha-button now, since the position styling was always done from the parent component.

Style updates

Box shadow tokens

We added new global box shadow tokens: --ha-box-shadow-s, --ha-box-shadow-m, --ha-box-shadow-l

But we also removed the old box shadow tokens:

--ha-color-shadow-light
--ha-color-shadow-dark
--ha-shadow-offset-x-...
--ha-shadow-blur-...
--ha-shadow-spread-..

Surface colors

In the next release we plan to change the way we handle surface background colors. The tokens are introduced now but are just used for ha-tooltip.

New tokens:

--ha-color-surface-default
--ha-color-surface-low
--ha-color-surface-lower
--ha-color-surface-default-inverted
--ha-color-surface-low-inverted
--ha-color-surface-lower-inverted

Frontend context groups, new context decorators and deprecated contexts

· 2 min read

Last release we introduced the lazy context and we wanted to use hass context and lazy context more in favor of passing the hass object. We found that small tasks often required subscribing to many contexts, so we grouped Hass contexts into logical groups.

Context groups

Following context groups have been added:

  • registriesContext: contains all registries (device, entity, area, etc)
  • internationalizationContext: contains all internationalization related data (locale, localize, etc)
  • apiContext: contains all API related methods (callService, callWS, etc)
  • connectionContext: contains all connection related data (connection, connected, hassUrl, etc)
  • uiContext: contains all UI related data (themes, panels, dockedSidebar, etc)
  • configContext: contains all config related data (auth, config, user, etc)

Consume context entry decorators

In the last blogpost I showed how to use context with @transform. @transform is powerful, but sometimes you only need a single context entry and do not want to define a transform function. To support that, we added decorators that consume a single context entry directly. You pass an array that defines where the entity ID comes from (usually a config property), and the decorator consumes the correct context and maps the entity ID to the correct registry entry. It also watches the defined path and updates the entry when needed.

New decorators:

  • @consumeEntityState
  • @consumeEntityStates
  • @consumeEntityRegistryEntry

sample usage:

@state()
@consumeEntityRegistryEntry({ entityIdPath: ["_config", "entity"] })
_entity?: EntityRegistryDisplayEntry;

We may add more of these decorators in the future, e.g. for areas, devices, etc.

Deprecate contexts

These contexts are still available, but they can be removed in a future release. Use the new context groups instead.

  • connectionSingleContext
  • localizeContext
  • localeContext
  • configSingleContext
  • themesContext
  • selectedThemeContext
  • userContext
  • userDataContext
  • panelsContext
  • authContext

Serious about serial: migrating from pyserial to serialx

· 2 min read

Existing integrations and libraries communicating with serial ports should migrate from pyserial, pyserial-asyncio, and pyserial-asyncio-fast to serialx. This new library features native asyncio support on all platforms and will allow your integrations and libraries to take advantage of ESPHome serial proxies in Home Assistant, and includes critical fixes for asyncio event loop stability.

Background

pyserial has been the de facto serial library in Python for many years and has broad support for all popular platforms. Its API, however, predates asyncio in Python and is sync-only. The pyserial-asyncio package was eventually released to bridge pyserial with asyncio. Unfortunately, pyserial-asyncio development never reached 1.0 stability or cross-platform support, and neither pyserial nor pyserial-asyncio have had PyPI releases in almost five years. We forked pyserial-asyncio and released pyserial-asyncio-fast to fix outstanding issues affecting Core event loop stability.

We developed serialx from the ground up as a modern Python serial library with native sync and async APIs. It is import-compatible with the serial, serial_asyncio, and serial_asyncio_fast modules and allows existing packages to migrate with very minimal changes, if any.

Migration

The serialx documentation has an extensive migration guide that goes into more detail.

Most packages just need to replace pyserial, pyserial-asyncio, and pyserial-asyncio-fast with serialx in their setup.py or pyproject.toml file and update exception handling to replace broad catching of SerialException with more granular error handling (such as OSError and TimeoutError).

Packages directly constructing a sync serial.Serial() object should migrate to using the serialx.serial_for_url() helper to ensure automatic compatibility with all supported protocols.

Prompt for your agent

The migration itself is mechanical, paste the following instructions into your agent of choice:

Migrate my code from pyserial, pyserial-asyncio, and pyserial-asyncio-fast to serialx using https://raw.githubusercontent.com/puddly/serialx/refs/heads/dev/docs/how-to/pyserial-migration.md

New radio frequency entity platform for RF device integrations

· 3 min read

Home Assistant now has a radio_frequency entity platform that decouples RF transceiver hardware from the devices it controls. Instead of each device integration talking directly to specific RF hardware, transmitter integrations (like esphome) expose RadioFrequencyTransmitterEntity instances, and device integrations send commands through them via helper functions.

This mirrors the infrared entity platform and was approved in architecture discussion #1365.

Registering custom dashboard strategies

· 2 min read

As of Home Assistant 2026.5, you can now register custom dashboard strategies, just as you can with custom cards, making them easier to discover and add using the new dashboard dialog under the Community dashboards section.

Previously, you had to send users to create a blank dashboard, edit in YAML mode, and paste in your custom strategy. Now you can register a friendly name, description, and documentation.

To register your strategy, call window.customStrategies.push() with an object containing the following keys:

  • type: The strategy type without the custom: prefix, for example "my-demo".
  • strategyType: Set to "dashboard" to register a dashboard strategy.
  • name: The friendly name of the strategy.
  • description (optional): A short description of the strategy.
  • documentationURL (optional): A URL to the documentation for the strategy. This is not shown in the strategy UI yet but may in the future.

Example:

window.customStrategies = window.customStrategies || [];
window.customStrategies.push({
type: "my-demo",
strategyType: "dashboard",
name: "My demo dashboard",
description: "A starter dashboard generated from JavaScript.",
documentationURL: "https://example.com/my-demo-dashboard",
});

This metadata is separate from the custom element itself. Your strategy still needs to be registered with a tag like ll-strategy-dashboard-my-demo, and users still need the resource loaded before Home Assistant can discover it. You can use HACS for this as other resources can be added, like custom cards.

Take a look at the updated custom strategies documentation with example code and further details.

Deprecation of legacy device tracker platform API

· 3 min read

Summary

The legacy (non-config-entry) device tracker platform API is deprecated and will be removed in the Home Assistant 2027.5 release. By the end of the 12-month deprecation period, all remaining legacy device tracker platforms will be removed from the core repository, and custom integrations implementing the legacy API will stop working.

Integrations authors need to update integrations to implement the modern device tracker platform API.

Background

Config entry device trackers were introduced in May 2019, which means integration authors have had 8 years to migrate integrations when support is removed in May 2027.

As of today (April 2026) most widely used core device tracker integrations have already been migrated.

Note that the most popular integration that has not yet been migrated, xiaomi_miio, has a wide mix of functionality including other things than device tracker.

The proposal to deprecate the legacy device tracker API was approved in architecture proposal 1375.

List of core integrations, sorted by reported use

The list was generated from https://analytics.home-assistant.io/ in March 2026

Integration Installations API Type Details
----------------------------------------------------------------------------------------------------
mobile_app 415,204 modern tracker TrackerEntity
mqtt 233,161 modern tracker TrackerEntity
zha 126,903 modern scanner ScannerEntity
ibeacon 89,099 modern unknown BaseTrackerEntity
fritz 42,934 modern scanner ScannerEntity
ping 33,439 modern scanner ScannerEntity
unifi 33,136 modern scanner ScannerEntity
xiaomi_miio 12,866 legacy scanner async_scan_devices
nmap_tracker 7,397 modern scanner ScannerEntity
icloud 5,772 modern tracker TrackerEntity
freebox 5,312 modern scanner ScannerEntity
asuswrt 4,686 modern scanner ScannerEntity
tile 4,212 modern tracker TrackerEntity
renault 3,646 modern tracker TrackerEntity
private_ble_device 3,231 modern unknown BaseTrackerEntity
keenetic_ndms2 3,080 modern scanner ScannerEntity
owntracks 3,022 modern tracker TrackerEntity
snmp 2,923 legacy scanner async_scan_devices
devolo_home_network 2,910 modern scanner ScannerEntity
tesla_fleet 2,798 modern tracker TrackerEntity
netgear 2,782 modern scanner ScannerEntity
mikrotik 2,761 modern scanner ScannerEntity
tplink_omada 2,708 modern scanner ScannerEntity
starlink 2,250 modern tracker TrackerEntity
tractive 2,144 modern tracker TrackerEntity
volvo 2,077 modern tracker TrackerEntity
husqvarna_automower 1,924 modern tracker TrackerEntity
tessie 1,562 modern tracker TrackerEntity
bluetooth_le_tracker 1,011 legacy
traccar_server 978 modern tracker TrackerEntity
huawei_lte 827 modern scanner ScannerEntity
gpslogger 813 modern tracker TrackerEntity
teslemetry 720 modern tracker TrackerEntity
traccar 609 modern tracker TrackerEntity
luci 590 legacy scanner scan_devices
subaru 502 modern tracker TrackerEntity
mysensors 474 modern tracker TrackerEntity
starline 460 modern tracker TrackerEntity
geofency 443 modern tracker TrackerEntity
google_maps 389 legacy
locative 378 modern tracker TrackerEntity
opnsense 355 legacy scanner scan_devices
fing 266 modern scanner ScannerEntity
ruckus_unleashed 232 modern scanner ScannerEntity
synology_srm 193 legacy scanner scan_devices
unifi_direct 190 legacy scanner scan_devices
mqtt_json 182 legacy
vodafone_station 166 modern scanner ScannerEntity
xiaomi 143 legacy scanner scan_devices
demo 141 legacy
ubus 111 legacy scanner scan_devices
bt_smarthub 95 legacy scanner scan_devices
aprs 93 legacy
nrgkick 81 modern tracker TrackerEntity
ddwrt 79 legacy scanner scan_devices
fressnapf_tracker 74 modern tracker TrackerEntity
linksys_smart 69 legacy scanner scan_devices
fortios 53 legacy scanner scan_devices
swisscom 51 legacy scanner scan_devices
tomato 45 legacy scanner scan_devices
quantum_gateway 42 legacy scanner scan_devices
aruba 24 legacy scanner scan_devices
meraki 24 legacy
sky_hub 22 legacy scanner async_scan_devices
ituran 19 modern tracker TrackerEntity
cisco_ios 10 legacy scanner scan_devices
upc_connect 10 legacy scanner async_scan_devices
cisco_mobility_express 6 legacy scanner scan_devices
arris_tg2492lg 2 legacy scanner async_scan_devices
bbox 1 legacy scanner scan_devices
actiontec 0 legacy scanner scan_devices
autoskope 0 modern tracker TrackerEntity
bt_home_hub_5 0 legacy scanner scan_devices
cppm_tracker 0 legacy scanner scan_devices
fleetgo 0 legacy
hitron_coda 0 legacy scanner scan_devices
lojack 0 modern tracker TrackerEntity
thomson 0 legacy scanner scan_devices

Entity IDs with mismatched domains are deprecated

· One min read

Integrations that set entity_id directly on an entity will now be validated to ensure the domain portion matches the platform's domain. For example, a light entity must use light.my_light, not cover.my_light.

Setting an entity ID with the wrong domain will log a deprecation warning and will stop working in Home Assistant 2027.5.

In most cases, integrations should not set entity_id at all — Home Assistant will generate it automatically.

Migrating app builds to Docker BuildKit

· 4 min read

The legacy home-assistant/builder container and the old home-assistant/builder GitHub Action have been retired. We recommend migrating all GitHub workflows and Dockerfiles for apps (formerly add-ons) as described in this post.

What changed and why

The old builder ran every architecture build inside a single privileged Docker-in-Docker container using QEMU emulation. This was slow, required elevated privileges, and those who were already familiar with Docker needed to learn how to use the custom Home Assistant's builder container. The old builder also had unnecessary maintenance overhead. Today, what the builder does can be fully replaced with Docker BuildKit, which is natively supported on GitHub Actions runners and has built-in multi-arch support with QEMU emulation if needed.

For your CI, the replacement is a set of focused composite GitHub Actions that delegate building to the runner's native Docker with Docker BuildKit. Outside the CI, the migration means that your Dockerfile is now the single source of truth for building your app image, and you can use docker build directly to build and test your app locally without needing to use the builder container.

Migration process

The migration has two parts: updating your Dockerfiles and updating your GitHub Actions workflows.

Update Dockerfiles

The new build workflow doesn't use build.yaml anymore. Move the content into your Dockerfile as follows:

  • build_from - replace the build_from key in build.yaml with a FROM statement in your Dockerfile:

    FROM ghcr.io/home-assistant/base:latest

    As the base images are now published as multi-platform manifests, there is usually no need to define per-arch base images anymore. The build-image action still supplies BUILD_ARCH as a build argument though, so you can use that in your Dockerfile if you need to use it in the template for the base image name.

  • labels - move any custom Docker labels directly into your Dockerfile with a LABEL statement:

    LABEL \
    org.opencontainers.image.title="Your awesome app" \
    org.opencontainers.image.description="Description of your app." \
    org.opencontainers.image.source="https://github.com/your/repo" \
    org.opencontainers.image.licenses="Apache License 2.0"

    If you are creating a custom workflow, note that the legacy builder used to add the io.hass.type, io.hass.name, io.hass.description, and io.hass.url labels automatically. The new actions do not infer these values, so add them explicitly via the labels input of the build-image (or similar) action.

  • args - move custom build arguments into your Dockerfile as ARG definitions with default values:

    ARG MY_BUILD_ARG="default-value"

    Default values in ARG replace what was previously supplied via build.yaml's args dictionary. They can still be overridden at build time with --build-arg if needed.

With the content of build.yaml migrated, you can delete the file from your repository.

Update GitHub Actions workflows

Remove any workflow steps using home-assistant/builder@master and replace them with the new composite actions. See the example workflow in our example app repository for a complete working example. Alternatively, use the individual actions in a more custom workflow as needed.

Image naming

The preferred way to reference a published app image is now the generic (multi-arch) name without an architecture prefix:

# config.yaml
image: "ghcr.io/my-org/my-app"

The {arch} placeholder (e.g. ghcr.io/my-org/{arch}-my-app) is still supported as a compatibility fallback, but it's encouraged to use the generic name and let the manifest handle the platform resolution.

Local builds

After updating your Dockerfile, you can use docker build to build the app image directly - you can refer to Local app testing for more details.

Apps built locally by Supervisor

For backward compatibility, Supervisor still reads build.yaml file if it's present and populates the image build arguments with values read from this file. This will produce warnings and eventually be removed in the future, so it's recommended to migrate to the new Dockerfile-based approach as described above.

New infrared entity platform for IR device integrations

· 2 min read

Home Assistant now has an infrared entity platform that decouples IR emitter hardware from the devices they control. Instead of each device integration talking directly to specific IR hardware, emitter integrations (like esphome) expose InfraredEntity instances, and device integrations (like lg_infrared) send commands through them via helper functions.

See the architecture discussion for the full background.