Toggle
One input_boolean.* or switch.*, used as a mode: Guest mode, Do Not Disturb, Away.
Quick example
Section titled “Quick example”import { useHaToggle } from "@dashhaus/core";
/** A mode as a switch: Guest mode, Do Not Disturb, an input_boolean or a switch. */export function ModeSwitch({ entityId }: { entityId: string }) { const { entity, actions } = useHaToggle(entityId); return ( <button type="button" role="switch" aria-checked={entity.state === "on"} disabled={entity.state === "unavailable"} onClick={actions.onToggle} > {entity.name} </button> );}onToggle calls toggle on the entity’s own domain, input_boolean.toggle or switch.toggle.
Component
Section titled “Component”<HaToggle> is useHaToggle as a component that draws nothing of its own. It takes every option of the hook as a
prop, and hands the hook’s result to its child function. Use it where hooks can’t go, such as one per item of a list.
entityIdstring- The Home Assistant entity id.
children(live: HaToggleResult) => ReactNode- Draws the hook's result. The component itself draws nothing.
useHaToggle(entityId: string, options?: HaToggleOptions): HaToggleResultOne live input_boolean or switch for any UI: the mapped entity, today's history and its toggle.
It reads the entity, its area and today’s history. icon and description are yours to give: Home Assistant has no such attributes for a mode.
Options
Section titled “Options”name?string- Overrides Home Assistant's friendly name.
area?string- Overrides the area Home Assistant's registries resolve for the entity.
lastSeen?string- Overrides when the entity was last reachable, shown while it is unavailable.
icon?ToggleIcondescription?stringhistory?ToggleHistory- Host-owned history override; when omitted, today's history is read from Home Assistant.
loadHistory?boolean- Set false to skip the Home Assistant history read.
onActionError?(error: HaActionError) => void- Called with an HaActionError when an action is refused or fails.
Returns
Section titled “Returns”entityToggleEntityhistoryToggleHistoryactionsToggleHandlers
entity: ToggleEntity
Section titled “entity: ToggleEntity”entityIdstring- The Home Assistant entity id.
namestring- Its name: the `name` option, else Home Assistant's friendly name, else its entity id.
area?string- Where it applies: "Whole home", "Bedroom".
state"unavailable" | "off" | "on"icon?ToggleIconuntil?string- Local time it switches itself off, when it was turned on for a while ("07:00"). The hook doesn't set it: Home Assistant has no timed-on service for these domains, so a host that times a mode supplies it.
duration?string- Which duration option it was turned on with; shown as selected in the sheet. Host-owned, like `until`.
description?string- One line on what it does, shown in the sheet.
lastChanged?stringlastSeen?string- While it is unavailable, when it was last reachable: the `lastSeen` option, else what Home Assistant reports.
history: ToggleHistory
Section titled “history: ToggleHistory”Today, from Home Assistant’s recorder, kept up to date by every change since. Pass history to supply your own, or
loadHistory={false} to skip the read.
samplesHourSample[]- 1 for hours it was on, 0 off, "unavailable", null for hours ahead. Fractions for part of an hour.
currentHournumberonMinutesnumber- Minutes on today, including the current hour.
actions: ToggleHandlers
Section titled “actions: ToggleHandlers”onToggle() => void- Calls `input_boolean.toggle` or `switch.toggle`. An unavailable entity, or one from another domain, reports `unsupported`.
Every mode
Section titled “Every mode”Hooks can’t be called in a loop, so a list renders one headless component per entity. The selector returns a string: useHaSelector re-renders only when its value changes, and a string of ids changes only when an entity comes or goes. Lists skip each item’s history read with loadHistory={false}.
import { HaToggle, useHaSelector } from "@dashhaus/core";import type { HaSnapshot } from "@dashhaus/core";
/** Every input_boolean: the house's modes. Switches are often devices, so this list leaves them out. */const modeIds = (snapshot: HaSnapshot) => Object.keys(snapshot.entities).filter((id) => id.startsWith("input_boolean.")).sort().join(" ");
export function AllModes() { const ids = useHaSelector(modeIds).split(" ").filter(Boolean); return ( <ul> {ids.map((id) => ( <li key={id}> <HaToggle entityId={id} loadHistory={false}> {({ entity, actions }) => ( <button type="button" role="switch" aria-checked={entity.state === "on"} onClick={actions.onToggle}> {entity.name} </button> )} </HaToggle> </li> ))} </ul> );}On for an hour
Section titled “On for an hour”import { useEffect, useState } from "react";import { useHaToggle } from "@dashhaus/core";
/** * "On for an hour". Home Assistant has no timed-on service for an input_boolean or a switch, so the timer is yours: * this one turns the mode off again from the page, and only while the page stays open. */export function OnForAnHour({ entityId }: { entityId: string }) { const { entity, actions } = useHaToggle(entityId, { loadHistory: false }); const [until, setUntil] = useState<number>(); const on = entity.state === "on";
useEffect(() => { if (until == null || !on) return; const timer = setTimeout(() => { actions.onToggle(); setUntil(undefined); }, until - Date.now()); return () => clearTimeout(timer); }, [until, on, actions]);
return ( <button type="button" disabled={on || entity.state === "unavailable"} onClick={() => { actions.onToggle(); setUntil(Date.now() + 60 * 60 * 1000); }} > {entity.name} for an hour </button> );}There is no onTurnOnFor in the actions on purpose: Home Assistant can’t turn an input_boolean or a switch on for a while, so the timer belongs to whoever runs it. Orb’s tile and Field’s module take your durations and onTurnOnFor and draw the choices. A timer in Home Assistant itself, an automation or a timer helper, outlives the page; this one doesn’t.
In a skin
Section titled “In a skin”Orb’s HaToggleTile and Field’s HaToggleModule are useHaToggle above each skin’s card. They take the hook’s
options as props, plus their own:
import { HaToggleTile } from "@dashhaus/orb";import { HaToggleModule } from "@dashhaus/field";
export function OrbGuestMode() { return <HaToggleTile entityId="input_boolean.guest_mode" icon="guest" footprint="compact" />;}
export function FieldDoNotDisturb() { return <HaToggleModule entityId="input_boolean.do_not_disturb" icon="bell-off" description="Silences the chimes." />;}entityIdstring- The Home Assistant entity id.
showControl?boolean- Compact only. false removes the inline control, shows the value in its place, and makes the row open the detail sheet. The orb keeps its tap and hold actions. Default true.
footprint?CardFootprint- Card footprint. The skin's stylesheet sets the heights; the three names are the shared vocabulary.
defaultOpen?booleandefaultAction?undefineddurations?DurationOption[]- Sheet: ways to turn it on. Omit `onTurnOnFor` to hide them.
onTurnOnFor?(value: string) => void- Sheet: turn on (or keep on) with one of `durations`.
entityIdstring- The Home Assistant entity id.
footprint?FieldFootprintdefaultOpen?boolean- Open the detail panel on first render (stories).
durations?DurationOption[]- The panel's ways to turn it on. Default: 30 min, 1 hour, until morning, until off.
onTurnOnFor?(value: string) => void- Turn on (or keep on) with one of `durations`. Omit and the panel has no duration keys.