VI Controls

Star on GitHubFeedback
VI ControlsNative HTMLot-switch

Switch

A sentence whose last word you can change. The state rolls between on and off in italic, and the full stop answers: a dot when on, a ring when off.

Report an issue with Switch

Example

On
Off
Pointed at
Focus
Disabled
either, on
either, off
either, pointed at
either, focus
question, off
question, on
question, pointed at
question, focus

Install

Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base along.

npx shadcn@latest add https://thedirectors.agency/ui/r/switch.json

Usage

switch-example.tsx
import { Switch } from "@/components/ui/switch"export default function Example() {return (<div className="ot-mp grid justify-items-start gap-4"><Switch defaultChecked>Email me when someone replies:</Switch><Switch>Send the weekly digest:</Switch><Switch variant="either" defaultChecked>Comments on this draft are</Switch><Switch variant="either" on="public" off="private">Keep this board</Switch><Switch variant="question">Share my location with the team</Switch><Switch variant="question" defaultChecked>Play a sound when a build finishes</Switch></div>)}

Contract

  • Underneath: native checkbox with role="switch".
  • Anatomy: <label class="ot-switch" data-variant="sentence | either | question"><input type="checkbox" role="switch" aria-label="Name"> Sentence is …</label>. Sentence ends <span class="ot-switch-state" aria-hidden="true"><span>on</span><span>off</span></span><span class="ot-switch-stop" aria-hidden="true"></span>; either ends <span class="ot-switch-either" aria-hidden="true"><span>on</span><span class="ot-switch-or">/</span><span>off</span></span>; question ends <span class="ot-switch-ask" aria-hidden="true"><span>.</span><span>?</span></span>.
  • Sentence (the default). Yours: the state word, in italic, rolls vertically between on and off. Off is pencil. The full stop is the state too: .ot-switch-stop is a filled dot when on and a hairline ring when off (the calendar's done and to-come). Ink fills it from the rim inward, and drains back out (an inset box-shadow over --ot-andante; kept under forced colours).
  • Either. A printed form's "delete as appropriate": both words stand in the italic, "on / off", and the one that doesn't apply is struck out in graphite and steps back to pencil. Pointing pencils a hairline through the one that holds, since that's the one you'd strike. Switching lifts the old strike off to the right and draws the new one from the left.
  • Question. After "It has to be design.", where "the concept of passion?" is answered by "the voice of reason.": off, the sentence asks, in graphite, ending on an italic question mark in pencil. On, the hook is wiped away from the top down to its dot, which stays as the full stop, and the sentence inks. Switching off, the hook grows back up out of the dot. The full stop shares the question mark's grid cell, so the line never moves. Pass the sentence without its last mark.
  • States: on, off, hover (sentence: the underline darkens; either: the pencil sketch; question: the mark inks), focus (accent outline round the state; round the whole sentence for question), disabled. Right to left, either's strikes run right to left.
  • Keyboard: Space toggles.

Props

Props of Switch
PropTypeDefaultWhat it does
childrenReactNodeThe sentence, up to its last word: "Email me when someone replies:". For question, the whole sentence without its last mark.
variant"sentence" | "either" | "question""sentence"How the sentence says its state. sentence: the last word rolls between on and off in italic, and the full stop is a dot when on and a ring when off. either: both words stand, "on / off", as a printed form offers them; the one that doesn't apply is struck out and steps back to pencil, and switching lifts the strike off one and draws it through the other. question: off, the sentence asks, ending on a pencil question mark; on, the hook is wiped away down to its dot, which stays as the full stop, and the sentence inks.
checked / defaultCheckedbooleanWhether it's on.
onCheckedChange(checked: boolean) => voidCalled with the new state.
onstring"on"The word for on, in italic.
offstring"off"The word for off.
labelClassNamestringClasses for the sentence's label wrapper. className goes to the native checkbox.

Craft

Where its move comes from

Where its move comes from
ComponentReferenceMove
Switch"28 December" dotsThe full stop is a dot or a ring
Either switchA printed form's "delete as appropriate"Both words stand; the one that doesn't apply is struck out
Question switch"It has to be design." (passion? / reason.)The question mark's hook lifts and leaves a full stop

How it moves

How it moves
ComponentArticulationWhat moves
SwitchLegatoThe word rolls; ink fills the full stop from its rim
Either switchPass-throughThe strike lifts off one word to the right and draws through the other from the left
Question switchAnswerThe hook wipes down to its dot, which stays as the full stop; the sentence inks