@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.
Files changed (109) hide show
  1. package/README.md +142 -707
  2. package/dist/components/Accordion/Accordion.d.ts +33 -0
  3. package/dist/components/Avatar/Avatar.d.ts +19 -0
  4. package/dist/components/Code/Code.d.ts +26 -3
  5. package/dist/components/Code/tokenize.d.ts +5 -0
  6. package/dist/components/CodeBlock/CodeBlock.d.ts +10 -0
  7. package/dist/components/Collection/Collection.d.ts +99 -0
  8. package/dist/components/Collection/useCollection.d.ts +66 -0
  9. package/dist/components/CollectionList/CollectionList.d.ts +12 -0
  10. package/dist/components/CollectionRow/CollectionRow.d.ts +17 -0
  11. package/dist/components/Combobox/Combobox.d.ts +14 -2
  12. package/dist/components/ConfirmAction/ConfirmAction.d.ts +42 -0
  13. package/dist/components/CopyableText/CopyableText.d.ts +38 -0
  14. package/dist/components/CopyableText/content.d.ts +14 -0
  15. package/dist/components/Dashboard/Dashboard.d.ts +17 -0
  16. package/dist/components/DescriptionList/DescriptionList.d.ts +20 -0
  17. package/dist/components/Dialog/Dialog.d.ts +3 -1
  18. package/dist/components/Disclosure/Disclosure.d.ts +21 -0
  19. package/dist/components/EmptyState/EmptyState.d.ts +30 -0
  20. package/dist/components/Form/Form.d.ts +19 -0
  21. package/dist/components/FormSection/FormSection.d.ts +26 -0
  22. package/dist/components/Gallery/Gallery.d.ts +26 -0
  23. package/dist/components/Grid/Grid.d.ts +17 -6
  24. package/dist/components/Image/Image.d.ts +20 -0
  25. package/dist/components/Link/Link.d.ts +15 -2
  26. package/dist/components/PageHeader/PageHeader.d.ts +27 -0
  27. package/dist/components/Panel/Panel.d.ts +3 -1
  28. package/dist/components/Popover/Popover.d.ts +55 -0
  29. package/dist/components/Settings/Settings.d.ts +11 -0
  30. package/dist/components/Skeleton/Skeleton.d.ts +34 -0
  31. package/dist/components/Spinner/Spinner.d.ts +26 -0
  32. package/dist/components/Stack/Stack.d.ts +15 -0
  33. package/dist/components/StatsRow/StatsRow.d.ts +33 -0
  34. package/dist/components/SupportingPane/SupportingPane.d.ts +15 -0
  35. package/dist/components/Table/Table.d.ts +65 -0
  36. package/dist/components/Tabs/Tabs.d.ts +69 -0
  37. package/dist/components/Tabs/index.d.ts +1 -0
  38. package/dist/components/Thumbnail/Thumbnail.d.ts +14 -0
  39. package/dist/components/Toast/Toast.d.ts +72 -0
  40. package/dist/index.d.ts +39 -4
  41. package/dist/index.js +3901 -1238
  42. package/dist/index.js.map +1 -1
  43. package/dist/styles.css +1 -1
  44. package/dist/utils/CollapsiblePanel.d.ts +10 -0
  45. package/dist/utils/useClipboard.d.ts +28 -0
  46. package/docs/components/Accordion.md +66 -0
  47. package/docs/components/Avatar.md +80 -0
  48. package/docs/components/Badge.md +37 -0
  49. package/docs/components/Button.md +46 -0
  50. package/docs/components/Callout.md +41 -0
  51. package/docs/components/Card.md +41 -0
  52. package/docs/components/Checkbox.md +60 -0
  53. package/docs/components/Code.md +77 -0
  54. package/docs/components/CodeBlock.md +77 -0
  55. package/docs/components/Collection.md +183 -0
  56. package/docs/components/CollectionList.md +44 -0
  57. package/docs/components/CollectionRow.md +62 -0
  58. package/docs/components/Combobox.md +88 -0
  59. package/docs/components/ConfirmAction.md +100 -0
  60. package/docs/components/Container.md +41 -0
  61. package/docs/components/CopyableText.md +93 -0
  62. package/docs/components/Dashboard.md +81 -0
  63. package/docs/components/DescriptionList.md +61 -0
  64. package/docs/components/Dialog.md +84 -0
  65. package/docs/components/Disclosure.md +53 -0
  66. package/docs/components/EmptyState.md +50 -0
  67. package/docs/components/ErrorSummary.md +48 -0
  68. package/docs/components/Fieldset.md +42 -0
  69. package/docs/components/FileInput.md +74 -0
  70. package/docs/components/Form.md +67 -0
  71. package/docs/components/FormActions.md +45 -0
  72. package/docs/components/FormSection.md +57 -0
  73. package/docs/components/Gallery.md +84 -0
  74. package/docs/components/Grid.md +66 -0
  75. package/docs/components/Heading.md +40 -0
  76. package/docs/components/Image.md +62 -0
  77. package/docs/components/Inline.md +42 -0
  78. package/docs/components/Input.md +82 -0
  79. package/docs/components/Link.md +52 -0
  80. package/docs/components/Menu.md +44 -0
  81. package/docs/components/MultiSelect.md +59 -0
  82. package/docs/components/NumberField.md +65 -0
  83. package/docs/components/PageHeader.md +68 -0
  84. package/docs/components/Panel.md +153 -0
  85. package/docs/components/Popover.md +89 -0
  86. package/docs/components/Progress.md +37 -0
  87. package/docs/components/RadioGroup.md +69 -0
  88. package/docs/components/ScrollArea.md +40 -0
  89. package/docs/components/Select.md +71 -0
  90. package/docs/components/Separator.md +40 -0
  91. package/docs/components/Settings.md +57 -0
  92. package/docs/components/Skeleton.md +86 -0
  93. package/docs/components/Spinner.md +45 -0
  94. package/docs/components/Split.md +47 -0
  95. package/docs/components/Stack.md +54 -0
  96. package/docs/components/Stat.md +34 -0
  97. package/docs/components/StatsRow.md +80 -0
  98. package/docs/components/Status.md +48 -0
  99. package/docs/components/SupportingPane.md +59 -0
  100. package/docs/components/Switch.md +73 -0
  101. package/docs/components/Table.md +105 -0
  102. package/docs/components/Tabs.md +89 -0
  103. package/docs/components/Text.md +36 -0
  104. package/docs/components/Textarea.md +47 -0
  105. package/docs/components/Thumbnail.md +66 -0
  106. package/docs/components/Toast.md +130 -0
  107. package/docs/components/Toolbar.md +39 -0
  108. package/docs/components/Tooltip.md +42 -0
  109. package/package.json +3 -2
