Skip to main content
On this pageFunctions

Ui/Switch

Functions

descriptionId

functionsource
/** Returns the description element id, derived from the switch's base id. */
(id: string): string

labelId

functionsource
/** Returns the label element id, derived from the switch's base id. */
(id: string): string

view

functionsource
/**
 * Renders an accessible switch as a stateless controlled component. The
 *  parent owns the checked state (`isChecked`) and receives the new state via
 *  `onToggle` when the user toggles it.
 * 
 *  ```ts
 *  // In view:
 *  Switch.view(
 *    {
 *      id: 'notifications',
 *      isChecked: model.notificationsEnabled,
 *      onToggle: isChecked => ToggledNotifications({ isChecked }),
 *      toView: attributes => ...,
 *    },
 *    h,
 *  )
 * 
 *  // In update:
 *  ToggledNotifications: ({ isChecked }) => [
 *    evo(model, { notificationsEnabled: () => isChecked }),
 *    [],
 *  ],
 *  ```
 */
<Message>(
  config: ViewConfig<Message>,
  h: HtmlBuilder<Message>
): Html

Types

SwitchAttributes

typesource
/**
 * Attribute groups the switch provides to the consumer's `toView` callback.
 *  Each group is a `ReadonlyArray<Attribute<Message>>` the consumer
 *  spreads into its own element attribute arrays. The `button` and `label`
 *  bundles carry the click and Space handlers that dispatch the configured
 *  `onToggle` Message.
 * 
 *  The `button` bundle sets `type="button"` so that rendering the switch as a
 *  `button` element inside a `form` element toggles without also submitting the
 *  form. Setting it is harmless on the other elements a switch might use, such
 *  as a `div` or a `span`, because the builder assigns a DOM property rather
 *  than an HTML attribute. Spread a later `h.Type` to override it.
 */
type SwitchAttributes = Readonly<{
  button: ReadonlyArray<Attribute<Message>>
  description: ReadonlyArray<Attribute<Message>>
  hiddenInput: ReadonlyArray<Attribute<Message>>
  label: ReadonlyArray<Attribute<Message>>
}>

ViewConfig

typesource
/**
 * Per-render view configuration for the stateless controlled view.
 *  Generic over `Message` (the message `onToggle` dispatches).
 * 
 *  - `isChecked`: the current checked state, read straight from the parent
 *    Model. `aria-checked` and the `data-checked` marker derive from it.
 *  - `onToggle`: dispatched with the new checked state when the user clicks
 *    the switch or its label, or presses Space. Handle it in the parent's
 *    `update` by storing the value.
 *  - `toView`: receives the SwitchAttributes and lays out the
 *    switch.
 *  - `isDisabled`: marks the switch unavailable with `aria-disabled="true"`
 *    and `data-disabled`, keeping it focusable. Use it when the control does
 *    not apply; use `isReadOnly` when its state is still information the user
 *    needs.
 *  - `isReadOnly`: prevents toggling while exposing read-only semantics with
 *    `aria-readonly="true"` and `data-readonly`. The switch remains
 *    focusable. Independent of `isDisabled`: setting both emits both
 *    attribute sets, and either one removes the interaction handlers.
 */
type ViewConfig = Readonly<{
  id: string
  isChecked: boolean
  isDisabled: boolean
  isReadOnly: boolean
  name: string
  onToggle: (isChecked: boolean) => Message
  toView: (attributes: SwitchAttributes<Message>) => Html
  value: string
}>

Stay in the update loop.

New releases, patterns, and the occasional deep dive.


Built with Foldkit.

© 2026 Devin Jameson