diff --git a/.changeset/switch.md b/.changeset/switch.md new file mode 100644 index 0000000..2f452dd --- /dev/null +++ b/.changeset/switch.md @@ -0,0 +1,23 @@ +--- +'@dunky.dev/switch': minor +'@dunky.dev/react-switch': minor +--- + +Add the Switch primitive — a binary on/off control following the WAI-ARIA APG +pattern, shipped as an agnostic core (`@dunky.dev/switch`) plus a React binding +(`@dunky.dev/react-switch`). + +```tsx +import { Switch } from '@dunky.dev/react-switch' + +function App() { + return ( + + + + + Airplane mode + + ) +} +``` diff --git a/packages/core/switch/README.md b/packages/core/switch/README.md new file mode 100644 index 0000000..6a5d3a3 --- /dev/null +++ b/packages/core/switch/README.md @@ -0,0 +1,27 @@ +# @dunky.dev/switch + +The framework-agnostic switch interaction, modeled as a state machine on +`@dunky.dev/state-machine`. Pure logic — no substrate, no framework. Consumers +pair it with a substrate driver rather than driving the machine directly. + +The behavior contract — scenarios, guarantees, driver obligations — lives in +[SPEC.md](./SPEC.md). + +## Install + +```sh +npm install @dunky.dev/switch +``` + +## Usage + +```ts +import { machine, connector } from '@dunky.dev/state-machine' +import { switchMachine, switchConnect } from '@dunky.dev/switch' + +// `id` is substrate-minted (SSR-safe); the connect derives the per-part ids. +const service = machine(switchMachine({ ...options, id: 'my-switch' })) +connector(service, switchConnect, options) // wires the consumer callbacks +service.start() +service.send({ type: 'toggle' }) +``` diff --git a/packages/core/switch/SPEC.md b/packages/core/switch/SPEC.md new file mode 100644 index 0000000..6251e62 --- /dev/null +++ b/packages/core/switch/SPEC.md @@ -0,0 +1,111 @@ +# SPEC / Switch + +## Reference + +- **W3C pattern**: [APG Switch](https://www.w3.org/WAI/ARIA/apg/patterns/switch/), + over the normative + [WAI-ARIA 1.2 `switch`](https://www.w3.org/TR/wai-aria-1.2/#switch) role + definition. +- **State machine**: built on `@dunky.dev/state-machine`. +- **Prior art**: API shape modeled on the Radix, Base UI, and Ark switches. + +## Overview + +A switch is a binary control that turns a setting on or off, taking effect +immediately — airplane mode, notifications, dark theme. Unlike a checkbox it +never collects a choice for later submission and never has a mixed state: it +is always exactly on or off. + +## Anatomy + +``` + — root; owns checked state, renders nothing of its own + |_ — the interactive element: carries the switch role and checked state + | |_ — the knob; purely visual, styled off data-state + |_