@handamade/psi-react 0.20.0 → 0.22.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 +1 -1
- package/dist/AppShell/AppShell.d.ts +51 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -0
- package/dist/Banner/Banner.d.ts +35 -0
- package/dist/Banner/Banner.d.ts.map +1 -0
- package/dist/Button/Button.d.ts +4 -0
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/CopyButton/CopyButton.d.ts +23 -0
- package/dist/CopyButton/CopyButton.d.ts.map +1 -0
- package/dist/CursorPagination/CursorPagination.d.ts +29 -0
- package/dist/CursorPagination/CursorPagination.d.ts.map +1 -0
- package/dist/Field/Field.d.ts +16 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/useFieldControl.d.ts +40 -0
- package/dist/Field/useFieldControl.d.ts.map +1 -0
- package/dist/InlineAlert/InlineAlert.d.ts +32 -0
- package/dist/InlineAlert/InlineAlert.d.ts.map +1 -0
- package/dist/NavBar/NavBar.d.ts +10 -2
- package/dist/NavBar/NavBar.d.ts.map +1 -1
- package/dist/NavTree/NavGroup.d.ts +22 -0
- package/dist/NavTree/NavGroup.d.ts.map +1 -0
- package/dist/NavTree/NavItem.d.ts +29 -0
- package/dist/NavTree/NavItem.d.ts.map +1 -0
- package/dist/NavTree/NavTree.d.ts +23 -0
- package/dist/NavTree/NavTree.d.ts.map +1 -0
- package/dist/Skeleton/Skeleton.d.ts +22 -0
- package/dist/Skeleton/Skeleton.d.ts.map +1 -0
- package/dist/SkipLink/SkipLink.d.ts +25 -0
- package/dist/SkipLink/SkipLink.d.ts.map +1 -0
- package/dist/Table/Table.d.ts +6 -3
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/TableBody.d.ts +7 -4
- package/dist/Table/TableBody.d.ts.map +1 -1
- package/dist/Table/TableCaption.d.ts +21 -0
- package/dist/Table/TableCaption.d.ts.map +1 -0
- package/dist/Table/TableCell.d.ts +15 -5
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableHead.d.ts +5 -3
- package/dist/Table/TableHead.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.d.ts +5 -3
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableRow.d.ts +5 -3
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Tabs/Tab.d.ts.map +1 -1
- package/dist/Tabs/Tabs.d.ts +20 -1
- package/dist/Tabs/Tabs.d.ts.map +1 -1
- package/dist/Toast/Announcement.d.ts +38 -0
- package/dist/Toast/Announcement.d.ts.map +1 -0
- package/dist/Toast/Toast.d.ts +16 -2
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/ToastProvider.d.ts +27 -4
- package/dist/Toast/ToastProvider.d.ts.map +1 -1
- package/dist/Toast/ToastRegion.d.ts +26 -8
- package/dist/Toast/ToastRegion.d.ts.map +1 -1
- package/dist/Toast/status.d.ts +15 -0
- package/dist/Toast/status.d.ts.map +1 -0
- package/dist/Toast/useToast.d.ts +17 -3
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.d.ts +26 -4
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/a11y-meta.d.ts.map +1 -1
- package/dist/index.d.ts +30 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1305 -958
- package/dist/manifest.json +1049 -235
- package/dist/patterns.json +671 -3
- package/dist/styles.css +1 -1
- package/docs/Announcement.md +37 -0
- package/docs/AppShell.md +46 -0
- package/docs/AspectRatio.md +1 -1
- package/docs/Banner.md +54 -0
- package/docs/Button.md +2 -1
- package/docs/Card.md +1 -1
- package/docs/Checkbox.md +1 -1
- package/docs/CopyButton.md +51 -0
- package/docs/CursorPagination.md +45 -0
- package/docs/DescriptionItem.md +1 -1
- package/docs/DescriptionList.md +1 -1
- package/docs/Dialog.md +1 -1
- package/docs/Field.md +4 -3
- package/docs/IconButton.md +1 -1
- package/docs/InlineAlert.md +53 -0
- package/docs/Input.md +1 -1
- package/docs/Menu.md +1 -1
- package/docs/MenuItem.md +1 -1
- package/docs/MenuSeparator.md +1 -1
- package/docs/NavBar.md +4 -2
- package/docs/NavGroup.md +40 -0
- package/docs/NavItem.md +40 -0
- package/docs/NavTree.md +39 -0
- package/docs/Pagination.md +1 -1
- package/docs/Panel.md +1 -1
- package/docs/Select.md +1 -1
- package/docs/Skeleton.md +50 -0
- package/docs/SkipLink.md +40 -0
- package/docs/Switch.md +1 -1
- package/docs/Tab.md +1 -1
- package/docs/TabList.md +1 -1
- package/docs/TabPanel.md +1 -1
- package/docs/Table.md +1 -1
- package/docs/TableBody.md +3 -2
- package/docs/TableCaption.md +39 -0
- package/docs/TableCell.md +5 -2
- package/docs/TableHead.md +2 -1
- package/docs/TableHeaderCell.md +2 -1
- package/docs/TableRow.md +2 -1
- package/docs/Tabs.md +3 -3
- package/docs/Tag.md +1 -1
- package/docs/Toast.md +5 -3
- package/docs/ToastProvider.md +6 -3
- package/docs/ToastRegion.md +5 -5
- package/docs/Toolbar.md +5 -3
- package/docs/Tooltip.md +1 -1
- package/llms.txt +41 -9
- package/package.json +2 -2
package/docs/MenuItem.md
CHANGED
|
@@ -45,5 +45,5 @@ This component has no `--psi-menu-item-*` tokens — its styling binds scale tok
|
|
|
45
45
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
46
46
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
47
47
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
48
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
48
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
49
49
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/MenuSeparator.md
CHANGED
|
@@ -32,5 +32,5 @@ This component has no `--psi-menu-separator-*` tokens — its styling binds scal
|
|
|
32
32
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
33
33
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
34
34
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
35
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
35
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
36
36
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/NavBar.md
CHANGED
|
@@ -9,7 +9,9 @@ Top navigation bar with brand, nav-link, and trailing-action slots.
|
|
|
9
9
|
|---|---|---|---|---|
|
|
10
10
|
| `brand` | `ReactNode` | — | no | Brand slot (wordmark / logo link), leading edge. |
|
|
11
11
|
| `actions` | `ReactNode` | — | no | Trailing actions slot (theme switch, CTA). |
|
|
12
|
-
| `children` | `ReactNode` | — | no | Nav links. |
|
|
12
|
+
| `children` | `ReactNode` | — | no | Nav links. The `<nav>` renders only when there are children, so a bar with a brand and actions and no links has no empty landmark (D88). |
|
|
13
|
+
| `navLabel` | `string` | — | no | Accessible name of the links' `<nav>` (its `aria-label`). Rest props land on the `<header>`, so this is the only way to label the `<nav>` (D88). |
|
|
14
|
+
| `fluid` | `boolean` | false | no | Lay the row out at full width: it drops `psi-container` (the centred max-width column) and keeps the `--psi-gutter` side padding. For an application header over a full-width frame (D88). |
|
|
13
15
|
| `ref` | `Ref<HTMLElement>` | — | no | Forwarded ref to the header element. |
|
|
14
16
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
15
17
|
|
|
@@ -28,5 +30,5 @@ Override `--psi-navbar-*` custom properties at any scope; interactive states der
|
|
|
28
30
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
29
31
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
30
32
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
31
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
33
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
32
34
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/NavGroup.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# NavGroup
|
|
3
|
+
|
|
4
|
+
A collapsible group of `NavItem`s in a `NavTree` (D88). Controlled-only, like `Tabs` (D67): `open` and `onOpenChange` are required and nothing is remembered. Renders a native `<button aria-expanded aria-controls>` over a `<ul>` that is `hidden` when closed, so the items leave the layout and the accessibility tree while `aria-controls` keeps naming an element. The chevron turns with the state and is `aria-hidden`: the label and `aria-expanded` carry the meaning.
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `label` | `ReactNode` | — | yes | The group's visible label, such as "Reports". |
|
|
11
|
+
| `open` | `boolean` | — | yes | Whether the group's items are shown. Controlled. |
|
|
12
|
+
| `onOpenChange` | `(open: boolean) => void` | — | yes | Called with the next state when the button is pressed. The group never changes `open` itself. |
|
|
13
|
+
| `children` | `ReactNode` | — | yes | `NavItem`s of the group. |
|
|
14
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
15
|
+
|
|
16
|
+
## Keyboard & assistive tech
|
|
17
|
+
|
|
18
|
+
| Keys | Behavior |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Enter / Space | Activates the group's native button, which asks the parent to open or close the group through onOpenChange. |
|
|
21
|
+
|
|
22
|
+
Controlled-only: open and onOpenChange are required and the group never changes its own state. Renders a <button type="button"> with aria-expanded and aria-controls naming its <ul>, which carries `hidden` when closed, so the links leave the layout and the accessibility tree while aria-controls still resolves. The chevron is aria-hidden and turns on a duration token; the label and aria-expanded carry the meaning.
|
|
23
|
+
|
|
24
|
+
## Theming
|
|
25
|
+
|
|
26
|
+
Override `--psi-nav-tree-*` custom properties at any scope; interactive states derive automatically (L - 0.04 hover, L - 0.08 active).
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
33
|
+
- danger only for actions with real consequences.
|
|
34
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
35
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
36
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
37
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
38
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
39
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
40
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/NavItem.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# NavItem
|
|
3
|
+
|
|
4
|
+
One entry of a `NavTree` (D88): an `<li>` that styles the single anchor inside it. Router apps pass their own link as the child, so it keeps its `href` and handlers; with `current`, `NavItem` clones it to add `aria-current="page"` (D93), as `Menu` clones its trigger. `href` is for plain links and for presets, where the compose tree can hold only manifest components and a raw `<a>` is not one. The current page is never marked by colour alone: medium weight, a raised surface and a bar at the inline start.
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `children` | `ReactNode` | — | yes | Without `href`: one anchor, your router's link. With `href`: the link's text. |
|
|
11
|
+
| `href` | `string` | — | no | Render the anchor yourself (D88), for a plain link or a preset: the `<li>` holds `<a href>` with `children` as its text. Router apps leave it out and pass their own link as the child, so the link keeps its own handlers. |
|
|
12
|
+
| `current` | `boolean` | — | no | Mark the link as the current page (`aria-current="page"`): on the anchor `href` renders, or on the single element you pass as a child (D93). Without `current`, a child's own `aria-current` is left alone, so a router that marks its active link keeps working. |
|
|
13
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
14
|
+
| `ref` | `Ref<HTMLLIElement>` | — | no | Forwarded ref to the `<li>`. |
|
|
15
|
+
|
|
16
|
+
## Keyboard & assistive tech
|
|
17
|
+
|
|
18
|
+
| Keys | Behavior |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Enter | Follows the link inside it (native anchor behavior); the link is the consumer's router link. |
|
|
21
|
+
|
|
22
|
+
An <li> that styles the one anchor inside it. Router apps pass their own link as the child; current clones it with aria-current="page" (D93), and without current the child keeps its own aria-current; with href the NavItem renders the anchor itself (for plain links and presets) and current sets aria-current="page" on it. The current page is marked by weight, a raised surface and an inline-start bar, never by colour alone, and the focus ring is drawn inset on the anchor.
|
|
23
|
+
|
|
24
|
+
## Theming
|
|
25
|
+
|
|
26
|
+
Override `--psi-nav-tree-*` custom properties at any scope; interactive states derive automatically (L - 0.04 hover, L - 0.08 active).
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
33
|
+
- danger only for actions with real consequences.
|
|
34
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
35
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
36
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
37
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
38
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
39
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
40
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/NavTree.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# NavTree
|
|
3
|
+
|
|
4
|
+
A navigation tree (D88): a `<nav aria-label>` around a `<ul>` of `NavItem`s and `NavGroup`s. Native elements only — *Tab* moves through the group buttons and the links of open groups; there is no roving focus and no `role="menu"` or `role="tree"`, because site navigation is a list of links, not a widget. Router-agnostic: pass your router's link inside each `NavItem`, with `aria-current="page"` on the current one.
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `aria-label` | `string` | — | yes | Accessible name of the navigation landmark, such as "Main". Required: an app has more than one `<nav>` (a header's, a sidebar's), and an unnamed one is indistinguishable from the rest. Declared here rather than inherited so docgen keeps it in the manifest (D60). |
|
|
11
|
+
| `children` | `ReactNode` | — | yes | `NavItem`s and `NavGroup`s — each renders an `<li>`. |
|
|
12
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
13
|
+
| `ref` | `Ref<HTMLElement>` | — | no | Forwarded ref to the `<nav>`. |
|
|
14
|
+
|
|
15
|
+
## Keyboard & assistive tech
|
|
16
|
+
|
|
17
|
+
| Keys | Behavior |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Tab / Shift+Tab | Moves through the group buttons and the links of open groups in document order. There is no roving focus and no arrow-key model: it is a list of links, not a menu or a tree widget. |
|
|
20
|
+
|
|
21
|
+
A native <nav> around a <ul>, named by the required aria-label (an app has more than one navigation landmark). No role="menu" or role="tree" is used (D88). Router-agnostic: the consumer passes its router's link inside each NavItem.
|
|
22
|
+
|
|
23
|
+
## Theming
|
|
24
|
+
|
|
25
|
+
Override `--psi-nav-tree-*` custom properties at any scope; interactive states derive automatically (L - 0.04 hover, L - 0.08 active).
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
|
|
31
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
32
|
+
- danger only for actions with real consequences.
|
|
33
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
34
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
35
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
36
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
37
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
38
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
39
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Pagination.md
CHANGED
|
@@ -29,5 +29,5 @@ This component has no `--psi-pagination-*` tokens — its styling binds scale to
|
|
|
29
29
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
30
30
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
31
31
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
32
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
32
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
33
33
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Panel.md
CHANGED
|
@@ -35,5 +35,5 @@ Override `--psi-panel-*` custom properties at any scope.
|
|
|
35
35
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
36
36
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
37
37
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
38
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
38
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
39
39
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Select.md
CHANGED
|
@@ -37,5 +37,5 @@ Override `--psi-select-*` custom properties at any scope; interactive states der
|
|
|
37
37
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
38
38
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
39
39
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
40
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
40
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
41
41
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Skeleton.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# Skeleton
|
|
3
|
+
|
|
4
|
+
A loading placeholder. It is not a live region: it renders no `role` and no `aria-live`, and it is always `aria-hidden="true"`, so assistive tech skips it entirely. Put `aria-busy` on the region the skeleton stands for — that is what tells a screen reader the content is coming. Its width fills the container; size the container, not the skeleton. The pulse is an opacity animation that stops under `prefers-reduced-motion: reduce` (D86).
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `variant` | `"text" \| "block"` | text | no | `text` renders `lines` stacked bars; `block` one box. |
|
|
11
|
+
| `lines` | `number` | 1 | no | Number of text lines; the last of several is shorter. Text only. |
|
|
12
|
+
| `size` | `24 \| 32 \| 40 \| 48` | 40 | no | Height of a block, from the size scale. Block only. |
|
|
13
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
14
|
+
| `ref` | `Ref<HTMLDivElement>` | — | no | Forwarded ref to the underlying `<div>`. |
|
|
15
|
+
|
|
16
|
+
## Keyboard & assistive tech
|
|
17
|
+
|
|
18
|
+
| Keys | Behavior |
|
|
19
|
+
|---|---|
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Not a live region: it renders no role and no aria-live, and it is always aria-hidden="true", so assistive tech skips it entirely. Put aria-busy="true" on the region the skeleton stands for (a table body, a card, a list) and remove it when the content arrives; that, not the skeleton, is what tells a screen reader the content is loading. Not focusable. The pulse is an opacity animation that stops under prefers-reduced-motion: reduce, because zeroing the duration of an infinite alternating animation flickers instead of stopping (D86).
|
|
23
|
+
|
|
24
|
+
## Theming
|
|
25
|
+
|
|
26
|
+
Override `--psi-skeleton-*` custom properties at any scope.
|
|
27
|
+
|
|
28
|
+
## Variant guidance
|
|
29
|
+
|
|
30
|
+
- **accent** — Primary action, draws attention. Submit, CTA, main action in a group.
|
|
31
|
+
- **accent-subtle** — Accent tone, lower visual weight. Selected state, active filter, soft CTA.
|
|
32
|
+
- **neutral** — Default, structurally present. Secondary actions, toolbar buttons.
|
|
33
|
+
- **neutral-subtle** — Minimal chrome. Inline actions, table row actions.
|
|
34
|
+
- **ghost** — No visible container until hover. Icon-only triggers, compact toolbars.
|
|
35
|
+
- **outline** — Bordered ghost — visible structure, no fill until hover. Marketing CTA, download button; hover fills accent.
|
|
36
|
+
- **danger** — Destructive action. Delete, remove, disconnect.
|
|
37
|
+
- **danger-subtle** — Destructive context, low urgency. Warning badges, soft destructive hints.
|
|
38
|
+
- **success | warning** — Status communication (Tag only). Status badges, labels.
|
|
39
|
+
|
|
40
|
+
## Rules
|
|
41
|
+
|
|
42
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
43
|
+
- danger only for actions with real consequences.
|
|
44
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
45
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
46
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
47
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
48
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
49
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
50
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/SkipLink.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# SkipLink
|
|
3
|
+
|
|
4
|
+
A link to the page's main content, invisible until it takes keyboard focus and then fixed at the inline-start top corner on a surface, drawing the shared focus ring (D88). Render it first in the document. No script: native fragment navigation moves focus to a target that is focusable, so the next *Tab* continues from inside it. `AppShell`'s `main` is one (`tabIndex={-1}`); a bare `<main>` is not, so give it one. A modal `Dialog` makes the rest of the document inert, so the link never needs to beat one. A `ToastRegion` is on the native top layer, which paints above everything whatever its `z-index`: do not place one at `top-start` (its default is `bottom-end`) in an app with a skip link, or it covers the focused link.
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `href` | `string` | — | yes | Fragment of the element to skip to, such as `"#main"`. The target must be focusable (`tabIndex={-1}` is enough), or focus does not move. |
|
|
11
|
+
| `children` | `ReactNode` | — | yes | Visible text, such as "Skip to content". |
|
|
12
|
+
| `ref` | `Ref<HTMLAnchorElement>` | — | no | Forwarded ref to the anchor. |
|
|
13
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
14
|
+
|
|
15
|
+
## Keyboard & assistive tech
|
|
16
|
+
|
|
17
|
+
| Keys | Behavior |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Tab | Takes focus and becomes visible at the inline-start top corner, drawing the shared focus ring. Put it first in the document so it is the first tab stop. |
|
|
20
|
+
| Enter | Follows the fragment href: focus moves to the target, and the next Tab continues from inside it. |
|
|
21
|
+
|
|
22
|
+
A native anchor, visually hidden until it is focused (:focus-visible) and with no script (D88). Fragment navigation moves focus only to a focusable target, so the element named by href must be focusable: tabIndex={-1} is enough, and AppShell's main has it. A modal Dialog makes the link inert, so it never needs to beat one. A ToastRegion is on the native top layer and paints over the focused link whatever its z-index: do not place one at top-start in an app with a skip link.
|
|
23
|
+
|
|
24
|
+
## Theming
|
|
25
|
+
|
|
26
|
+
Override `--psi-skip-link-*` custom properties at any scope.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
33
|
+
- danger only for actions with real consequences.
|
|
34
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
35
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
36
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
37
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
38
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
39
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
40
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Switch.md
CHANGED
|
@@ -33,5 +33,5 @@ Override `--psi-switch-*` custom properties at any scope.
|
|
|
33
33
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
34
34
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
35
35
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
36
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
36
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
37
37
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Tab.md
CHANGED
|
@@ -36,5 +36,5 @@ This component has no `--psi-tab-*` tokens — its styling binds scale tokens on
|
|
|
36
36
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
37
37
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
38
38
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
39
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
39
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
40
40
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TabList.md
CHANGED
|
@@ -37,5 +37,5 @@ This component has no `--psi-tab-list-*` tokens — its styling binds scale toke
|
|
|
37
37
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
38
38
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
39
39
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
40
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
40
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
41
41
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TabPanel.md
CHANGED
|
@@ -35,5 +35,5 @@ This component has no `--psi-tab-panel-*` tokens — its styling binds scale tok
|
|
|
35
35
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
36
36
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
37
37
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
38
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
38
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
39
39
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Table.md
CHANGED
|
@@ -34,5 +34,5 @@ Override `--psi-table-*` custom properties at any scope; interactive states deri
|
|
|
34
34
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
35
35
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
36
36
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
37
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
37
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
38
38
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TableBody.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
2
|
# TableBody
|
|
3
3
|
|
|
4
|
-
`<tbody>` wrapper.
|
|
4
|
+
`<tbody>` wrapper. Remaining attributes land on it (D85) — `aria-busy` while a page of rows loads, say.
|
|
5
5
|
|
|
6
6
|
## Props
|
|
7
7
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|---|---|---|---|---|
|
|
10
10
|
| `children` | `ReactNode` | — | yes | The body TableRows. |
|
|
11
11
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
12
|
+
| `ref` | `Ref<HTMLTableSectionElement>` | — | no | Forwarded ref to the `<tbody>`. |
|
|
12
13
|
|
|
13
14
|
## Theming
|
|
14
15
|
|
|
@@ -25,5 +26,5 @@ This component has no `--psi-table-body-*` tokens — its styling binds scale to
|
|
|
25
26
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
26
27
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
27
28
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
28
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
29
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
29
30
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
|
+
# TableCaption
|
|
3
|
+
|
|
4
|
+
`<caption>` — the table's name, above it, and an optional detail line (D85). It names the table for assistive tech, which an `aria-label` on the `Table` would also do, but a caption is visible. A token-paged list has no page numbers to land on, so after a page change the consumer moves focus here: give it `tabIndex={-1}`, put the range in `detail`, and call `focus()` on the ref. The ring is the shared one (D82), drawn inside the caption's box. Remaining attributes land on the element.
|
|
5
|
+
|
|
6
|
+
## Props
|
|
7
|
+
|
|
8
|
+
| Prop | Type | Default | Required | Description |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| `children` | `ReactNode` | — | yes | The name line — what the table lists. Also the table's accessible name. |
|
|
11
|
+
| `detail` | `ReactNode` | — | no | An optional second line: the range shown, say — "Rows 51–100 of more than 100,000". |
|
|
12
|
+
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
13
|
+
| `ref` | `Ref<HTMLTableCaptionElement>` | — | no | Forwarded ref to the `<caption>`, so focus can be moved to it. |
|
|
14
|
+
|
|
15
|
+
## Keyboard & assistive tech
|
|
16
|
+
|
|
17
|
+
| Keys | Behavior |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Tab | Not a tab stop. With tabIndex={-1} the consumer moves focus to it after a page change, and the shared ring is drawn inside the caption. |
|
|
20
|
+
|
|
21
|
+
Renders <caption>, which names the table for assistive tech and is visible, unlike an aria-label on Table. Put the range in `detail` ("Rows 51–100 of more than 100,000") so that moving focus to the caption after a token-paged page change reads the new range (D85). Remaining attributes land on the element.
|
|
22
|
+
|
|
23
|
+
## Theming
|
|
24
|
+
|
|
25
|
+
This component has no `--psi-table-caption-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
|
|
31
|
+
- One accent per visual group; everything else neutral or ghost.
|
|
32
|
+
- danger only for actions with real consequences.
|
|
33
|
+
- Sizes are px numbers (24|32|40|48), never S/M/L.
|
|
34
|
+
- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.
|
|
35
|
+
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
36
|
+
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
37
|
+
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
38
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
39
|
+
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TableCell.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
2
|
# TableCell
|
|
3
3
|
|
|
4
|
-
`<td
|
|
4
|
+
`<td>`, or `<th scope="row">` with `rowHeader`. `numeric` means right-aligned *and* tabular — a column that aligns but whose digits jitter between rows defeats the purpose. Remaining attributes land on the cell (D85).
|
|
5
5
|
|
|
6
6
|
## Props
|
|
7
7
|
|
|
8
8
|
| Prop | Type | Default | Required | Description |
|
|
9
9
|
|---|---|---|---|---|
|
|
10
10
|
| `numeric` | `boolean` | — | no | Right-aligns and renders tabular figures (D62). |
|
|
11
|
+
| `colSpan` | `number` | — | no | Columns the cell spans — an empty-state row spanning the table (D85). |
|
|
12
|
+
| `rowHeader` | `boolean` | — | no | Renders `<th scope="row">` instead of `<td>`: the cell that names its row, an identifier say, so a screen reader reads it with every cell in the row (D85). Styled as a cell, at medium weight. |
|
|
11
13
|
| `children` | `ReactNode` | — | no | Cell content. |
|
|
12
14
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
15
|
+
| `ref` | `Ref<HTMLTableCellElement>` | — | no | Forwarded ref to the cell element. |
|
|
13
16
|
|
|
14
17
|
## Theming
|
|
15
18
|
|
|
@@ -26,5 +29,5 @@ This component has no `--psi-table-cell-*` tokens — its styling binds scale to
|
|
|
26
29
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
27
30
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
28
31
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
29
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
32
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
30
33
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TableHead.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|---|---|---|---|---|
|
|
10
10
|
| `children` | `ReactNode` | — | yes | The header TableRow. |
|
|
11
11
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
12
|
+
| `ref` | `Ref<HTMLTableSectionElement>` | — | no | Forwarded ref to the `<thead>`. |
|
|
12
13
|
|
|
13
14
|
## Theming
|
|
14
15
|
|
|
@@ -25,5 +26,5 @@ This component has no `--psi-table-head-*` tokens — its styling binds scale to
|
|
|
25
26
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
26
27
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
27
28
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
28
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
29
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
29
30
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TableHeaderCell.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
| `numeric` | `boolean` | — | no | Right-aligns and renders tabular figures (D62). |
|
|
12
12
|
| `children` | `ReactNode` | — | no | Header label. |
|
|
13
13
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
14
|
+
| `ref` | `Ref<HTMLTableCellElement>` | — | no | Forwarded ref to the `<th>`. |
|
|
14
15
|
|
|
15
16
|
## Theming
|
|
16
17
|
|
|
@@ -27,5 +28,5 @@ This component has no `--psi-table-header-cell-*` tokens — its styling binds s
|
|
|
27
28
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
28
29
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
29
30
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
30
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
31
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
31
32
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/TableRow.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
| `selectLabel` | `string` | — | no | Accessible name for this row's selection checkbox. |
|
|
12
12
|
| `children` | `ReactNode` | — | yes | The row's cells. |
|
|
13
13
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
14
|
+
| `ref` | `Ref<HTMLTableRowElement>` | — | no | Forwarded ref to the `<tr>`. |
|
|
14
15
|
|
|
15
16
|
## Theming
|
|
16
17
|
|
|
@@ -27,5 +28,5 @@ This component has no `--psi-table-row-*` tokens — its styling binds scale tok
|
|
|
27
28
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
28
29
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
29
30
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
30
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
31
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
31
32
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Tabs.md
CHANGED
|
@@ -7,7 +7,7 @@ Tab set root (D67) — holds no selection state of its own, following D50, D53 a
|
|
|
7
7
|
|
|
8
8
|
| Prop | Type | Default | Required | Description |
|
|
9
9
|
|---|---|---|---|---|
|
|
10
|
-
| `value` | `string` | — | yes | Controlled selected tab, matched against each `Tab`/`TabPanel` value. |
|
|
10
|
+
| `value` | `string` | — | yes | Controlled selected tab, matched against each `Tab`/`TabPanel` value. A value that matches no tab selects nothing, and the first enabled tab holds the list's tab stop (D93); development builds warn. |
|
|
11
11
|
| `onValueChange` | `(value: string) => void` | — | yes | Fires with the newly selected value; the consumer flips `value`. |
|
|
12
12
|
| `orientation` | `"horizontal" \| "vertical"` | horizontal | no | Axis of the tab list, which also picks the arrow keys. |
|
|
13
13
|
| `children` | `ReactNode` | — | yes | A `TabList` and one `TabPanel` per tab. |
|
|
@@ -18,7 +18,7 @@ Tab set root (D67) — holds no selection state of its own, following D50, D53 a
|
|
|
18
18
|
|
|
19
19
|
| Keys | Behavior |
|
|
20
20
|
|---|---|
|
|
21
|
-
| Tab | Enters the tab list at its selected tab (one stop for the whole list), then moves on to the active panel. |
|
|
21
|
+
| Tab | Enters the tab list at its selected tab (one stop for the whole list), then moves on to the active panel. When value matches no tab, the first enabled tab holds the stop (the first tab if all are disabled) and none is selected; a selected disabled tab keeps the stop (D93). |
|
|
22
22
|
|
|
23
23
|
Controlled-only (D67): value and onValueChange are required and Tabs never selects itself. Tab and TabPanel pair by string value, not index, so their source order need not match. Every panel renders and unselected ones carry `hidden`, so aria-controls always resolves and panel DOM state survives a switch.
|
|
24
24
|
|
|
@@ -37,5 +37,5 @@ Override `--psi-tabs-*` custom properties at any scope; interactive states deriv
|
|
|
37
37
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
38
38
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
39
39
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
40
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
40
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
41
41
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Tag.md
CHANGED
|
@@ -47,5 +47,5 @@ Override `--psi-tag-*` custom properties at any scope.
|
|
|
47
47
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
48
48
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
49
49
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
50
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
50
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
51
51
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|
package/docs/Toast.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- Generated by emit-docs.ts — do not edit. -->
|
|
2
2
|
# Toast
|
|
3
3
|
|
|
4
|
-
A single transient notification card (D64). Controlled and presentational: it holds no state, runs no timer, and never removes itself — `onDismiss` reports and the owner disposes, exactly as Dialog (D50) and Menu (D53) do. Toast does not carry its own `role`/`aria-live`. Politeness belongs to the two persistent wrappers inside ToastRegion, because a live region must pre-exist the content it announces; a role on the toast itself would reintroduce the mount-with-content problem one level down. Composed by hand with ToastRegion for full control, or driven by ToastProvider's queue.
|
|
4
|
+
A single transient notification card (D64). Controlled and presentational: it holds no state, runs no timer, and never removes itself — `onDismiss` reports and the owner disposes, exactly as Dialog (D50) and Menu (D53) do. Toast does not carry its own `role`/`aria-live`. Politeness belongs to the two persistent wrappers inside ToastRegion, because a live region must pre-exist the content it announces; a role on the toast itself would reintroduce the mount-with-content problem one level down. `politeness` (D83) only tells the region which wrapper to use. Composed by hand with ToastRegion for full control, or driven by ToastProvider's queue.
|
|
5
5
|
|
|
6
6
|
## Props
|
|
7
7
|
|
|
@@ -11,6 +11,8 @@ A single transient notification card (D64). Controlled and presentational: it ho
|
|
|
11
11
|
| `children` | `ReactNode` | — | yes | The message. |
|
|
12
12
|
| `action` | `ReactNode` | — | no | Trailing affordance — a ghost Button (Undo, Retry, View). |
|
|
13
13
|
| `onDismiss` | `(() => void)` | — | no | When provided, renders the dismiss button and calls this. Toast does not remove itself; the owner disposes. |
|
|
14
|
+
| `politeness` | `"polite" \| "assertive"` | — | no | Which live wrapper ToastRegion routes this toast into (D83). Unset, the variant decides: neutral and success are polite, warning and danger assertive. Set it when the kind of event, not its tone, decides — the outcome of the user's own action may interrupt even when it succeeded. |
|
|
15
|
+
| `statusLabel` | `string \| null` | — | no | The visually hidden status word (D83). A string replaces the default ("Success:", "Warning:", "Error:") — pass the translated word; `null` drops it. Unset keeps the default, and `neutral` has none. |
|
|
14
16
|
| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |
|
|
15
17
|
| `ref` | `Ref<HTMLDivElement>` | — | no | Forwarded ref to the underlying `<div>`. |
|
|
16
18
|
|
|
@@ -21,7 +23,7 @@ A single transient notification card (D64). Controlled and presentational: it ho
|
|
|
21
23
|
| Tab | Reaches the action and the dismiss button in DOM order. Esc is not a dismissal — a toast is not modal and traps nothing. |
|
|
22
24
|
| Enter / Space | Activates the focused action or dismiss button. |
|
|
23
25
|
|
|
24
|
-
Presentational and controlled (D64): onDismiss reports and the owner disposes; Toast never removes itself. It carries no role/aria-live of its own — politeness belongs to ToastRegion's two persistent wrappers. The variant's meaning is announced by a visually hidden status word ("Success:", "Warning:", "Error:"), never by colour and icon shape alone; the icon is aria-hidden. neutral has no status and gets no prefix. The dismiss button requires no props — it is labelled "Dismiss notification".
|
|
26
|
+
Presentational and controlled (D64): onDismiss reports and the owner disposes; Toast never removes itself. It carries no role/aria-live of its own — politeness belongs to ToastRegion's two persistent wrappers. The variant's meaning is announced by a visually hidden status word ("Success:", "Warning:", "Error:"), never by colour and icon shape alone; the icon is aria-hidden. neutral has no status and gets no prefix. statusLabel replaces that word with a translated one, or drops it with null (D83). politeness tells ToastRegion which wrapper speaks the toast; unset, the variant decides. The dismiss button requires no props — it is labelled "Dismiss notification".
|
|
25
27
|
|
|
26
28
|
## Theming
|
|
27
29
|
|
|
@@ -48,5 +50,5 @@ Override `--psi-toast-*` custom properties at any scope.
|
|
|
48
50
|
- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.
|
|
49
51
|
- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).
|
|
50
52
|
- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.
|
|
51
|
-
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field).
|
|
53
|
+
- Field is for a control with a *visible* label. A toolbar filter control named by aria-label or placeholder takes neither a Field nor a hand-rolled label row — compare filter-toolbar (no labels) with table-pagination ("Rows per page" visible, so Field). Filters with visible labels submitted together by a Find button are filter-form: a Toolbar as="form" align="start" of Fields with one-line labels, where a field's error line is the Field's own and hangs below its control (D87, D92).
|
|
52
54
|
- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.
|