import type { Meta, StoryObj } from '@storybook/react-vite' import { fn } from 'storybook/test' import { useState } from 'react' import { IconSquareRounded } from '@tabler/icons-react' import { Checkbox } from './Checkbox' const meta = { title: 'Inputs/Checkbox', component: Checkbox, // `onChange` makes it the control; without one it is the picture of a // state (the "inside a row" story), and these stories are about the control. args: { checked: false, 'aria-label': 'Example', onChange: fn() }, argTypes: { onChange: { control: false } }, } satisfies Meta export default meta type Story = StoryObj export const Unchecked: Story = {} export const Checked: Story = { args: { checked: true } } export const Disabled: Story = { args: { disabled: true } } export const DisabledChecked: Story = { args: { checked: true, disabled: true } } /** Words beside the box. Clicking them toggles it too, and they name it. */ export const WithLabel: Story = { args: { label: 'Label', 'aria-label': undefined }, render: (args) => { const [checked, setChecked] = useState(args.checked) return }, } /** Disabled with words: only the box shows it; the words keep their colour. */ export const WithLabelDisabled: Story = { args: { label: 'Label', 'aria-label': undefined, disabled: true } } /** * A list you tick several from: each row is the target — a picture, the words, * the box at the end — and fills on hover and while checked. */ export const Row: Story = { parameters: { controls: { disable: true } }, render: () => { const [ticked, setTicked] = useState(new Set(['Item two'])) const toggle = (item: string) => setTicked((prev) => { const next = new Set(prev) if (next.has(item)) next.delete(item) else next.add(item) return next }) return (
{['Item one', 'Item two', 'Item three'].map((item) => ( } label={item} checked={ticked.has(item)} onChange={() => toggle(item)} /> ))}
) }, } /** A row that cannot be changed: the box shows it, and the row neither fills nor points. */ export const RowDisabled: Story = { parameters: { controls: { disable: true } }, render: () => (
} label="Item one" checked onChange={() => {}} /> } label="Item two" checked={false} onChange={() => {}} />
), } /** Controlled, as always — the parent owns the state. */ export const Toggles: Story = { parameters: { controls: { disable: true } }, render: () => { const [checked, setChecked] = useState(false) return }, } /** * Inside a clickable row the row owns the toggle: the checkbox gets no * `onChange`, draws the state, and is hidden from assistive technology, so * the whole row is one control. The row says the state itself — here * `aria-pressed`, on an option in a list `aria-selected`. */ export const InsideARow: Story = { parameters: { controls: { disable: true } }, render: () => { const [checked, setChecked] = useState(true) return ( ) }, }