Build an accessible Toggle button that works controlled or uncontrolled
Build Toggle: a button that is on or off, like a Bold button in an editor. It shows its children as its label and tells screen readers its state with aria-pressed ("true" or "false").
Without a pressed prop it's uncontrolled: it starts at defaultPressed (false if not given) and flips itself on every click. With a pressed prop it's controlled: it shows exactly that value and never changes it itself. In both cases, a click calls onPressedChange (if given) with the new value. Pass any other props, like disabled or className, on to the button.
// Uncontrolled
<Toggle defaultPressed>Bold</Toggle>
// Controlled
const [bold, setBold] = useState(false);
<Toggle pressed={bold} onPressedChange={setBold}>Bold</Toggle>
export default function Toggle({ pressed, defaultPressed = false, onPressedChange, children }) {
return <button type="button">{children}</button>;
}
- starts off, with aria-pressed false
- flips on every click when uncontrolled
- starts on with defaultPressed
- reports clicks when uncontrolled too
- when controlled, shows the pressed prop and doesn't change itself
- follows a parent's state, including changes from outside
- passes other props to the button
The answer
Write it yourself first. Then compare it with a reference solution and the checks it passes.
Checking your sign-in…