@kb.ui/react 0.10.3 → 0.11.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 +130 -708
- 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/CopyableText/CopyableText.d.ts +38 -0
- package/dist/components/CopyableText/content.d.ts +14 -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/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/Popover/Popover.d.ts +55 -0
- package/dist/components/Skeleton/Skeleton.d.ts +32 -0
- package/dist/components/Spinner/Spinner.d.ts +26 -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 +29 -4
- package/dist/index.js +3510 -1232
- 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/Container.md +41 -0
- package/docs/components/CopyableText.md +93 -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 +46 -0
- package/docs/components/Fieldset.md +42 -0
- package/docs/components/FileInput.md +74 -0
- package/docs/components/FormActions.md +45 -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/Panel.md +145 -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/Skeleton.md +46 -0
- package/docs/components/Spinner.md +40 -0
- package/docs/components/Split.md +47 -0
- package/docs/components/Stat.md +34 -0
- package/docs/components/Status.md +47 -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,69 @@
|
|
|
1
|
+
# RadioGroup
|
|
2
|
+
|
|
3
|
+
Use RadioGroup when people need to choose one option and see all the choices at once. Give the group a label and each item a unique string value. Arrow keys change the selection and skip disabled options.
|
|
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-radiogroup--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { RadioGroup } from "@kb.ui/react";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
|
|
14
|
+
export function Example() {
|
|
15
|
+
const [value, setValue] = useState<string | null>("weekly");
|
|
16
|
+
return (
|
|
17
|
+
<RadioGroup label="Frequency" value={value} onValueChange={setValue}>
|
|
18
|
+
<RadioGroup.Item value="daily">Daily</RadioGroup.Item>
|
|
19
|
+
<RadioGroup.Item value="weekly">Weekly</RadioGroup.Item>
|
|
20
|
+
</RadioGroup>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## More examples
|
|
26
|
+
|
|
27
|
+
- [An unanswered choice](https://kbui.kcb.pro/storybook/?path=/story/components-radiogroup--empty-selection): Start without a selected option.
|
|
28
|
+
- [Segmented choices](https://kbui.kcb.pro/storybook/?path=/story/components-radiogroup--segmented): Compare a visual treatment with the same single-choice contract.
|
|
29
|
+
- [Validation feedback](https://kbui.kcb.pro/storybook/?path=/story/components-radiogroup--invalid): Explain why a choice is required.
|
|
30
|
+
|
|
31
|
+
## Reference
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Default | Notes |
|
|
34
|
+
| ----------------------- | --------------------------- | ------------ | -------------------------------------------------------- |
|
|
35
|
+
| `label` | `string` | required | Visible accessible group label |
|
|
36
|
+
| `value` | `string \| null` | required | Controlled choice; null means no choice |
|
|
37
|
+
| `onValueChange` | `(value: string) => void` | required | Next choice request |
|
|
38
|
+
| `appearance` | `"standard" \| "segmented"` | `"standard"` | Segmented tray for compact single-choice controls |
|
|
39
|
+
| `selectionMotion` | `"slide" \| "none"` | `"slide"` | Segmented selection background glides or moves instantly |
|
|
40
|
+
| `selectionTone` | `"primary" \| "neutral"` | `"primary"` | Accent pill by default; neutral uses the raised surface |
|
|
41
|
+
| `disabled` | `boolean` | `false` | Disable every item |
|
|
42
|
+
| `name` | `string` | | Native form field name |
|
|
43
|
+
| `description` / `error` | `string` | | Associated help and invalid-state text |
|
|
44
|
+
| `visuallyHidden` | `boolean` | `false` | Hide group label visually |
|
|
45
|
+
| `ref` | `Ref<HTMLDivElement>` | | Group root |
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<RadioGroup
|
|
49
|
+
label="Density"
|
|
50
|
+
name="density"
|
|
51
|
+
value={density}
|
|
52
|
+
onValueChange={setDensity}
|
|
53
|
+
>
|
|
54
|
+
<RadioGroup.Item value="compact">Compact</RadioGroup.Item>
|
|
55
|
+
<RadioGroup.Item value="comfortable">Comfortable</RadioGroup.Item>
|
|
56
|
+
</RadioGroup>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`RadioGroup.Item` forwards Base UI Radio props, including `value`, `disabled` and the native control ref. `className` styles the item label; `controlClassName` styles its radio slot. The group uses the shared theme colors and shadows. Adjust the control size with `--kb-radiogroup-size` and the spacing with `--kb-radiogroup-gap`.
|
|
60
|
+
|
|
61
|
+
Set `appearance="segmented"` for compact choices such as view, density, or a filter. The control still behaves as a radio group, rather than tabs with associated panels. Your app manages the value and resets it when the form resets. An item’s `required` prop participates in native form validation. Changing the appearance keeps the same controls and focus.
|
|
62
|
+
|
|
63
|
+
The segmented selection uses a pill shape with the primary accent color by default. Set `selectionTone="neutral"` for a raised surface with neutral text and borders. Both tones follow the current light or dark theme. The background slides along the padded track and follows option widths, wrapped rows and layout changes. Set `selectionMotion="none"` for instant changes. Reduced-motion preferences disable movement regardless of this setting; forced-colors mode uses the selected option’s system highlight.
|
|
64
|
+
|
|
65
|
+
In dark mode, the primary pill uses a darker orange with white text for contrast. Override `--kb-radiogroup-primary-background` and `--kb-radiogroup-primary-color` together to customize this pair without changing other primary controls.
|
|
66
|
+
|
|
67
|
+
## Related components
|
|
68
|
+
|
|
69
|
+
Use [Checkbox](Checkbox.md) for independent choices and [Select](Select.md) when the options belong in a dropdown.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# ScrollArea
|
|
2
|
+
|
|
3
|
+
Keep logs, activity, or other long content inside a height cap. Let ordinary page content scroll with the page when a separate region is unnecessary.
|
|
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-scrollarea--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { ScrollArea } from "@kb.ui/react";
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
return (
|
|
15
|
+
<ScrollArea label="Activity log" maxHeight="12rem">
|
|
16
|
+
<p>Project created.</p>
|
|
17
|
+
<p>Review requested.</p>
|
|
18
|
+
</ScrollArea>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## More examples
|
|
24
|
+
|
|
25
|
+
- [Keyboard scrolling](https://kbui.kcb.pro/storybook/?path=/story/components-scrollarea--default): Focus the named scrolling region and try the keyboard.
|
|
26
|
+
|
|
27
|
+
## Reference
|
|
28
|
+
|
|
29
|
+
| Prop | Type | Default | Notes |
|
|
30
|
+
| ------------ | ----------------- | -------- | ------------------------------------------------- |
|
|
31
|
+
| `label` | `string` | required | Accessible name of the focusable scrolling region |
|
|
32
|
+
| `children` | `ReactNode` | required | Content inside the viewport |
|
|
33
|
+
| `maxHeight` | CSS length string | unset | Height cap, such as 12rem; longer content scrolls |
|
|
34
|
+
| `classNames` | keyed classes | unset | Style viewport, scrollbar, or thumb |
|
|
35
|
+
|
|
36
|
+
Tab reaches the viewport so keyboard users can scroll it. Keep the focus indicator visible and give the region a specific name such as Build output.
|
|
37
|
+
|
|
38
|
+
## Related components
|
|
39
|
+
|
|
40
|
+
Use [Panel](Panel.md) to group the scrolling content with its heading and actions.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Select
|
|
2
|
+
|
|
3
|
+
Use Select to choose one option from a dropdown. Each option has a string value, a visible label, and an optional disabled flag. Pass `null` to show the placeholder. Your app stores the selected value and decides whether it is valid.
|
|
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-select--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Select } from "@kb.ui/react";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
|
|
14
|
+
export function Example() {
|
|
15
|
+
const [value, setValue] = useState<string | null>(null);
|
|
16
|
+
return (
|
|
17
|
+
<Select
|
|
18
|
+
label="Frequency"
|
|
19
|
+
value={value}
|
|
20
|
+
onValueChange={setValue}
|
|
21
|
+
options={[
|
|
22
|
+
{ value: "daily", label: "Daily" },
|
|
23
|
+
{ value: "weekly", label: "Weekly" },
|
|
24
|
+
]}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## More examples
|
|
31
|
+
|
|
32
|
+
- [No available options](https://kbui.kcb.pro/storybook/?path=/story/components-select--empty): Inspect the empty helper and field description.
|
|
33
|
+
- [Validation feedback](https://kbui.kcb.pro/storybook/?path=/story/components-select--invalid): Explain a selection that needs correction.
|
|
34
|
+
- [A retained selection](https://kbui.kcb.pro/storybook/?path=/story/components-select--read-only): Keep the chosen value while preventing changes.
|
|
35
|
+
|
|
36
|
+
## Reference
|
|
37
|
+
|
|
38
|
+
| Prop | Type | Default | Notes |
|
|
39
|
+
| ------------------------------------- | ---------------------------------- | -------------------- | --------------------------------------------------------- |
|
|
40
|
+
| `label` | `string` | required | Visible field label and accessible popup name |
|
|
41
|
+
| `value` | `string \| null` | required | Controlled selection; null means unset |
|
|
42
|
+
| `onValueChange` | `(value: string \| null) => void` | required | Next valid choice request |
|
|
43
|
+
| `options` | `readonly SelectOption[]` | required | Ordered unique values, labels and optional disabled flags |
|
|
44
|
+
| `placeholder` | `string` | `"Choose an option"` | Text for unset values |
|
|
45
|
+
| `description` / `error` | `string` | | Associated help and invalid-state text |
|
|
46
|
+
| `disabled` / `readOnly` | `boolean` | `false` | Prevent edits; disabled also blocks form submission |
|
|
47
|
+
| `name` | `string` | | Native hidden form field name |
|
|
48
|
+
| `container` | `Select.Portal.Props["container"]` | field root | Portal host; default retains nested theme |
|
|
49
|
+
| `controlClassName` / `popupClassName` | `string` | | Trigger and popup slot classes |
|
|
50
|
+
| `className` / `ref` | root div props | | Wrapper class and native root ref |
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<Select
|
|
54
|
+
label="View"
|
|
55
|
+
name="view"
|
|
56
|
+
value={view}
|
|
57
|
+
onValueChange={setView}
|
|
58
|
+
options={[
|
|
59
|
+
{ value: "recent", label: "Recent" },
|
|
60
|
+
{ value: "all", label: "All records" },
|
|
61
|
+
]}
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use the arrow keys or type to find an option, Enter to select it, and Escape to close the popup and return focus. Disabled options cannot be selected. When there are no options, the trigger is disabled and “No options available” appears below it. Opening the popup leaves the page scrollable. Pointer selection returns focus without a keyboard ring; keyboard dismissal keeps a visible focus indicator.
|
|
66
|
+
|
|
67
|
+
By default, the popup mounts inside the field root and inherits its theme. If you provide a custom `container`, apply the theme there too. Use `--kb-select-popup-min-width`, `--kb-select-max-height`, and `--kb-select-layer` to adjust the popup’s size and stacking order.
|
|
68
|
+
|
|
69
|
+
## Related components
|
|
70
|
+
|
|
71
|
+
Use [RadioGroup](RadioGroup.md) for a visible set of choices and [Menu](Menu.md) for actions.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Separator
|
|
2
|
+
|
|
3
|
+
Native hr thematic break; decorative dividers are hidden from assistive technology. Native hr props and ref pass through; orientation and decorative own role, aria-hidden and aria-orientation.
|
|
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,46 @@
|
|
|
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
|
+
## More examples
|
|
23
|
+
|
|
24
|
+
- [Wave, pulse, and accent synthesis](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--wave-and-pulse): Choreograph staggered multi-line wave cascades, breathing pulse blocks, and warm accent-tinted synthesis placeholders.
|
|
25
|
+
- [Structured card placeholder](https://kbui.kcb.pro/storybook/?path=/story/components-skeleton--card-placeholder): Combine avatar circles, pills, rectangular wells, and multi-line text placeholders.
|
|
26
|
+
- [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.
|
|
27
|
+
- [Loading-to-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.
|
|
28
|
+
|
|
29
|
+
## Reference
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Default | Notes |
|
|
32
|
+
| ------------ | ------------------------------------- | ----------- | ----------------------------------------------------------------------------------------- |
|
|
33
|
+
| `variant` | `text` / `rect` / `circle` / `pill` | `text` | Matches incoming typography, media blocks, avatars, or status chips |
|
|
34
|
+
| `size` | `sm` / `md` / `lg` | `md` | Scales line height and circle diameter |
|
|
35
|
+
| `lines` | `number` | `1` | Number of stacked lines when `variant="text"`; the final line shortens naturally |
|
|
36
|
+
| `width` | `number` / `string` | unset | Explicit inline size override (`px` number or CSS length) |
|
|
37
|
+
| `height` | `number` / `string` | unset | Explicit block size override (`px` number or CSS length) |
|
|
38
|
+
| `animated` | `boolean` | `true` | Enables motion that stops automatically under `prefers-reduced-motion` |
|
|
39
|
+
| `animation` | `shimmer` / `pulse` / `wave` / `none` | `"shimmer"` | Selects specular sweep, breathing pulse, staggered multi-line wave, or static placeholder |
|
|
40
|
+
| `tone` | `default` / `subtle` / `accent` | `"default"` | Surface treatment (`default` surface, `subtle` recessed well, or `accent` synthesis tint) |
|
|
41
|
+
| `loading` | `boolean` | `true` | Renders decorative placeholders when `true`, or `children` inside `.kb-skeleton-content` |
|
|
42
|
+
| `classNames` | keyed classes | unset | Style `line` or `content` |
|
|
43
|
+
|
|
44
|
+
## Related components
|
|
45
|
+
|
|
46
|
+
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,40 @@
|
|
|
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
|
+
- [Fancy variants and status pills](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--fancy-variants): Compare `ring`, `orbit`, `dots`, and `bars` indicators alongside elevated `pill` status framing.
|
|
21
|
+
- [Visible status label](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--with-visible-label): Pair the animated arc with explicit text describing what is loading.
|
|
22
|
+
- [Busy button submission](https://kbui.kcb.pro/storybook/?path=/story/components-spinner--busy-button): Render a decorative spinner inside a disabled button during asynchronous submission.
|
|
23
|
+
- [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.
|
|
24
|
+
|
|
25
|
+
## Reference
|
|
26
|
+
|
|
27
|
+
| Prop | Type | Default | Notes |
|
|
28
|
+
| ------------ | ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------ |
|
|
29
|
+
| `label` | `string` | `"Loading"` | Accessible status text announced by `role="status"` |
|
|
30
|
+
| `showLabel` | `boolean` | `false` | Renders `label` visibly beside the spinner instead of `.kb-sr-only` |
|
|
31
|
+
| `decorative` | `boolean` | `false` | Omits `role="status"` and sets `aria-hidden="true"` inside already-labeled controls |
|
|
32
|
+
| `size` | `sm` / `md` / `lg` | `md` | Scales the SVG indicator and accompanying label |
|
|
33
|
+
| `tone` | `current` / `accent` / `neutral` / `info` / `success` / `warning` / `danger` | `accent` | Stroke ink; use `current` inside buttons or badges to inherit text color |
|
|
34
|
+
| `variant` | `ring` / `orbit` / `dots` / `bars` | `ring` | Selects classic arc, dual counter-rotating orbit, staggered wave dots, or equalizer bars |
|
|
35
|
+
| `appearance` | `plain` / `pill` | `plain` | Wraps the indicator and label in a tinted status pill when set to `pill` |
|
|
36
|
+
| `classNames` | keyed classes | unset | Style `icon`, `track`, `arc`, `core`, `dot`, `bar`, or `label` |
|
|
37
|
+
|
|
38
|
+
## Related components
|
|
39
|
+
|
|
40
|
+
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
|
+
Two children form equal or weighted columns through layout-owned `.kb-split-track` wrappers. Below the available-width threshold, columns stack in source order. Layout uses CSS alone, including inside nested panels. 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-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; empty conditional children add no track. Each track owns column sizing, so Text keeps its reading measure and nested token overrides stay local. Non-default generic native elements require an explicit `as`. Use Grid for variable child counts. 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,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,47 @@
|
|
|
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): Inspect the status announcement contract.
|
|
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.
|
|
27
|
+
|
|
28
|
+
## Reference
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<Status tone="running" appearance="chip" icon={<PlayIcon />} live>
|
|
32
|
+
Running
|
|
33
|
+
</Status>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Prop | Values | Default | Notes |
|
|
37
|
+
| ------------ | ------------------------------------------------------------------ | --------- | ----------------------------------------------------------------------- |
|
|
38
|
+
| `children` | `ReactNode` | unset | State text such as Running or Blocked; keep it meaningful without color |
|
|
39
|
+
| `tone` | `neutral` / `info` / `running` / `success` / `warning` / `blocked` | `neutral` | Reinforces the written state |
|
|
40
|
+
| `appearance` | `plain` / `chip` | `plain` | Plain stays inline; chip adds separation with a tinted surface |
|
|
41
|
+
| `icon` | `ReactNode` | unset | Optional decorative icon; the text still names the state |
|
|
42
|
+
| `live` | `boolean` | `false` | Adds role=status for changing text; does not move focus |
|
|
43
|
+
| `compact` | `boolean` | `false` | Tighter spacing and smaller text for dense layouts |
|
|
44
|
+
|
|
45
|
+
## Related components
|
|
46
|
+
|
|
47
|
+
Use [Badge](Badge.md) for static metadata, [Progress](Progress.md) for completion, and [Callout](Callout.md) for a fuller message.
|
|
@@ -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.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Table
|
|
2
|
+
|
|
3
|
+
Present related records with native table semantics, optional controlled sorting and selection, and independent row actions. Your app owns records, stable IDs, ordering, selection and requests.
|
|
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-table--docs)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import "@kb.ui/react/styles.css";
|
|
11
|
+
import { Table, type TableSortDirection } from "@kb.ui/react";
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
|
|
14
|
+
const records = [{ id: "ada", name: "Ada Chen" }, { id: "lin", name: "Lin Patel" }];
|
|
15
|
+
|
|
16
|
+
export function Example() {
|
|
17
|
+
const [direction, setDirection] = useState<TableSortDirection>("ascending");
|
|
18
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
19
|
+
const ordered = [...records].sort((a, b) => a.name.localeCompare(b.name) * (direction === "descending" ? -1 : 1));
|
|
20
|
+
const selectedCount = records.filter((record) => selected.includes(record.id)).length;
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<p role="status">{selectedCount} people selected</p>
|
|
24
|
+
<Table.ScrollContainer label="People scroll area" maxHeight="20rem">
|
|
25
|
+
<Table density="dense" stickyHeader>
|
|
26
|
+
<Table.Caption>People</Table.Caption>
|
|
27
|
+
<Table.Head><Table.Row>
|
|
28
|
+
<Table.ColumnHeader>
|
|
29
|
+
<Table.SelectionCheckbox visuallyHidden label="Select all people" checked={selectedCount === records.length} indeterminate={selectedCount > 0 && selectedCount < records.length} onCheckedChange={(checked) => setSelected(checked ? records.map((record) => record.id) : [])} />
|
|
30
|
+
</Table.ColumnHeader>
|
|
31
|
+
<Table.ColumnHeader sortDirection={direction} onSortChange={setDirection}>Name</Table.ColumnHeader>
|
|
32
|
+
<Table.ColumnHeader align="end">Actions</Table.ColumnHeader>
|
|
33
|
+
</Table.Row></Table.Head>
|
|
34
|
+
<Table.Body>{ordered.map((record) => (
|
|
35
|
+
<Table.Row key={record.id} selected={selected.includes(record.id)}>
|
|
36
|
+
<Table.Cell><Table.SelectionCheckbox visuallyHidden label={`Select ${record.name}`} checked={selected.includes(record.id)} onCheckedChange={(checked) => setSelected(checked ? [...selected, record.id] : selected.filter((id) => id !== record.id))} /></Table.Cell>
|
|
37
|
+
<Table.RowHeader>{record.name}</Table.RowHeader>
|
|
38
|
+
<Table.Cell><Table.RowActions><a href={`/people/${record.id}`}>View {record.name}</a></Table.RowActions></Table.Cell>
|
|
39
|
+
</Table.Row>
|
|
40
|
+
))}</Table.Body>
|
|
41
|
+
</Table>
|
|
42
|
+
</Table.ScrollContainer>
|
|
43
|
+
</>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## More examples
|
|
49
|
+
|
|
50
|
+
- [Sorting and selection](https://kbui.kcb.pro/storybook/?path=/story/components-table--sorting-and-selection): Numeric and text ordering, stable selected IDs, mixed selection and excluded rows.
|
|
51
|
+
- [Row actions](https://kbui.kcb.pro/storybook/?path=/story/components-table--sorting-and-selection): Named Buttons and Menu composition with focus return.
|
|
52
|
+
- [Dense and sticky](https://kbui.kcb.pro/storybook/?path=/story/components-table--dense-sticky): Bounded scrolling, sticky headers and a pinned first column.
|
|
53
|
+
|
|
54
|
+
## Reference
|
|
55
|
+
|
|
56
|
+
| Part | Native element | Purpose |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `Table` | `table` | Named data table; forwards table attributes, children and ref |
|
|
59
|
+
| `Table.ScrollContainer` | `section` | Named focusable scroll region; `label` required, `maxHeight` optional CSS length |
|
|
60
|
+
| `Table.Caption` | `caption` | Visible table name; use a caption or native `aria-label`/`aria-labelledby` |
|
|
61
|
+
| `Table.Head`, `Table.Body`, `Table.Foot` | `thead`, `tbody`, `tfoot` | Native row groups; `aria-busy` may mark pending rows |
|
|
62
|
+
| `Table.Row` | `tr` | `selected` projects visual selection; checkbox communicates checked state |
|
|
63
|
+
| `Table.ColumnHeader` | `th`, optional `button` | Defaults `scope="col"`; controlled sorting and logical alignment |
|
|
64
|
+
| `Table.RowHeader` | `th` | Defaults `scope="row"`; supports grouped header scope override |
|
|
65
|
+
| `Table.Cell` | `td` | Native data cell; supports `colSpan`, `rowSpan`, children and ref |
|
|
66
|
+
| `Table.SelectionCheckbox` | Checkbox | Same required `label`, `checked`, `onCheckedChange`, optional `indeterminate`, `disabled`, `readOnly`, ref and slots as Checkbox |
|
|
67
|
+
| `Table.RowActions` | `div` | Wrapping, end-aligned actions; compose named Buttons, links or Menu |
|
|
68
|
+
|
|
69
|
+
| Prop | Applies to | Default | Behavior |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `density` | Table | `comfortable` | `comfortable` or `dense`; controls cell spacing, preserves control targets |
|
|
72
|
+
| `layout` | Table | `auto` | `auto` or `fixed`; with fixed layout supply widths through native `colgroup`/`col` or styles |
|
|
73
|
+
| `stickyHeader` | Table | false | Pins the complete head, including grouped header rows, to the scroll boundary |
|
|
74
|
+
| `align` | Cell, ColumnHeader, RowHeader | `start` | Logical `start`, `center`, `end`; works with `dir="rtl"` |
|
|
75
|
+
| `sticky` | Cell, ColumnHeader, RowHeader | unset | Pins one `start` or `end` edge cell; match the same edge across rows |
|
|
76
|
+
| `sortDirection` | ColumnHeader | `none` | `none`, `ascending`, `descending`; explicit direction owns `aria-sort`, otherwise native `aria-sort` passes through |
|
|
77
|
+
| `onSortChange` | ColumnHeader | unset | Enables sort button; requests ascending from none, then toggles ascending/descending |
|
|
78
|
+
| `sortDisabled` | ColumnHeader | false | Disables sort button, preserves announced order |
|
|
79
|
+
| `classNames` | ColumnHeader | unset | Adds `sortButton`, `sortIcon` slot classes; root uses `className` |
|
|
80
|
+
|
|
81
|
+
Every part accepts its native element attributes, `style`, `className` and ref. The checkbox forwards its ref to the input. Public prop types follow `Table<Part>Props`; root uses `TableProps`, sorting uses `TableSortDirection`, shared cell options use `TableCellOptions`. The sort button is `type="button"`; sorting inside forms does not submit them. Put text and decorative content in sortable headers; nested interactive children would create invalid nested controls.
|
|
82
|
+
|
|
83
|
+
### Sorting and selection ownership
|
|
84
|
+
|
|
85
|
+
Sortable headings use the full cell as the button target. Unsorted headings show paired arrows; the applied order uses one arrow with stronger ink. Keep headings readable with native column widths and a bounded scroll container. Fixed-layout sortable headings wrap within their assigned columns. Reserve a compact checkbox column, align numeric headings with their values, and keep row action labels short while supplying record-specific accessible names. The sorting example places its title, instructions and selection count outside scrolling data, with visible text explaining unavailable selection.
|
|
86
|
+
|
|
87
|
+
Sort a copy of your data or request server ordering. Keep the column and direction together; reset other headers to `none` so only one header announces an active sort. For server requests, handle stale responses in your app, keep applied order authoritative, set `sortDisabled` while pending, and announce progress through a status message outside an `aria-busy` body. Table does not mutate or fetch records. It does not implement multiple simultaneous sort keys.
|
|
88
|
+
|
|
89
|
+
Keep selection by stable ID rather than visible row index. Define whether select-all covers the current page, filtered results or all records; label that scope explicitly. Compute mixed/all state from eligible rows only, exclude disabled rows, and disable select-all when no rows are eligible. Decide how removed records and page changes affect selection. `Table.Row selected` provides styling; selection controls own the accessible state. Row actions have their own names and normal Tab order, and do not toggle selection implicitly.
|
|
90
|
+
|
|
91
|
+
### Layout and feedback
|
|
92
|
+
|
|
93
|
+
Place the table inside `Table.ScrollContainer` for horizontal overflow or a bounded vertical viewport. Its region is keyboard focusable; `maxHeight` limits height. On focus, the React container reveals controls hidden beneath sticky headers or pinned edges without moving keyboard focus. Keep enough free viewport space for the action; a pinned column wider than the viewport cannot expose adjacent cells. Supply a readable minimum table width with `style` when columns should scroll rather than wrap. A table can also render directly when page scrolling is sufficient. To keep the table title fixed on both scroll axes, render a Heading outside ScrollContainer and name the table through `aria-labelledby`, as in Dense and sticky. Native Table.Caption remains part of the scrollable table. Column headings stay fixed vertically with stickyHeader and scroll horizontally with their data columns.
|
|
94
|
+
|
|
95
|
+
Sticky edges support one cell on each edge. For several pinned columns, calculate non-overlapping offsets in your own styles; Table does not assign column offsets. Keep sufficient viewport space for unpinned cells. Header/body column widths must match. Set `dir="rtl"` on the application or ScrollContainer as well as the table when the scroll direction should follow RTL; the stories expose a direction control. Nested tables keep their own density and section surfaces. Native `colSpan`, `rowSpan`, `scope="colgroup"` and explicit `id`/`headers` relationships support grouped headers. Sticky and selected cell backgrounds stay opaque in both themes; restyled background tokens must remain opaque.
|
|
96
|
+
|
|
97
|
+
Render empty or error feedback in a row containing a `Table.Cell colSpan={columnCount}`; supply retry as a named Button if appropriate. Use a separate status for asynchronous updates. Table preserves semantic HTML and ordinary Tab navigation; arrow-key cell navigation, pagination, filtering, virtualization and record management remain app-owned. For very large sets, paginate in your app rather than assuming all rows are virtualized.
|
|
98
|
+
|
|
99
|
+
Adjust `--kb-table-cell-padding-block`, `--kb-table-cell-padding-inline`, `--kb-table-dense-padding-block`, `--kb-table-background`, `--kb-table-header-background`, `--kb-table-selected-background`, `--kb-table-border`, `--kb-table-radius` and `--kb-table-sort-target` through normal CSS. Keep focus visible and dense action targets usable. See [accessibility verification](../../../../docs/guides/accessibility.md) for manual keyboard, screen-reader, zoom, spacing and contrast checks. Automated stories do not establish screen-reader interoperability or page conformance.
|
|
100
|
+
|
|
101
|
+
## Related components
|
|
102
|
+
|
|
103
|
+
Use [DescriptionList](DescriptionList.md) for labeled facts about one record and [CollectionList](CollectionList.md) with [CollectionRow](CollectionRow.md) for records with variable details. The [Structured data guide](../../../../docs/guides/structured-data.md) compares these choices.
|
|
104
|
+
|
|
105
|
+
Use [Checkbox](Checkbox.md) for independent selection, [Menu](Menu.md) for overflow actions, [Button](Button.md) for immediate actions, and [Status](Status.md) for meaningful asynchronous feedback. Use [Grid](Grid.md) for visual page layout rather than tabular relationships.
|