@@ -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. In auto layout, headings and cells keep whole words, so a table narrower than its longest words scrolls instead of breaking them; supply a minimum table width with `style` when columns need more room. Fixed layout breaks long words within its assigned columns. 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.
@@ -0,0 +1,89 @@
1
+ # Tabs
2
+
3
+ Switch between peer panels within one page. Use links for navigation to another URL and `RadioGroup` for a single form choice.
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-tabs--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Tabs } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return (
15
+ <Tabs defaultValue="summary">
16
+ <Tabs.List aria-label="Project sections">
17
+ <Tabs.Tab value="summary">Summary</Tabs.Tab>
18
+ <Tabs.Tab value="activity" badge="3">Activity</Tabs.Tab>
19
+ </Tabs.List>
20
+ <Tabs.Panel value="summary">Project summary</Tabs.Panel>
21
+ <Tabs.Panel value="activity">Recent activity</Tabs.Panel>
22
+ </Tabs>
23
+ );
24
+ }
25
+ ```
26
+
27
+ ## More examples
28
+
29
+ - [Section headers](https://kbui.kcb.pro/storybook/?path=/story/components-tabs--default): Select a release panel with arrow keys or a pointer.
30
+ - [Compact time windows](https://kbui.kcb.pro/storybook/?path=/story/components-tabs--pill): Small pill tabs with a disabled option.
31
+ - [Vertical settings](https://kbui.kcb.pro/storybook/?path=/story/components-tabs--vertical): Up/Down navigation beside settings content.
32
+ - [Retained settings draft](https://kbui.kcb.pro/storybook/?path=/story/components-tabs--retained-draft): Manual activation retains an input while its panel is hidden.
33
+
34
+ - [Nested panels](https://kbui.kcb.pro/storybook/?path=/story/components-tabs--nested): Each `Tabs` root owns its orientation, density and variant.
35
+
36
+ ## Reference
37
+
38
+ | Part | Responsibility |
39
+ | --- | --- |
40
+ | `Tabs` | Selection owner, orientation, appearance and shared class names |
41
+ | `Tabs.List` | Named tab list with roving keyboard focus; inserts an indicator by default |
42
+ | `Tabs.Tab` | Named trigger with a unique value matching its panel |
43
+ | `Tabs.Indicator` | Optional explicit active indicator inside the list |
44
+ | `Tabs.Panel` | Content associated with a matching trigger |
45
+
46
+ | `Tabs` prop | Type | Default | Purpose |
47
+ | --- | --- | --- | --- |
48
+ | `value` | `string \| number \| null` | — | Controlled selection; null selects no panel |
49
+ | `defaultValue` | `string \| number \| null` | First enabled tab | Initial uncontrolled selection; null selects none |
50
+ | `onValueChange` | `(value, details) => void` | — | Selection request with Base UI reason, event and cancel method |
51
+ | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout and keyboard axis |
52
+ | `variant` | `"line" \| "pill"` | `"line"` | Underline or raised active surface |
53
+ | `size` | `"sm" \| "md"` | `"md"` | Trigger density |
54
+ | `className` | `string` | — | Root class |
55
+ | `classNames` | `ClassNames<TabsClassKey>` | — | root, list, tab, `tabIcon`, `tabLabel`, `tabBadge`, indicator, panel |
56
+
57
+ | Part prop | Type | Default | Purpose |
58
+ | --- | --- | --- | --- |
59
+ | `Tabs.List.activateOnFocus` | `boolean` | `true` | Select with arrow-key focus; false requires Enter/Space |
60
+ | `Tabs.List.loopFocus` | `boolean` | `true` | Wrap focus at list ends |
61
+ | `Tabs.List.showIndicator` | `boolean` | `true` | Insert automatic indicator; false leaves authored indicators intact |
62
+ | `Tabs.Tab.value` | `string \| number` | Required | Stable unique selection key |
63
+ | `Tabs.Tab.disabled` | `boolean` | `false` | Prevent selection; remain discoverable with arrow keys |
64
+ | `Tabs.Tab.icon` | `ReactNode` | — | Decorative leading icon |
65
+ | `Tabs.Tab.badge` | `ReactNode` | — | Trailing count/status included in accessible name |
66
+ | `Tabs.Panel.value` | `string \| number` | Required | Matching trigger value |
67
+ | `Tabs.Panel.keepMounted` | `boolean` | `false` | Retain hidden DOM and local draft state |
68
+
69
+ All parts forward refs, native element props and Base UI composition props; `className` accepts a string. Keep triggers and panels inside their `Tabs` root. Put an explicit indicator directly inside `Tabs.List`, or set `showIndicator` to false when supplying a custom composition. Use unique values within each root and avoid interactive elements inside tab labels or badges.
70
+
71
+ ## Selection and focus
72
+
73
+ Base UI owns selection, tab/panel relationships and roving focus. Tab enters the selected trigger; Left/Right moves horizontal focus, Up/Down moves vertical focus, and Home/End reaches the first/last trigger. Disabled tabs can receive arrow-key focus but cannot be selected. Automatic activation selects enabled tabs while moving; manual activation requires Enter or Space. Controlled values change only when the parent updates them. A null value selects no tab.
74
+
75
+ Uncontrolled roots recover to an enabled tab when the selected tab is removed or disabled, reporting the reason through `onValueChange`. Controlled recovery belongs to the parent. User selection can be cancelled through details.cancel(); automatic fallback cannot. Applications own fetching, loading feedback and content availability. Prefer manual activation for panels that require loading.
76
+
77
+ Inactive panels unmount by default. `keepMounted` preserves their DOM and draft state while hiding them from reading and keyboard navigation; hidden components can still run effects. Default values must match a tab when selecting a particular initial panel.
78
+
79
+ ## Styling and accessibility
80
+
81
+ Each part receives its nearest root’s `data-variant`, `data-size` and `data-orientation`, so nested roots retain independent styling. Use the documented classes and component tokens: `--kb-tabs-radius`, `--kb-tabs-list-padding`, `--kb-tabs-tab-height-sm`, `--kb-tabs-tab-height-md`, `--kb-tabs-indicator-thickness` and `--kb-tabs-panel-padding`. The tab list scrolls horizontally when labels exceed available width. Vertical tabs place the list beside the panel from 48rem of their own width; at narrower widths, the panel moves beneath the list.
82
+
83
+ For right-to-left interfaces, combine HTML `dir="rtl"` with Base UI `DirectionProvider direction="rtl"` so keyboard direction matches layout.
84
+
85
+ Name `Tabs.List` with `aria-label` or `aria-labelledby`. Keep tab labels descriptive and use associated panels for peer views. Verify selected versus focused states, hidden panel controls, long labels, both themes, forced colors and enlarged text. Browser automation covers tested keyboard and accessibility fixtures; manual screen-reader and browser-zoom checks remain pending. See [shared verification](../../../../docs/guides/accessibility.md) and the informative [WAI-ARIA tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
86
+
87
+ ## Related components
88
+
89
+ Use [`RadioGroup`](RadioGroup.md) for a form choice and [`Toolbar`](Toolbar.md) for grouped actions.
@@ -0,0 +1,36 @@
1
+ # Text
2
+
3
+ Body paragraphs, inline text and block grouping.
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-text--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Text } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return <Text>Review the project details before saving changes.</Text>;
15
+ }
16
+ ```
17
+
18
+ ## More examples
19
+
20
+ - [Body and supporting copy](https://kbui.kcb.pro/storybook/?path=/story/components-text--sizes-and-tones): Compare text emphasis and measure.
21
+ - [Inline text](https://kbui.kcb.pro/storybook/?path=/story/components-text--inline): Preserve surrounding document structure.
22
+
23
+ ## Reference
24
+
25
+ | Prop | Type | Default | Notes |
26
+ | ------------------ | ---------------------- | --------- | ----------------------------------------------------- |
27
+ | `as` | `p` \| `span` \| `div` | `p` | Use span inside paragraphs; div for block children |
28
+ | `size` | `sm` \| `md` \| `lg` | `md` | Existing small/body roles (13px, 15px), then 1.125rem |
29
+ | `tone` | `default` \| `muted` | `default` | Primary ink or readable secondary ink |
30
+ | `className`, `ref` | Native element props | unset | Ref type follows chosen element |
31
+
32
+ Body text has a line height of 1.6 and a 65ch line-length limit set by `--kb-text-measure`. `Text` adds no margin. Inline spans stay in the flow of the sentence. Use native `<strong>` and `<em>` for emphasis. Keep paragraphs and other block elements outside the default paragraph.
33
+
34
+ ## Related components
35
+
36
+ Use [`Heading`](Heading.md) for hierarchy, [`Link`](Link.md) for navigation, and [`Code`](Code.md) for literal code.
@@ -0,0 +1,47 @@
1
+ # Textarea
2
+
3
+ Use `Textarea` for multiline notes, summaries, or configuration payloads. It pairs a native `textarea` with a persistent label, optional help text, and validation feedback.
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-textarea--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Textarea } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return (
15
+ <Textarea
16
+ label="Review notes"
17
+ name="notes"
18
+ rows={5}
19
+ description="Explain what needs attention."
20
+ />
21
+ );
22
+ }
23
+ ```
24
+
25
+ ## More examples
26
+
27
+ - [Validation feedback](https://kbui.kcb.pro/storybook/?path=/story/components-textarea--with-error): Associate an error with multiline input.
28
+ - [User resizing](https://kbui.kcb.pro/storybook/?path=/story/components-textarea--resize-modes): Compare allowed resize directions.
29
+
30
+ ## Reference
31
+
32
+ | Prop | Type | Default | Notes |
33
+ | ---------------- | -------------------------------------------------------------- | ------------ | ---------------------------------------------------------- |
34
+ | `label` | `string` | required | Visible field label and accessible name |
35
+ | `visuallyHidden` | `boolean` | `false` | Hides the label visually while keeping its accessible name |
36
+ | `description` | `string` | unset | Supporting help text below the control |
37
+ | `error` | `string` | unset | Validation message; marks the control invalid |
38
+ | `rows` | `number` | `4` | Initial visible line count on the native `textarea` |
39
+ | `resize` | `"vertical" \| "none" \| "both"` | `"vertical"` | Controls user drag-resizing axis |
40
+ | `onValueChange` | `(value: string) => void` | unset | Called with the next string value on change |
41
+ | `classNames` | `ClassNames<"label" \| "control" \| "description" \| "error">` | unset | Classes for inner parts |
42
+
43
+ Other native `textarea` props (`value`, `defaultValue`, `onChange`, `placeholder`, `disabled`, `readOnly`, `required`, `name`, `form`, `ref`) pass through to the `<textarea>` element. Adjust minimum height and padding with `--kb-textarea-min-height`, `--kb-textarea-padding-block`, and `--kb-textarea-padding-inline`.
44
+
45
+ ## Related components
46
+
47
+ Use [`Input`](Input.md) for a single-line value and [`Fieldset`](Fieldset.md) to group related answers.
@@ -0,0 +1,66 @@
1
+ # Thumbnail
2
+
3
+ Pair stable image frames with visible titles and metadata for products, studies and attachments. Compose figures into responsive collections with `Grid`.
4
+
5
+ [All components](../../README.md#components) · [Usage](#usage) · [Reference](#reference) · [Live examples and accessibility](https://kbui.kcb.pro/storybook/?path=/docs/components-thumbnail--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Grid, Link, Thumbnail } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return (
15
+ <Grid as="ul" minItemWidth="sm" gap="lg">
16
+ <li>
17
+ <Thumbnail
18
+ src="/products/studio-coat.jpg"
19
+ alt="Sand wool coat with broad lapels"
20
+ ratio="portrait"
21
+ fit="contain"
22
+ caption={<Link href="/products/studio-coat">The studio coat</Link>}
23
+ description="Sand · Wool blend"
24
+ imageProps={{ loading: "lazy", width: 900, height: 1200 }}
25
+ />
26
+ </li>
27
+ <li>
28
+ <Thumbnail
29
+ alt=""
30
+ ratio="portrait"
31
+ fallback="PDF"
32
+ caption={<Link href="/brand-guide.pdf">Brand guide.pdf</Link>}
33
+ description="PDF · 2.4 MB"
34
+ />
35
+ </li>
36
+ </Grid>
37
+ );
38
+ }
39
+ ```
40
+
41
+ ## More examples
42
+
43
+ - [Products](https://kbui.kcb.pro/storybook/?path=/story/components-thumbnail--products): Responsive product cards and absent photography.
44
+ - [Attachments](https://kbui.kcb.pro/storybook/?path=/story/components-thumbnail--attachments): Persistent filenames, formats and file sizes.
45
+ - [Gallery](https://kbui.kcb.pro/storybook/?path=/story/components-thumbnail--gallery): Keyboard-operable `Dialog` inspection and focus return.
46
+
47
+ ## Reference
48
+
49
+ | Prop | Type | Default | Notes |
50
+ | --- | --- | --- | --- |
51
+ | `alt` | `string` | required | Meaningful visual alternative; empty when decorative |
52
+ | `src` | `string` | unset | Preview source |
53
+ | `ratio`, `fit`, `position`, `fallback` | `Image` props | `Image` defaults | Framing and non-interactive fallback |
54
+ | `caption` | `ReactNode` | unset | Visible figure title; may contain `Link`, `Button` or `Dialog.Trigger` |
55
+ | `description` | `ReactNode` | unset | Persistent supporting text such as format and size |
56
+ | `imageProps` | remaining `Image` props | unset | Responsive source/loading attributes, callbacks, frame ref, style and `Image` slots |
57
+ | `classNames` | keyed classes | unset | `root`, `media`, `caption`, `title`, `description` |
58
+ | `ref` | `Ref<HTMLElement>` | unset | Native figure; remaining figure props apply here |
59
+
60
+ A caption names the figure through `aria-labelledby`; caller naming attributes take precedence. Description is visible metadata within `figcaption`. Without either, no caption element is rendered. Figure and image remain non-interactive; caption actions own their native keyboard behavior. The component never infers file type, size or download policy from the URL.
61
+
62
+ For a page of previews, put each `Thumbnail` in a [`Gallery`](Gallery.md) item. A named `Dialog` trigger in the caption supports enlarged inspection, Escape dismissal and focus return through `Dialog`. `Gallery` provides no carousel, arrow-key selection, image editor or upload. See [media recipes](../../../../docs/guides/media-and-identity.md#build-a-gallery-in-reading-order) for a complete implementation.
63
+
64
+ ## Related components
65
+
66
+ Use [`Image`](Image.md) for an image alone, [`Avatar`](Avatar.md) for people, [`Grid`](Grid.md) for layout, and [`Dialog`](Dialog.md) for focused media inspection.
@@ -0,0 +1,130 @@
1
+ # Toast
2
+
3
+ Use `Toast` for temporary feedback about background work. One provider owns the message list, timers and focus. Keep essential results available in the page or a notification history.
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-toast--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Button, Toast, useToastManager } from "@kb.ui/react";
12
+
13
+ function SaveButton() {
14
+ const { add } = useToastManager();
15
+ return (
16
+ <Button onClick={() => add({ title: "Changes saved", description: "Your project is up to date.", type: "success" })}>
17
+ Save changes
18
+ </Button>
19
+ );
20
+ }
21
+
22
+ export function Example() {
23
+ return (
24
+ <Toast.Provider timeout={5000} limit={3}>
25
+ <SaveButton />
26
+ <Toast.Viewport aria-label="Notifications" />
27
+ </Toast.Provider>
28
+ );
29
+ }
30
+ ```
31
+
32
+ Mount one `Toast.Viewport` inside each provider. Fixed placements portal to `document.body`; `placement="inline"` renders in normal layout without a portal. Choose a logical corner with `top-start`, `top-end`, `bottom-start` or `bottom-end`. For a nested theme, pass a mounted themed element or ref through `container`; otherwise the document theme applies. The provider and hook are scoped, so nested providers maintain independent messages.
33
+
34
+ ## Queue and timing
35
+
36
+ Messages display newest first. `limit` defaults to `3`; older overflow messages remain mounted, hidden and inert. Dismissing a newer message reveals an older message if it has not expired. Timers continue for overflow messages. This is a temporary notification stack, not a FIFO delivery queue or durable history.
37
+
38
+ `timeout` defaults to `5000` milliseconds; a per-message timeout overrides the provider. Set `timeout: 0` to keep a message until dismissed. Hover, keyboard focus in the viewport and window blur pause timers; leaving resumes the remaining duration. New messages added while paused also wait. Unmounting the provider clears its timers and subscriptions.
39
+
40
+ Use `timeout: 0` for essential information or time-sensitive actions. Supply an application preference to disable or adjust time limits where the task requires it; hover/focus pause alone does not meet every requirement of [WCAG 2.2.1 Timing Adjustable, Level A](https://www.w3.org/WAI/WCAG22/Understanding/timing-adjustable.html).
41
+
42
+ F6 moves focus into the viewport without notifications interrupting the current task. Tab reaches messages and actions. Escape dismisses the focused message. Dismissal keeps focus within remaining messages or returns it to the previous working control when the last message closes. Close buttons provide a pointer and keyboard alternative to swipe dismissal.
43
+
44
+ ## More examples
45
+
46
+ - [Overflow and dismissal](https://kbui.kcb.pro/storybook/?path=/story/components-toast--queue): Hide older messages and reveal persistent messages as capacity returns.
47
+ - [Undo action](https://kbui.kcb.pro/storybook/?path=/story/components-toast--with-action): Update an existing notification after an action.
48
+ - [Timed dismissal](https://kbui.kcb.pro/storybook/?path=/story/components-toast--timed): Enter notifications with F6, dismiss with Escape and return to work.
49
+ - [Promise states](https://kbui.kcb.pro/storybook/?path=/story/components-toast--promise-state): Keep message identity through loading and success.
50
+ - [Custom composition](https://kbui.kcb.pro/storybook/?path=/story/components-toast--custom-composition): Render typed message data and a real navigation link.
51
+ - [Positioned urgent message](https://kbui.kcb.pro/storybook/?path=/story/components-toast--positioned): Use a portaled corner viewport and a high-priority announcement.
52
+ - [Long content](https://kbui.kcb.pro/storybook/?path=/story/components-toast--long-content): Check wrapping, actions and dismissal at narrow widths.
53
+
54
+ ## Reference
55
+
56
+ ### Toast.Provider
57
+
58
+ | Prop | Type | Default | Notes |
59
+ | --- | --- | --- | --- |
60
+ | `children` | `ReactNode` | unset | Application content and one viewport |
61
+ | `timeout` | `number` | `5000` | Milliseconds before dismissal; `0` disables automatic dismissal |
62
+ | `limit` | `number` | `3` | Maximum visible active messages; use a positive integer |
63
+ | `toastManager` | `ToastManager` | unset | Optional external manager created once per application or request |
64
+
65
+ ### Toast.Viewport
66
+
67
+ | Prop | Type | Default | Notes |
68
+ | --- | --- | --- | --- |
69
+ | `placement` | `ToastPlacement` | `bottom-end` | Four logical corners or `inline` |
70
+ | `container` | `HTMLElement` or ref | `document.body` | Portal host for fixed placements; unused for inline |
71
+ | `aria-label` | `string` | `Notifications` | Localize and distinguish the notification region |
72
+ | `renderToast` | `(toast: ToastObject<Data>) => ReactNode` | complete `Toast` | Custom renderer; give each returned root `key={toast.id}` |
73
+ | `children` | `ReactNode` | managed messages | Explicit children replace automatic rendering |
74
+ | `className`, `ref`, DOM props | native `div` props | unset | Reach the viewport; Base UI `render` composition is supported |
75
+
76
+ ### Toast and parts
77
+
78
+ | Prop or part | Type | Default | Notes |
79
+ | --- | --- | --- | --- |
80
+ | `toast` | `ToastObject<Data>` | required | Message from the matching provider |
81
+ | `tone` | `neutral`, `info`, `success`, `warning`, `danger` | from type | `error` maps to danger; loading maps to info; other types fall back to neutral |
82
+ | `closeLabel` | `string` | `Dismiss notification` | Localized name for default close control |
83
+ | `classNames` | content, title, description, action, close | unset | Extra classes for default slots |
84
+ | `children` | `ReactNode` | complete message | Overrides default content and close control |
85
+ | `swipeDirection` | Base UI swipe directions | down and right | Configure or disable with an empty array |
86
+ | `Toast.Content` | content wrapper | div | Groups message content |
87
+ | `Toast.Title` | heading | message title | Supplies the root accessible name |
88
+ | `Toast.Description` | paragraph | message description | Supplies the root accessible description |
89
+ | `Toast.Action` | button | message `actionProps` | Does not close automatically; explicitly call close or update |
90
+ | `Toast.Close` | button | caller children | Dismisses its message; supply visible text or an accessible name |
91
+ | `className`, `ref`, DOM props | part element props | unset | Every part supports a plain class string, ref and Base UI render composition |
92
+
93
+ Custom children own their own slot classes and close control. For a link action, use `render={<a href="…" />}`, `nativeButton={false}` and `role="link"`. Default parts render title, description and action only when the message supplies them. Description-only messages, including shorthand promise text, become the title so the default dialog stays named. Give every message meaningful title text; an icon or color cannot replace it. Keep `title` and `description` on the message even when custom parts render them, because urgent announcements use the stored message content.
94
+
95
+ ### Managers and messages
96
+
97
+ `useToastManager<Data>()` returns reactive `toasts`, `add`, `update`, `close` and `promise` from the nearest provider. `createToastManager<Data>()` supplies the same methods outside React; pass it to `toastManager`. Create a stable instance per application or server request. Calls made before provider subscription or after unmount are not buffered. Do not share a module-level manager between server requests.
98
+
99
+ | Method or option | Type | Behavior |
100
+ | --- | --- | --- |
101
+ | `add(options)` | `ToastAddOptions<Data>` | Returns string ID; adding the same ID updates in place and refreshes its timer |
102
+ | `update(id, options)` | `ToastUpdateOptions<Data>` or updater | Changes existing content; an explicit timeout restarts timing |
103
+ | `close(id?)` | optional string ID | Closes one message or all messages; callbacks fire once |
104
+ | `promise(value, options)` | promise and loading/success/error options | Persistent loading message becomes success/error using same ID; resolves or rejects with original result |
105
+ | `title`, `description` | `ReactNode` | Stored message and announcement text |
106
+ | `type` | `string` | Visual type; use words in content to explain status |
107
+ | `priority` | `low` or `high` | Low is polite; high uses a separate urgent alert announcement |
108
+ | `timeout` | `number` | Per-message duration; `0` disables automatic dismissal |
109
+ | `id` | `string` | Optional stable key for upsert |
110
+ | `actionProps` | native `button` props | Includes action text, handler, disabled state and accessible name |
111
+ | `onClose`, `onRemove` | `() => void` | Close intent and final removal after exit transition |
112
+ | `data` | caller-defined object | Typed custom data for `renderToast` |
113
+
114
+ Promise options accept `loading`, `success` and `error` as text or update options; success/error also accept functions of the result/error. Handle rejected returned promises in application code. `ToastObject`, `ToastManager`, `ToastAddOptions`, `ToastUpdateOptions`, `ToastPromiseOptions`, component prop types, `ToastTone` and `ToastPlacement` are public exports.
115
+
116
+ Base UI owns interaction and lifecycle semantics; see its [`Toast` reference](https://base-ui.com/react/components/toast). CSS-only consumers must implement queueing, announcements, timing and focus themselves. Component tokens use the `--kb-toast-*` namespace; importing a standalone `toast.css` also requires tokens and reset.
117
+
118
+ ## Motion
119
+
120
+ Messages enter with a short slide and soft scale settle; dismissal fades and collapses the space before removal. `Stack` spacing opens as a new message enters, and swipe dismissal continues in the gesture direction. Reduced motion removes transitions and geometric movement.
121
+
122
+ Tune `--kb-toast-motion-duration`, `--kb-toast-exit-duration`, `--kb-toast-motion-easing`, `--kb-toast-enter-offset` and `--kb-toast-enter-scale` to match the application. Keep exits brief so notifications do not obstruct work.
123
+
124
+ ## Accessibility evidence and limits
125
+
126
+ Component tests cover lifecycle, announcements in the DOM, provider isolation, callbacks and portal composition. Browser stories exercise keyboard/focus, live-region structure, queue visibility, actions and real timing in both themes and motion preferences. These checks do not prove spoken delivery. Test relevant initial/update/urgent messages with supported screen readers and confirm no duplicate announcements. Manual screen-reader interoperability remains unverified; follow the [shared accessibility procedure](../../../../docs/guides/accessibility.md).
127
+
128
+ ## Related components
129
+
130
+ Use [`Status`](Status.md) for state beside its content, [`Callout`](Callout.md) for an inline message with fuller context, and [`Dialog`](Dialog.md) when a decision must interrupt work.
@@ -0,0 +1,39 @@
1
+ # Toolbar
2
+
3
+ Group related actions, such as editing or filtering controls. Give the row an accessible name so people know what its controls affect.
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-toolbar--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Toolbar } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return (
15
+ <Toolbar aria-label="Document actions">
16
+ <Toolbar.Button onClick={() => window.print()}>Print</Toolbar.Button>
17
+ </Toolbar>
18
+ );
19
+ }
20
+ ```
21
+
22
+ ## More examples
23
+
24
+ - [Coordinated actions](https://kbui.kcb.pro/storybook/?path=/story/components-toolbar--default): Try the toolbar’s single Tab entry and arrow-key navigation.
25
+
26
+ ## Reference
27
+
28
+ | Part | Props and responsibility |
29
+ | ------------------- | ------------------------------------------------------------------------------- |
30
+ | `Toolbar` | Root; name with `aria-label`; Base UI orientation controls the keyboard direction |
31
+ | `Toolbar.Group` | Groups related controls inside the toolbar |
32
+ | `Toolbar.Button` | Action; variant accepts `Button` variants and defaults to ghost |
33
+ | `Toolbar.Separator` | Visual division between groups |
34
+
35
+ Tab enters the toolbar once; arrow keys move between its controls. Give icon-only actions their own accessible names. Use `Checkbox` or `RadioGroup` when a control represents a persistent choice rather than an action.
36
+
37
+ ## Related components
38
+
39
+ Use [`Inline`](Inline.md) for independent controls that should each retain their normal Tab stop, and [`Menu`](Menu.md) for a compact action list.
@@ -0,0 +1,42 @@
1
+ # Tooltip
2
+
3
+ Add a brief, optional hint to an already named control. Put essential instructions in visible text or a field description 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-tooltip--docs)
6
+
7
+ ## Usage
8
+
9
+ ```tsx
10
+ import "@kb.ui/react/styles.css";
11
+ import { Button, Tooltip } from "@kb.ui/react";
12
+
13
+ export function Example() {
14
+ return (
15
+ <Tooltip content="Print using your browser’s print dialog.">
16
+ <Button onClick={() => window.print()}>Print page</Button>
17
+ </Tooltip>
18
+ );
19
+ }
20
+ ```
21
+
22
+ ## More examples
23
+
24
+ - [An optional description](https://kbui.kcb.pro/storybook/?path=/story/components-tooltip--on-hover): Try pointer and keyboard access to a named trigger.
25
+ - [A themed hint](https://kbui.kcb.pro/storybook/?path=/story/components-tooltip--nested-theme): Check that the hint uses its parent theme.
26
+
27
+ ## Reference
28
+
29
+ | Prop | Type | Default | Notes |
30
+ | ----------- | ---------------- | ------------- | ---------------------------------------------------------- |
31
+ | `children` | `ReactElement` | required | Focusable trigger that accepts Base UI props and a ref |
32
+ | `content` | `ReactNode` | required | Short, non-interactive hint shown on hover or focus |
33
+ | `side` | positioner side | `top` | Preferred side; placement can adjust near viewport edges |
34
+ | `delay` | `number` | `400` | Hover delay in milliseconds |
35
+ | `container` | portal container | document body | Use a themed host when the popup belongs to a nested theme |
36
+ | `className` | `string` | unset | Class on the popup |
37
+
38
+ Give icon-only triggers their own `aria-label`. The tooltip is a description, not a replacement for the control's name. Do not put links, buttons, or required instructions in the popup.
39
+
40
+ ## Related components
41
+
42
+ Use [`Input`](Input.md) descriptions for essential field instructions and [`Callout`](Callout.md) for a persistent message.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kb.ui/react",
3
- "version": "0.10.4",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,7 +9,8 @@
9
9
  "directory": "packages/react"
10
10
  },
11
11
  "files": [
12
- "dist"
12
+ "dist",
13
+ "docs"
13
14
  ],
14
15
  "sideEffects": [
15
16
  "*.css"