HabSwitch
A setting that takes effect the moment it is flipped.
<HabSwitch v-model="autoPublish" label="Auto-publish transcripts" help="Applies immediately." />If the change needs a Save button, use a HabCheckbox instead. A switch that does nothing until saved is a lie about immediacy, and users act on that lie — they flip it and navigate away.
It reads label-left, control-right, which is the opposite of the other two toggles: a switch is a setting in a list of settings, not an option in a set. Give it a width so the control lands where the reader expects.
Boxed
boxed draws the switch as a field: inside HabFieldBox, the box HabInput is drawn in, with the label above and the help below. Use it for a true/false value in a column of fields, where a bare toggle would not line up with the fields around it — and where the value has a kind chosen in a prependAddon segment, which a bare toggle has nothing to put in front of. Outside a form of fields, keep the plain switch: a setting in a list of settings is a row.
on-label and off-label say the state in the box, before the switch, in the product's words. Habitus writes none of its own; without them the box holds the switch alone. density sizes the box as it does a field's, and state="error" marks it as a field's: the error border, the help line in error ink as the message, and aria-invalid on the switch. disabled outranks it.
state has no disabled on a switch, by decision. The fields put availability in state (state="disabled" on HabInput, HabSelect and the pickers); the toggles — HabSwitch, HabCheckbox, HabRadio — have always taken a disabled prop, and a boxed switch keeps it rather than offer two ways to say the same thing. In a column of fields, that is the one prop that reads differently: :disabled="locked" on the switch, :state="locked ? 'disabled' : 'default'" on the fields around it.
density, state, on-label, off-label and prependAddon belong to the box, so they do nothing without boxed — and warn in development, rather than being ignored silently.
<HabSwitch v-model="debug" boxed label="Debug Logging" on-label="true" off-label="false">
<template #prependAddon>…a HabFieldAddon…</template>
</HabSwitch><HabSwitch
v-model="accepted"
boxed
state="error"
label="Terms"
help="Accept the terms to continue."
/>Focused, the box's border turns accent as a field's does, and the track drops its own ring rather than showing two indicators for one focus.
Read-only
readonly shows the setting to be read: on or off at full contrast and the label in full ink, but clicking it or pressing Space changes nothing and no update:modelValue is emitted. It stays focusable and is announced as read-only — unlike disabled, which says "not now", is dimmed, and wins when both are set. See HabReadonly for the difference, and for making a whole region read-only at once; :readonly="false" keeps one switch editable inside it.
<HabSwitch v-model="autoPublish" label="Auto-publish transcripts" readonly />Accessibility
- A real
<input type="checkbox">carryingrole="switch". The native control holds the state; the role only changes how it is announced — as "on"/"off" rather than "checked"/"unchecked". - The track is the input's immediately following sibling, which is where
base.cssdraws the focus indicator. - The label names the control, the help describes it.
- The knob's travel is a
lefttransition, whichprefers-reduced-motiondoes not currently suppress — the movement is the affordance rather than decoration, and it is 180ms. Raise it if that proves wrong in use. - Give it a
label, or anaria-label. Habitus warns when it has neither.
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
boxed | boolean | false | Drawn as a field: the switch inside HabFieldBox, the box HabInput is drawn in — the label above it, the help below, state, and the box's prependAddon segment — for a true/false value in a column of fields, where a bare toggle would not line up with them and a kind menu would have nothing to sit in front of. Off by default: a switch in a list of settings is a row, not a field. |
density | "default" | "compact" | "default" | Box height while boxed, as HabInput's density. Only while boxed; warns otherwise. |
disabled | boolean | false | — |
help | string | undefined | Quiet second line — what the setting actually does. |
label | string | undefined | The setting's name. |
modelValue | boolean | false | On/off state, for v-model. |
offLabel | string | undefined | Text shown in the box while off. See onLabel. |
onLabel | string | undefined | Text shown in the box while on, before the switch — "true", "Shown". Only while boxed, and warns otherwise; Habitus writes none of its own, so without it the box shows the switch alone. |
readonly | boolean | undefined | The setting is shown to be read, not changed: on or off at full contrast, the label in full ink, and clicking or pressing Space changes nothing. Still focusable and announced as read-only — unlike disabled, which says "not now", is dimmed, and wins when both are set. Unset, it follows a surrounding HabReadonly; false keeps this switch editable inside one. |
state | "default" | "error" | "default" | Validation state while boxed, as a field's: error turns the box's border and the help line to error and sets aria-invalid, so the message in help is announced with it. Availability is disabled, which wins. Only while boxed — a bare switch has no box to mark — and warns otherwise. |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | on: boolean | — |
Slots
| Slot | Bindings | Description |
|---|---|---|
prependAddon | any | While boxed: a control fused to the start of the box — usually a HabFieldAddon as a menu trigger — as on HabInput. Not drawn otherwise, and warns. |