@kb.ui/react 0.10.4 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -707
- package/dist/components/Accordion/Accordion.d.ts +33 -0
- package/dist/components/Avatar/Avatar.d.ts +19 -0
- package/dist/components/Code/Code.d.ts +26 -3
- package/dist/components/Code/tokenize.d.ts +5 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +10 -0
- package/dist/components/Collection/Collection.d.ts +99 -0
- package/dist/components/Collection/useCollection.d.ts +66 -0
- package/dist/components/CollectionList/CollectionList.d.ts +12 -0
- package/dist/components/CollectionRow/CollectionRow.d.ts +17 -0
- package/dist/components/Combobox/Combobox.d.ts +14 -2
- package/dist/components/ConfirmAction/ConfirmAction.d.ts +42 -0
- package/dist/components/CopyableText/CopyableText.d.ts +38 -0
- package/dist/components/CopyableText/content.d.ts +14 -0
- package/dist/components/Dashboard/Dashboard.d.ts +17 -0
- package/dist/components/DescriptionList/DescriptionList.d.ts +20 -0
- package/dist/components/Dialog/Dialog.d.ts +3 -1
- package/dist/components/Disclosure/Disclosure.d.ts +21 -0
- package/dist/components/EmptyState/EmptyState.d.ts +30 -0
- package/dist/components/Form/Form.d.ts +19 -0
- package/dist/components/FormSection/FormSection.d.ts +26 -0
- package/dist/components/Gallery/Gallery.d.ts +26 -0
- package/dist/components/Grid/Grid.d.ts +17 -6
- package/dist/components/Image/Image.d.ts +20 -0
- package/dist/components/Link/Link.d.ts +15 -2
- package/dist/components/PageHeader/PageHeader.d.ts +27 -0
- package/dist/components/Panel/Panel.d.ts +3 -1
- package/dist/components/Popover/Popover.d.ts +55 -0
- package/dist/components/Settings/Settings.d.ts +11 -0
- package/dist/components/Skeleton/Skeleton.d.ts +34 -0
- package/dist/components/Spinner/Spinner.d.ts +26 -0
- package/dist/components/Stack/Stack.d.ts +15 -0
- package/dist/components/StatsRow/StatsRow.d.ts +33 -0
- package/dist/components/SupportingPane/SupportingPane.d.ts +15 -0
- package/dist/components/Table/Table.d.ts +65 -0
- package/dist/components/Tabs/Tabs.d.ts +69 -0
- package/dist/components/Tabs/index.d.ts +1 -0
- package/dist/components/Thumbnail/Thumbnail.d.ts +14 -0
- package/dist/components/Toast/Toast.d.ts +72 -0
- package/dist/index.d.ts +39 -4
- package/dist/index.js +3901 -1238
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/CollapsiblePanel.d.ts +10 -0
- package/dist/utils/useClipboard.d.ts +28 -0
- package/docs/components/Accordion.md +66 -0
- package/docs/components/Avatar.md +80 -0
- package/docs/components/Badge.md +37 -0
- package/docs/components/Button.md +46 -0
- package/docs/components/Callout.md +41 -0
- package/docs/components/Card.md +41 -0
- package/docs/components/Checkbox.md +60 -0
- package/docs/components/Code.md +77 -0
- package/docs/components/CodeBlock.md +77 -0
- package/docs/components/Collection.md +183 -0
- package/docs/components/CollectionList.md +44 -0
- package/docs/components/CollectionRow.md +62 -0
- package/docs/components/Combobox.md +88 -0
- package/docs/components/ConfirmAction.md +100 -0
- package/docs/components/Container.md +41 -0
- package/docs/components/CopyableText.md +93 -0
- package/docs/components/Dashboard.md +81 -0
- package/docs/components/DescriptionList.md +61 -0
- package/docs/components/Dialog.md +84 -0
- package/docs/components/Disclosure.md +53 -0
- package/docs/components/EmptyState.md +50 -0
- package/docs/components/ErrorSummary.md +48 -0
- package/docs/components/Fieldset.md +42 -0
- package/docs/components/FileInput.md +74 -0
- package/docs/components/Form.md +67 -0
- package/docs/components/FormActions.md +45 -0
- package/docs/components/FormSection.md +57 -0
- package/docs/components/Gallery.md +84 -0
- package/docs/components/Grid.md +66 -0
- package/docs/components/Heading.md +40 -0
- package/docs/components/Image.md +62 -0
- package/docs/components/Inline.md +42 -0
- package/docs/components/Input.md +82 -0
- package/docs/components/Link.md +52 -0
- package/docs/components/Menu.md +44 -0
- package/docs/components/MultiSelect.md +59 -0
- package/docs/components/NumberField.md +65 -0
- package/docs/components/PageHeader.md +68 -0
- package/docs/components/Panel.md +153 -0
- package/docs/components/Popover.md +89 -0
- package/docs/components/Progress.md +37 -0
- package/docs/components/RadioGroup.md +69 -0
- package/docs/components/ScrollArea.md +40 -0
- package/docs/components/Select.md +71 -0
- package/docs/components/Separator.md +40 -0
- package/docs/components/Settings.md +57 -0
- package/docs/components/Skeleton.md +86 -0
- package/docs/components/Spinner.md +45 -0
- package/docs/components/Split.md +47 -0
- package/docs/components/Stack.md +54 -0
- package/docs/components/Stat.md +34 -0
- package/docs/components/StatsRow.md +80 -0
- package/docs/components/Status.md +48 -0
- package/docs/components/SupportingPane.md +59 -0
- package/docs/components/Switch.md +73 -0
- package/docs/components/Table.md +105 -0
- package/docs/components/Tabs.md +89 -0
- package/docs/components/Text.md +36 -0
- package/docs/components/Textarea.md +47 -0
- package/docs/components/Thumbnail.md +66 -0
- package/docs/components/Toast.md +130 -0
- package/docs/components/Toolbar.md +39 -0
- package/docs/components/Tooltip.md +42 -0
- package/package.json +3 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Separator
|
|
2
|
+
|
|
3
|
+
Use `Separator` for a thematic break or a decorative divider. It renders a native `<hr>` and accepts its props and `ref`. The `orientation` and `decorative` props set `role`, `aria-hidden` and `aria-orientation`; decorative dividers are hidden from assistive technology.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/layout-separator--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Separator } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<div>
|
|
16
|
+
<p>Project summary</p>
|
|
17
|
+
<Separator />
|
|
18
|
+
<p>Review history</p>
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## More examples
|
|
25
|
+
|
|
26
|
+
- [A divider in a row](https://kbui.kcb.pro/storybook/?path=/story/layout-separator--vertical): Inspect orientation and stretching.
|
|
27
|
+
- [Visual grouping](https://kbui.kcb.pro/storybook/?path=/story/layout-separator--decorative): Hide a decorative rule from assistive technology.
|
|
28
|
+
|
|
29
|
+
## Reference
|
|
30
|
+
|
|
31
|
+
| Prop | Values | Default |
|
|
32
|
+
| ------------- | ---------------------------------------------------- | ------------ |
|
|
33
|
+
| `orientation` | `horizontal` `vertical` | `horizontal` |
|
|
34
|
+
| `decorative` | Hide a visual-only divider from assistive technology | `false` |
|
|
35
|
+
|
|
36
|
+
Vertical rules stretch inside `Inline` and have a 1rem minimum height. No tab stop or resizing interaction is added. See [Layout composition](https://github.com/KhallilB/kbui/blob/main/docs/guides/layout.md).
|
|
37
|
+
|
|
38
|
+
## Related components
|
|
39
|
+
|
|
40
|
+
Use [`Inline`](Inline.md) to arrange a row and [`Panel`](Panel.md) to group a complete section.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Settings
|
|
2
|
+
|
|
3
|
+
Use `Settings` for a page of preferences or account management: sections of fields, and managed lists such as members, API keys or sessions with row actions. Each section is saved on its own. `Settings` renders a header region and a sections region with a rule between sections; [`FormSection`](FormSection.md) children put their heading beside their fields on wide screens and above them on narrow ones. Record rows from [`CollectionRow`](CollectionRow.md) keep their status and actions end-aligned, on one line beside the main text from 40rem of page width. For one task with a single submit, use [`Form`](Form.md).
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/layout-settings--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Button, Container, FormSection, Heading, Input, Settings, Switch } from "@kb.ui/react";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
|
|
14
|
+
export function Example() {
|
|
15
|
+
const [digest, setDigest] = useState(true);
|
|
16
|
+
return (
|
|
17
|
+
<Container as="main">
|
|
18
|
+
<Settings header={<Heading level={1}>Account</Heading>}>
|
|
19
|
+
<form onSubmit={(event) => event.preventDefault()}>
|
|
20
|
+
<FormSection
|
|
21
|
+
title="Profile"
|
|
22
|
+
description="Shown to everyone in your workspace."
|
|
23
|
+
actions={<Button type="submit">Save profile</Button>}
|
|
24
|
+
>
|
|
25
|
+
<Input label="Display name" name="name" />
|
|
26
|
+
</FormSection>
|
|
27
|
+
</form>
|
|
28
|
+
<FormSection title="Email" description="Sent to the address on your profile.">
|
|
29
|
+
<Switch label="Weekly digest" checked={digest} onCheckedChange={setDigest} />
|
|
30
|
+
</FormSection>
|
|
31
|
+
</Settings>
|
|
32
|
+
</Container>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## More examples
|
|
38
|
+
|
|
39
|
+
- [Notifications](https://kbui.kcb.pro/storybook/?path=/story/layout-settings--notifications): Email, push and quiet-hours sections with switches, a frequency select and event checkboxes.
|
|
40
|
+
- [Team members](https://kbui.kcb.pro/storybook/?path=/story/layout-settings--team-members): An invite form beside a member list with role changes and a confirmed removal.
|
|
41
|
+
|
|
42
|
+
## Reference
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Notes |
|
|
45
|
+
| --- | --- | --- | --- |
|
|
46
|
+
| `header` | `ReactNode` | unset | Page title and intro above the sections |
|
|
47
|
+
| `classNames` | `{ header?, sections? }` | unset | Classes for the regions |
|
|
48
|
+
|
|
49
|
+
Other native `div` props and `ref` pass through. Direct children of the sections region are separated by a rule; wrap a section in its own `form` when it saves fields, and leave list sections unwrapped.
|
|
50
|
+
|
|
51
|
+
A `FormSection` inside `Settings` uses the split layout unless you set its `layout`: header in one third, fields in two thirds from 40rem of section width, stacked below it. Tokens: `--kb-settings-gap` and `--kb-settings-divider`.
|
|
52
|
+
|
|
53
|
+
Start the header with an `h1` and keep section headings at `h2`. Put destructive row actions behind a confirmation such as [`Dialog`](Dialog.md), and announce saved or failed sections with a status message. Your app owns saving, list data and permissions.
|
|
54
|
+
|
|
55
|
+
## Related components
|
|
56
|
+
|
|
57
|
+
Use [`FormSection`](FormSection.md) for each section, [`CollectionList`](CollectionList.md) for managed lists and [`Form`](Form.md) for a single task.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Skeleton
|
|
2
|
+
|
|
3
|
+
Reserve the footprint of incoming text, media, or cards so the page does not jump when asynchronous data resolves.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-skeleton--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Card, Skeleton } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<Card aria-busy="true" aria-label="Loading release summary">
|
|
16
|
+
<Skeleton variant="text" lines={3} animation="wave" />
|
|
17
|
+
</Card>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Shape from content
|
|
23
|
+
|
|
24
|
+
Set `variant="auto"` and pass the real layout as children. While `loading` is true, Skeleton renders the children inert and hidden from assistive technology. kbui avatars, buttons, badges, status chips, images, form fields, headings and text then become placeholders in their own size and shape. Leave data-driven fields empty while loading: empty headings and text still reserve one line. Other text elements fall back to plain text bars. Skeleton marks itself `aria-busy` and announces `label` once, so callers do not write placeholder copy.
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import "@kb.ui/react/styles.css";
|
|
28
|
+
import { Avatar, Card, Heading, Inline, Skeleton, Text } from "@kb.ui/react";
|
|
29
|
+
|
|
30
|
+
type Person = { name: string; role: string };
|
|
31
|
+
|
|
32
|
+
export function Example({ person }: { person?: Person | undefined }) {
|
|
33
|
+
return (
|
|
34
|
+
<Skeleton variant="auto" loading={!person} label="Loading profile">
|
|
35
|
+
<Card>
|
|
36
|
+
<Inline gap="md" align="center">
|
|
37
|
+
<Avatar name={person?.name ?? ""} decorative />
|
|
38
|
+
<div>
|
|
39
|
+
<Heading level={3} size="sm">
|
|
40
|
+
{person?.name}
|
|
41
|
+
</Heading>
|
|
42
|
+
<Text size="sm" tone="muted">
|
|
43
|
+
{person?.role}
|
|
44
|
+
</Text>
|
|
45
|
+
</div>
|
|
46
|
+
</Inline>
|
|
47
|
+
</Card>
|
|
48
|
+
</Skeleton>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Skeleton cannot know how many items a list will hold. Render a fixed number of empty rows while loading. Without children, `auto` falls back to `text` lines.
|
|
54
|
+
|
|
55
|
+
## More examples
|
|
56
|
+
|
|
57
|
+
- [Animations](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--animations): Compare `shimmer`, `pulse`, and `wave` motion.
|
|
58
|
+
- [Tones](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--tones): Compare the `default`, `subtle`, and `accent` surfaces.
|
|
59
|
+
- [Profile card](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--profile-card): Combine circle, pill, block, and text placeholders into a card layout.
|
|
60
|
+
- [Shapes and sizes](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--shapes-and-sizes): Compare `text`, `rect`, `circle`, and `pill` geometry across the size scale.
|
|
61
|
+
- [Content transition](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--content-transition): Toggle `loading` to swap placeholder bars for resolved children without layout shift.
|
|
62
|
+
- [Auto](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--auto): Shape placeholders from a real profile card and toggle `loading` to reveal it in place.
|
|
63
|
+
|
|
64
|
+
## Motion
|
|
65
|
+
|
|
66
|
+
Shimmer moves a soft light band across the placeholder, with a short rest between passes. Pulse and wave use a restrained brightness change so the reserved shape stays visible. In `auto`, one animation drives every placeholder in step, and `wave` fades without a stagger. Existing `--kb-skeleton-*` motion tokens control timing; reduced-motion preferences and forced-colors mode use static placeholders.
|
|
67
|
+
|
|
68
|
+
## Reference
|
|
69
|
+
|
|
70
|
+
| Prop | Type | Default | Notes |
|
|
71
|
+
| ------------ | -------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
|
|
72
|
+
| `variant` | `text` / `rect` / `circle` / `pill` / `auto` | `text` | Matches typography, media blocks, avatars, or status chips; `auto` shapes from `children` |
|
|
73
|
+
| `size` | `sm` / `md` / `lg` | `md` | Scales line height and circle diameter |
|
|
74
|
+
| `lines` | `number` | `1` | Number of stacked lines when `variant="text"`; the final line shortens naturally |
|
|
75
|
+
| `width` | `number` / `string` | unset | Explicit inline size override (`px` number or CSS length) |
|
|
76
|
+
| `height` | `number` / `string` | unset | Explicit block size override (`px` number or CSS length) |
|
|
77
|
+
| `animated` | `boolean` | `true` | Enables motion that stops automatically under `prefers-reduced-motion` |
|
|
78
|
+
| `animation` | `shimmer` / `pulse` / `wave` / `none` | `"shimmer"` | Light sweep, fade, staggered fade across lines, or a static placeholder |
|
|
79
|
+
| `tone` | `default` / `subtle` / `accent` | `"default"` | Surface treatment: `default`, `subtle` recessed, or `accent` tinted |
|
|
80
|
+
| `loading` | `boolean` | `true` | Renders decorative placeholders when `true`, or `children` inside `.kb-skeleton-content` |
|
|
81
|
+
| `label` | `string` | `"Loading"` | Status announced while `variant="auto"` is loading |
|
|
82
|
+
| `classNames` | keyed classes | unset | Style `line`, `content`, or `status` |
|
|
83
|
+
|
|
84
|
+
## Related components
|
|
85
|
+
|
|
86
|
+
Use [`Spinner`](Spinner.md) for compact indeterminate waits, [`EmptyState`](EmptyState.md) when a query resolves with zero items, and [`Card`](Card.md) as the owning surface with `aria-busy="true"`.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Spinner
|
|
2
|
+
|
|
3
|
+
Signal an indeterminate wait when completion percentage is unknown. Pair standalone indicators with a clear status label, or mark the spinner decorative inside a button that already names its busy action.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-spinner--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Spinner } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return <Spinner label="Loading workspace" variant="orbit" appearance="pill" showLabel />;
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## More examples
|
|
19
|
+
|
|
20
|
+
- [Variants](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--variants): Compare the `ring`, `orbit`, `dots`, and `bars` indicators.
|
|
21
|
+
- [Pill](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--pill): Frame a spinner and its visible label as a compact status chip.
|
|
22
|
+
- [With label](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--with-label): Show the label next to the indicator so sighted users know what is loading.
|
|
23
|
+
- [Busy button](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--busy-button): Render a decorative spinner inside a disabled button during asynchronous submission.
|
|
24
|
+
- [Sizes and tones](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--sizes-and-tones): Match compact controls, inline status rows, or section-level waits.
|
|
25
|
+
|
|
26
|
+
## Motion
|
|
27
|
+
|
|
28
|
+
The ring expands and contracts through a continuous sweep. Orbit combines two opposing sweeps around a breathing core; dots lift in sequence and bars run a staggered wave. Motion uses the existing `--kb-spinner-*` duration, easing, and stagger tokens. Reduced-motion preferences leave a static indicator and retain the status label.
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
| Prop | Type | Default | Notes |
|
|
33
|
+
| ------------ | ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------ |
|
|
34
|
+
| `label` | `string` | `"Loading"` | Accessible status text announced by `role="status"` |
|
|
35
|
+
| `showLabel` | `boolean` | `false` | Renders `label` visibly beside the spinner instead of `.kb-sr-only` |
|
|
36
|
+
| `decorative` | `boolean` | `false` | Omits `role="status"` and sets `aria-hidden="true"` inside already-labeled controls |
|
|
37
|
+
| `size` | `sm` / `md` / `lg` | `md` | Scales the SVG indicator and accompanying label |
|
|
38
|
+
| `tone` | `current` / `accent` / `neutral` / `info` / `success` / `warning` / `danger` | `accent` | Stroke ink; use `current` inside buttons or badges to inherit text color |
|
|
39
|
+
| `variant` | `ring` / `orbit` / `dots` / `bars` | `ring` | Selects classic arc, dual counter-rotating orbit, staggered wave dots, or equalizer bars |
|
|
40
|
+
| `appearance` | `plain` / `pill` | `plain` | Wraps the indicator and label in a tinted status pill when set to `pill` |
|
|
41
|
+
| `classNames` | keyed classes | unset | Style `icon`, `track`, `arc`, `core`, `dot`, `bar`, or `label` |
|
|
42
|
+
|
|
43
|
+
## Related components
|
|
44
|
+
|
|
45
|
+
Use [`Progress`](Progress.md) when a numeric completion ratio exists, [`Skeleton`](Skeleton.md) to preserve layout geometry while loading content, and [`Status`](Status.md) for persistent state labels.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Split
|
|
2
|
+
|
|
3
|
+
Use `Split` for two columns with equal or different widths. Each child sits in a `.kb-split-track` wrapper. When space is tight, the columns stack in source order. This uses CSS alone and also works inside nested panels. Native HTML props and the matching `ref` pass through.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/layout-split--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Split } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<Split>
|
|
16
|
+
<section aria-labelledby="main-title">
|
|
17
|
+
<h2 id="main-title">Project</h2>
|
|
18
|
+
<p>Current work.</p>
|
|
19
|
+
</section>
|
|
20
|
+
<aside aria-label="Project details">Last updated today.</aside>
|
|
21
|
+
</Split>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## More examples
|
|
27
|
+
|
|
28
|
+
- [Stacked columns](https://kbui.kcb.pro/storybook/?path=/story/layout-split--responsive): Resize the available width and inspect reading order.
|
|
29
|
+
- [Readable column content](https://kbui.kcb.pro/storybook/?path=/story/layout-split--content-measures): Retain text measure within layout tracks.
|
|
30
|
+
- [Nested columns](https://kbui.kcb.pro/storybook/?path=/story/layout-split--nested): Inspect collapse behavior inside another layout.
|
|
31
|
+
|
|
32
|
+
## Reference
|
|
33
|
+
|
|
34
|
+
| Prop | Values | Default |
|
|
35
|
+
| ------------ | -------------------------------------------------- | --------- |
|
|
36
|
+
| `as` | `div` `section` `article` | `div` |
|
|
37
|
+
| `ratio` | `equal` (1:1) `wide-start` (2:1) `wide-end` (1:2) | `equal` |
|
|
38
|
+
| `collapse` | `sm` (32rem) `md` (48rem) `lg` (64rem) | `md` |
|
|
39
|
+
| `gap` | `none` `sm` `md` `lg`, same scale as `Inline` | `md` |
|
|
40
|
+
| `align` | `start` `center` `end` `baseline` `stretch` | `stretch` |
|
|
41
|
+
| `classNames` | `{ track?: string }`, applied to each column track | unset |
|
|
42
|
+
|
|
43
|
+
Provide two children, one per column. Empty conditional children add no track. The track controls column width, so `Text` keeps its line-length limit and nested token overrides affect only that nested layout. Set `as` explicitly when using an element other than the default. Use `Grid` when the number of children varies. See [Layout composition](https://github.com/KhallilB/kbui/blob/main/docs/guides/layout.md).
|
|
44
|
+
|
|
45
|
+
## Related components
|
|
46
|
+
|
|
47
|
+
Use [`Grid`](Grid.md) for a variable number of children and [`Container`](Container.md) for the page boundary.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Stack
|
|
2
|
+
|
|
3
|
+
Vertical flow with shared spacing: the block-axis counterpart to `Inline`. Children keep source and tab order; `Stack` adds no role, focus management or keyboard handling. Native props and matching ref pass through.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/layout-stack--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Button, Heading, Inline, Stack, Text } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<Stack as="section" aria-labelledby="billing-title">
|
|
16
|
+
<Heading level={2} size="md" id="billing-title">
|
|
17
|
+
Billing
|
|
18
|
+
</Heading>
|
|
19
|
+
<Text>Your plan renews on 1 December.</Text>
|
|
20
|
+
<Inline gap="sm">
|
|
21
|
+
<Button>Change plan</Button>
|
|
22
|
+
<Button variant="secondary">Download invoices</Button>
|
|
23
|
+
</Inline>
|
|
24
|
+
</Stack>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## More examples
|
|
30
|
+
|
|
31
|
+
- [Section rhythm](https://kbui.kcb.pro/storybook/?path=/story/layout-stack--sections): Nest sections with a wider outer gap.
|
|
32
|
+
- [Inline-axis alignment](https://kbui.kcb.pro/storybook/?path=/story/layout-stack--alignment): Compare stretched and content-width children.
|
|
33
|
+
- [Block-axis distribution](https://kbui.kcb.pro/storybook/?path=/story/layout-stack--justify): Push actions to the bottom of a fixed-height card.
|
|
34
|
+
- [Form fields](https://kbui.kcb.pro/storybook/?path=/story/layout-stack--form): Space fields and actions in a native form.
|
|
35
|
+
- [A native list](https://kbui.kcb.pro/storybook/?path=/story/layout-stack--list): Ordered steps without list chrome.
|
|
36
|
+
|
|
37
|
+
## Reference
|
|
38
|
+
|
|
39
|
+
| Prop | Values | Default |
|
|
40
|
+
| --------- | ------------------------------------------------------------- | --------- |
|
|
41
|
+
| `as` | `div` `section` `article` `aside` `ul` `ol` `nav` `form` | `div` |
|
|
42
|
+
| `gap` | `none` `sm` (0.5rem) `md` (1rem) `lg` (1.5rem) | `md` |
|
|
43
|
+
| `align` | `start` `center` `end` `stretch` | `stretch` |
|
|
44
|
+
| `justify` | `start` `center` `end` `between` | `start` |
|
|
45
|
+
|
|
46
|
+
Non-default native elements require an explicit `as`; native props and refs follow that element. Explicit layout props own their data attributes even when caller attributes conflict.
|
|
47
|
+
|
|
48
|
+
`gap` owns vertical rhythm: `Stack` removes block margins from its direct children and its own browser margins, padding and list markers. `align="stretch"` fills the stack's width; `start`, `center` and `end` size children to their content. `justify` distributes children only when the stack is taller than its content, for example with `style={{ blockSize: "100%" }}` inside a fixed-height parent.
|
|
49
|
+
|
|
50
|
+
A named `section` exposes a region landmark; name it with `aria-labelledby`. With `ul` or `ol`, use `li` children. `Stack` removes list markers, so include `role="list"` when Safari must keep announcing the list; see [MDN’s list-style accessibility guidance](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/list-style#accessibility). Override `--kb-layout-gap-sm`, `-md` or `-lg` on a subtree to change the shared scale. See [Layout composition](https://github.com/KhallilB/kbui/blob/main/docs/guides/layout.md).
|
|
51
|
+
|
|
52
|
+
## Related components
|
|
53
|
+
|
|
54
|
+
Use [`Inline`](Inline.md) for a wrapping row, [`Grid`](Grid.md) when items may share columns, and [`Split`](Split.md) for two columns that stack below a threshold.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Stat
|
|
2
|
+
|
|
3
|
+
Show a value with the label that explains it. Include units and a time period in the label or value when they affect the meaning.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-stat--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Stat } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return <Stat label="Open tasks" value={12} />;
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## More examples
|
|
19
|
+
|
|
20
|
+
- [A headline figure](https://kbui.kcb.pro/storybook/?path=/story/components-stat--display): Compare emphasis for one primary value.
|
|
21
|
+
- [Several measures](https://kbui.kcb.pro/storybook/?path=/story/components-stat--row): Keep labels beside comparable figures.
|
|
22
|
+
|
|
23
|
+
## Reference
|
|
24
|
+
|
|
25
|
+
| Prop | Type | Default | Notes |
|
|
26
|
+
| ------------ | ---------------- | -------- | -------------------------------------------------- |
|
|
27
|
+
| `label` | `ReactNode` | required | What the value measures; read before the value |
|
|
28
|
+
| `value` | `ReactNode` | required | Number or short text; include units where needed |
|
|
29
|
+
| `size` | `md` / `display` | `md` | Use display for one headline number, md for groups |
|
|
30
|
+
| `classNames` | keyed classes | unset | Style the label and value separately |
|
|
31
|
+
|
|
32
|
+
## Related components
|
|
33
|
+
|
|
34
|
+
Use [`Progress`](Progress.md) when the number represents completion and [`Status`](Status.md) for changing state.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# StatsRow
|
|
2
|
+
|
|
3
|
+
Show a few comparable metrics in a row, such as the key figures at the top of a dashboard. The row fills its region and wraps into more rows when narrow.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-statsrow--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Link, StatsRow } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<StatsRow aria-label="Store performance, September 2026">
|
|
16
|
+
<StatsRow.Item
|
|
17
|
+
label="Total revenue"
|
|
18
|
+
value="$48,250"
|
|
19
|
+
change="+12.8%"
|
|
20
|
+
trend="up"
|
|
21
|
+
tone="positive"
|
|
22
|
+
context="vs. previous month"
|
|
23
|
+
link={<Link href="/revenue">View revenue</Link>}
|
|
24
|
+
/>
|
|
25
|
+
<StatsRow.Item
|
|
26
|
+
label="Orders"
|
|
27
|
+
value="625"
|
|
28
|
+
change="+8.7%"
|
|
29
|
+
trend="up"
|
|
30
|
+
tone="positive"
|
|
31
|
+
context="vs. previous month"
|
|
32
|
+
/>
|
|
33
|
+
<StatsRow.Item
|
|
34
|
+
label="Refund requests"
|
|
35
|
+
value="38"
|
|
36
|
+
change="+12 requests"
|
|
37
|
+
trend="up"
|
|
38
|
+
tone="negative"
|
|
39
|
+
context="vs. previous month"
|
|
40
|
+
/>
|
|
41
|
+
</StatsRow>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Items share equal columns no narrower than `--kb-statsrow-item-min-width` (10rem) and fill the row. Below that width they wrap into more rows, so no screen size scrolls sideways. Labels, values, changes and links each share a track across a row, so a label that wraps to two lines keeps the values beside it aligned.
|
|
47
|
+
|
|
48
|
+
## More examples
|
|
49
|
+
|
|
50
|
+
- [Outlined with links](https://kbui.kcb.pro/storybook/?path=/story/components-statsrow--outlined): Put each metric on a card surface and link to its detail screen.
|
|
51
|
+
- [Direction and tone](https://kbui.kcb.pro/storybook/?path=/story/components-statsrow--direction-and-tone): Set the direction glyph apart from whether the change is good news.
|
|
52
|
+
- [Compact wrap](https://kbui.kcb.pro/storybook/?path=/story/components-statsrow--wrap): See six metrics wrap at the widths of 390 and 768 pixel screens.
|
|
53
|
+
|
|
54
|
+
## Reference
|
|
55
|
+
|
|
56
|
+
`StatsRow` renders a `ul`; other native `ul` props, including `aria-label` and `aria-labelledby`, pass through to it.
|
|
57
|
+
|
|
58
|
+
| Prop | Type | Default | Notes |
|
|
59
|
+
| ------------ | --------------------- | ------- | --------------------------------------------------------- |
|
|
60
|
+
| `appearance` | `plain` / `outlined` | `plain` | Plain metrics on the page, or each metric on a card surface |
|
|
61
|
+
| `children` | `StatsRow.Item` nodes | unset | One item per metric |
|
|
62
|
+
|
|
63
|
+
`StatsRow.Item` renders an `li` around a [`Stat`](Stat.md); other native `li` props pass through to it.
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Notes |
|
|
66
|
+
| ------------ | ----------------------------------- | --------- | --------------------------------------------------------------------------- |
|
|
67
|
+
| `label` | `ReactNode` | required | What the value measures; read first |
|
|
68
|
+
| `value` | `ReactNode` | required | The figure with its unit; tabular figures |
|
|
69
|
+
| `change` | `ReactNode` | unset | Change since the comparison period; its text states the direction, such as `+12.8%` |
|
|
70
|
+
| `trend` | `up` / `down` / `flat` | unset | Direction glyph before `change`; hidden from assistive technology; needs `change` |
|
|
71
|
+
| `tone` | `positive` / `negative` / `neutral` | `neutral` | Colors `change` by whether it is good news, apart from its direction; needs `change` |
|
|
72
|
+
| `context` | `ReactNode` | unset | Comparison period or freshness, such as `vs. previous month` |
|
|
73
|
+
| `link` | `ReactNode` | unset | `Link` to the detail behind the metric; aligned on the last row of the item |
|
|
74
|
+
| `classNames` | keyed classes | unset | Style `stat`, `label`, `value`, `trend`, `change`, `glyph`, `context`, `link` |
|
|
75
|
+
|
|
76
|
+
Keep units comparable across a row: one currency, the same precision and one comparison period. Write the direction into the change text; color and the glyph do not convey it on their own. Tone is color only, so when good or bad news is not obvious from the label, say it in the change or context text, such as `+12 requests, above target`.
|
|
77
|
+
|
|
78
|
+
## Related components
|
|
79
|
+
|
|
80
|
+
Use [`Stat`](Stat.md) for a single figure, [`Progress`](Progress.md) when a metric measures completion toward a target, [`DescriptionList`](DescriptionList.md) for labelled record details that are not comparable figures, and [`Grid`](Grid.md) for collections of cards that are not metrics.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Status
|
|
2
|
+
|
|
3
|
+
Use `Status` for a state such as running, blocked, or complete. Always include text so the meaning is clear without relying on color or an icon.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-status--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Status } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<Status tone="running" live>
|
|
16
|
+
Build running
|
|
17
|
+
</Status>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## More examples
|
|
23
|
+
|
|
24
|
+
- [Changing state](https://kbui.kcb.pro/storybook/?path=/story/components-status--live): Check how status updates are announced.
|
|
25
|
+
- [Supporting iconography](https://kbui.kcb.pro/storybook/?path=/story/components-status--with-icon): Keep meaning in text when an icon is present.
|
|
26
|
+
- [A compact state label](https://kbui.kcb.pro/storybook/?path=/story/components-status--chip): Compare a contained appearance; the icon leads the chip.
|
|
27
|
+
- [A chip without an icon](https://kbui.kcb.pro/storybook/?path=/story/components-status--chip-without-icon): The chip leads with a dot in the tone's color.
|
|
28
|
+
|
|
29
|
+
## Reference
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<Status tone="running" appearance="chip" icon={<PlayIcon />} live>
|
|
33
|
+
Running
|
|
34
|
+
</Status>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Prop | Values | Default | Notes |
|
|
38
|
+
| ------------ | ------------------------------------------------------------------ | --------- | ----------------------------------------------------------------------- |
|
|
39
|
+
| `children` | `ReactNode` | unset | State text such as Running or Blocked; keep it meaningful without color |
|
|
40
|
+
| `tone` | `neutral` / `info` / `running` / `success` / `warning` / `blocked` | `neutral` | Reinforces the written state |
|
|
41
|
+
| `appearance` | `plain` / `chip` | `plain` | Plain stays inline; chip adds separation with a tinted surface |
|
|
42
|
+
| `icon` | `ReactNode` | unset | Decorative; the text still names the state. Replaces a chip's dot |
|
|
43
|
+
| `live` | `boolean` | `false` | Adds `role=status` for changing text; does not move focus |
|
|
44
|
+
| `compact` | `boolean` | `false` | Tighter spacing and smaller text for dense layouts |
|
|
45
|
+
|
|
46
|
+
## Related components
|
|
47
|
+
|
|
48
|
+
Use [`Badge`](Badge.md) for static metadata, [`Progress`](Progress.md) for completion, and [`Callout`](Callout.md) for a fuller message.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# SupportingPane
|
|
2
|
+
|
|
3
|
+
Use `SupportingPane` for a page with one main task and supporting context beside it, such as a cart with its order summary or a record list with an inspector. It renders a main region and a named `aside` landmark. From 48rem of page content width the aside sits beside main at a fixed width while main fills the rest; below that it moves under main. It also frames the page: full width up to 80rem, centred, with 1, 1.5 and 2rem gutters. For two equal columns inside a section, use [`Split`](Split.md).
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/layout-supportingpane--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Button, Card, Heading, PageHeader, SupportingPane, Text } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<main>
|
|
16
|
+
<SupportingPane
|
|
17
|
+
asideLabelledBy="summary-title"
|
|
18
|
+
aside={
|
|
19
|
+
<Card as="div">
|
|
20
|
+
<Heading level={2} id="summary-title">
|
|
21
|
+
Order summary
|
|
22
|
+
</Heading>
|
|
23
|
+
<Text>Total $245.75</Text>
|
|
24
|
+
<Button>Continue to payment</Button>
|
|
25
|
+
</Card>
|
|
26
|
+
}
|
|
27
|
+
>
|
|
28
|
+
<PageHeader title="Your cart" description="Your sneakers are reserved for 15 minutes." />
|
|
29
|
+
<Text>2 items</Text>
|
|
30
|
+
</SupportingPane>
|
|
31
|
+
</main>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## More examples
|
|
37
|
+
|
|
38
|
+
- [Shoe cart](https://kbui.kcb.pro/storybook/?path=/story/layout-supportingpane--shoe-cart): Items, free-shipping progress and help in main; the order summary beside them, or below them on narrow screens.
|
|
39
|
+
- [Inspector](https://kbui.kcb.pro/storybook/?path=/story/layout-supportingpane--inspector): An order list with the selected order's details in the aside.
|
|
40
|
+
|
|
41
|
+
## Reference
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Default | Notes |
|
|
44
|
+
| --- | --- | --- | --- |
|
|
45
|
+
| `children` | `ReactNode` | unset | Main region content, starting with the page heading |
|
|
46
|
+
| `aside` | `ReactNode` | unset | Supporting content; omit it and main fills the page |
|
|
47
|
+
| `asideLabelledBy` | `string` | unset | Id of a visible heading inside the aside that names it |
|
|
48
|
+
| `asideLabel` | `string` | unset | Accessible name for the aside when it has no visible heading |
|
|
49
|
+
| `classNames` | `{ main?, aside? }` | unset | Classes for the regions |
|
|
50
|
+
|
|
51
|
+
Other native `div` props and `ref` pass through to the root. Main comes first in source order and the aside second at every width; nothing is reordered. Each region stacks its children with the pane's gap, so main content needs no extra wrapper.
|
|
52
|
+
|
|
53
|
+
Tokens: `--kb-supportingpane-max-width`, `--kb-supportingpane-gutter-sm`, `-md`, `-lg`, `--kb-supportingpane-gap` and `--kb-supportingpane-aside-width`. Gutters step at 48rem and 64rem of viewport width; the aside moves beside main at 48rem of the pane's own content width, so a pane inside a narrow parent stays stacked.
|
|
54
|
+
|
|
55
|
+
Place `SupportingPane` inside your page's `main` and start main content with the page's `h1`, such as a [`PageHeader`](PageHeader.md). Name the aside, preferably from its visible heading; the complementary landmark is allowed inside main. The aside does not stick or hide; your app owns any show and hide control and its focus.
|
|
56
|
+
|
|
57
|
+
## Related components
|
|
58
|
+
|
|
59
|
+
Use [`PageHeader`](PageHeader.md) to open main, [`Card`](Card.md) to group the aside, and [`Split`](Split.md) for proportional columns inside a section.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
Use `Switch` for a preference that takes effect as soon as it changes. Pass `checked` and update it in `onCheckedChange`; your app handles saving and form reset. `Switch` uses a labelled native checkbox with `role="switch"`. Use `Checkbox` when people are selecting items instead.
|
|
4
|
+
|
|
5
|
+
[All components](../../README.md#components) · [Usage](#usage) · [Examples](#more-examples) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-switch--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Switch } from "@kb.ui/react";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
|
|
14
|
+
export function Example() {
|
|
15
|
+
const [checked, setChecked] = useState(false);
|
|
16
|
+
return (
|
|
17
|
+
<Switch
|
|
18
|
+
label="Email notifications"
|
|
19
|
+
checked={checked}
|
|
20
|
+
onCheckedChange={setChecked}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## More examples
|
|
27
|
+
|
|
28
|
+
- [Form integration](https://kbui.kcb.pro/storybook/?path=/story/components-switch--native-form): Include an on/off value in a native form.
|
|
29
|
+
- [A retained setting](https://kbui.kcb.pro/storybook/?path=/story/components-switch--read-only): Show a setting while blocking edits.
|
|
30
|
+
- [Validation feedback](https://kbui.kcb.pro/storybook/?path=/story/components-switch--with-error): Associate a correction with the setting.
|
|
31
|
+
|
|
32
|
+
## Reference
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Notes |
|
|
35
|
+
| -------------------------------------- | ----------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
36
|
+
| `label` | `string` | required | Associated visible label and accessible name |
|
|
37
|
+
| `checked` | `boolean` | required | Current controlled state |
|
|
38
|
+
| `onCheckedChange` | `(checked: boolean) => void` | required | Requests next state; owner updates checked |
|
|
39
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | Visual track size (`36×20px`, `44×24px`, `56×32px`); `Fieldset` defaults nested switches to `"sm"` while keeping a 44px touch target |
|
|
40
|
+
| `tone` | `"accent" \| "neutral" \| "info" \| "success" \| "warning" \| "danger"` | `"accent"` | Checked-state track tone when `onTone` is unset |
|
|
41
|
+
| `offTone` / `onTone` | `SwitchTone` | `"neutral"` / `tone` | Independent track tone for unchecked and checked sides |
|
|
42
|
+
| `offColor` / `onColor` | `string` | | Custom CSS color for the unchecked or checked track |
|
|
43
|
+
| `description` / `error` | `string` | | Associated helper/error text; error sets `aria-invalid` |
|
|
44
|
+
| `disabled` / `readOnly` | `boolean` | `false` | Disabled blocks focus/changes; read-only keeps focus and form value while blocking edits |
|
|
45
|
+
| `visuallyHidden` | `boolean` | `false` | Hide label visually, keep its accessible name |
|
|
46
|
+
| `offIcon` / `onIcon` | `ReactNode` | | Decorative slots; do not place interactive content inside |
|
|
47
|
+
| `name` / `value` / `form` / `required` | native `input` props | | Native form ownership, successful value and validation |
|
|
48
|
+
| `ref` | `Ref<HTMLInputElement>` | | Native checkbox, never an extra hidden control |
|
|
49
|
+
| `className` / `controlClassName` | `string` | | Root/native `input` class |
|
|
50
|
+
| `style` | `CSSProperties` | | Native input styles; CSS custom properties also reach visible track and thumb |
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { useState } from "react";
|
|
54
|
+
import { Switch } from "@kb.ui/react";
|
|
55
|
+
|
|
56
|
+
export function Preference() {
|
|
57
|
+
const [checked, setChecked] = useState(false);
|
|
58
|
+
return (
|
|
59
|
+
<Switch
|
|
60
|
+
label="Email updates"
|
|
61
|
+
checked={checked}
|
|
62
|
+
onCheckedChange={setChecked}
|
|
63
|
+
name="updates"
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Import `useState` from React and `Switch` from `@kb.ui/react`. Clicking or pressing Space calls `onCheckedChange`. Unchecked or disabled controls submit no value; a checked control submits its native value (`"on"` unless you supply one). Reset `checked` in the form’s `onReset` handler when needed. Use `offTone`/`onTone` or `offColor`/`onColor` when both sides of a toggle carry distinct state colors. The `switch` token group controls its appearance in both themes, and reduced motion removes the thumb’s travel animation.
|
|
70
|
+
|
|
71
|
+
## Related components
|
|
72
|
+
|
|
73
|
+
Use [`Checkbox`](Checkbox.md) for a choice submitted with other answers and [`RadioGroup`](RadioGroup.md) for one of several settings.
|