Reviewed on 2026-11-10 against the Home Assistant demo, the supplied screenshots, and the current frontend design references. This records the shared interaction families, rather than treating a component rendering successfully as proof of visual parity.
| Family | Resting, hover and focus | Drag/press behavior | Composition coverage |
|---|---|---|---|
| Buttons, icon buttons, entity actions, keypad and command bars | Shared state layer; hover only on hover-capable devices; distinct pressed tint; keyboard focus ring; disabled controls have no hover layer | Native button activation, keyboard activation and existing hold/double-tap semantics | Cards, tiles, rows, alarm, vacuum, lock, valve, mower, remote, scenes, helpers and popup header/footer actions |
| Compact switch | 48×24 track, 18px thumb; hover/focus state layer, 2px focus outline, disabled opacity; RTL thumb positioning | Native tap/Space/Enter | Settings rows, mute/oscillation and entity-row toggles |
| Large device switch | Separate 40px horizontal or 130px vertical control; track tint strengthens on hover, focused track ring | Tap or swipe; live thumb preview; cancellation restores state; keyboard arrows | Toggle/humidifier/fan features; main power controls in switch-like details |
| Horizontal and vertical sliders | 40px track; vertical popup control 130px wide and up to 320px tall; visible marker; accent focus ring | Value tooltip while dragging, 500ms keyboard-release delay, captured native range behavior; start/end/cursor fill modes | Brightness, kelvin, volume, speed, cover position/tilt, numeric and feature controls |
| Circular dial | Pale arc and strong current-to-target segment; measured marker; fixed-metric localized readout; local handle focus indicator and thicker focused active arc; disabled track/marker only; inactive colored arc hidden | Pointer capture, live preview, cancellation, keyboard limits; dual handles cannot cross | Thermostat, humidifier and water-heater detail layouts |
| Menus and segments | Selected tint/fill, 20% menu-option hover tint, keyboard focus; popovers measured and constrained to viewport | Arrow/Home/End selection, text search, Enter, Escape and Tab dismissal | HVAC/preset/swing/fan selectors and composed device menus |
| Color picker | Selection marker, localized keyboard-focus indicator, disabled grayscale, standard pipette artwork and icon tooltip | Pointer hue/saturation preview, keyboard adjustment, hex validation, swatches and native eyedropper | Standalone picker and RGB light details |
| Charts and energy | Theme-aware tooltip, crosshair and drag selection; focus-visible bar emphasis; tooltip stays within plot | Hover/keyboard inspection; legends; drag zoom; standalone navigator pans/resizes a window and resets; plot follows navigator preview | Line/history, statistics, sensor/sparkline and energy cards |
| Maps | Grab/grabbing cursors, focus outline and bounded zoom buttons | Captured pan, cancel, arrow-key pan and +/- zoom | Standalone map and supplied entity markers |
| Dialogs | 580px desktop surface, 24px corners, 20px header, SVG close/back icons, themed scrim; animated opening with reduced-motion support | Native modal focus containment, Escape/backdrop/close, return focus and background scroll lock | Base dialog, confirmation, and all entity detail routes |
| Adaptive entity sheets | Full-width bottom sheet up to 90% viewport height, 20px top corners, drag handle, independently scrolling content | Header/handle swipe dismissal or snap-back; a slider drag never becomes a sheet drag; mode remains stable while open | Every automatic more-info route on small screens |
| Device details | Main controls follow device type: tall cover panel with button/tilt modes; capability-based fan slider/buttons/switch; humidity/water-temperature dial; media artwork and transport; explicit alarm state | Changes preserve source entity identity and emit the documented public properties/actions | All routes in COVERAGE.md |
References: controls, switch, button, dialog, adaptive dialog, and the more-info inventory.
The browser suite checks shared interaction states in both themes, real pointer/touch input, keyboard focus and tooltips, every public feature mapping, and every detail route in desktop/light and mobile/dark layouts. Targeted screenshots are reviewed manually for the principal control families. This is not a pixel-diff certification against every upstream screen. Native select/date/time choosers and screen eyedropper prompts retain browser/OS appearance; maps and media depend on the supplied assets. Backend-dependent actions and administrative Home Assistant dialogs remain outside this UI library, as described in COVERAGE.md.
The ioBroker comparison records the source widget families and why these additions are useful. These are independently authored controls using Luma theme tokens and shared surfaces, rather than copies of VIS appearance.
- Native radio groups support arrow keys, disabled-option skipping and JSON options; selection updates both input state and the public value.
- Momentary buttons pair press/release events through pointer capture, keyboard repeat, cancellation, focus loss and removal. Disabled controls reject input.
- Measured level indicators clamp their graphic and expose meter semantics with low/high warnings; progress rings distinguish known percentages from indeterminate work.
- Analog clocks resolve supplied/live timestamps in an IANA timezone. Opening indicators distinguish closed/open/tilted states and mirror hinges. State images select explicit URL mappings and reject executable URLs.
- Marquees measure actual overflow, pause for hover/focus and explicit pause, and display static wrapping text under reduced motion.
- Tank, opening and appliance cards reuse those primitives in their automatic detail dialogs. Commands remain requests with source identity; supplied cycle state remains authoritative. Theme selection emits a value without changing application theme scope.
The browser suite covers these behaviors. Manual gallery review includes the composed appliance popup in light mode and tank details in dark mode.