@nadicodeai/ui 12.1.111 → 12.1.114
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/AGENTS.md +11 -9
- package/README.md +3 -2
- package/dist/components/account-menu.d.ts +1 -1
- package/dist/components/account-menu.js +1 -1
- package/dist/components/action-menu.d.ts +2 -2
- package/dist/components/action-menu.js +2 -2
- package/dist/components/activity-feed.d.ts +1 -1
- package/dist/components/activity-feed.js +1 -1
- package/dist/components/agent-card.d.ts +5 -3
- package/dist/components/agent-card.d.ts.map +1 -1
- package/dist/components/agent-card.js +5 -3
- package/dist/components/agent-list-row.d.ts +2 -2
- package/dist/components/agent-list-row.js +2 -2
- package/dist/components/agent-orb.d.ts +31 -7
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/components/agent-orb.js +29 -5
- package/dist/components/agent-profile.d.ts +6 -2
- package/dist/components/agent-profile.d.ts.map +1 -1
- package/dist/components/agent-profile.js +6 -2
- package/dist/components/aspect-ratio.d.ts +7 -3
- package/dist/components/aspect-ratio.d.ts.map +1 -1
- package/dist/components/aspect-ratio.js +7 -3
- package/dist/components/avatar.d.ts +11 -5
- package/dist/components/avatar.d.ts.map +1 -1
- package/dist/components/avatar.js +11 -5
- package/dist/components/breadcrumb.d.ts +1 -1
- package/dist/components/breadcrumb.js +1 -1
- package/dist/components/button.d.ts +23 -10
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +23 -10
- package/dist/components/card-row.d.ts +4 -2
- package/dist/components/card-row.d.ts.map +1 -1
- package/dist/components/card-row.js +4 -2
- package/dist/components/card.d.ts +1 -1
- package/dist/components/card.js +1 -1
- package/dist/components/carousel.d.ts +9 -4
- package/dist/components/carousel.d.ts.map +1 -1
- package/dist/components/carousel.js +9 -4
- package/dist/components/catalog-drawer.d.ts +1 -1
- package/dist/components/catalog-drawer.js +1 -1
- package/dist/components/chart-card.d.ts +1 -1
- package/dist/components/chart-card.js +1 -1
- package/dist/components/checkbox.d.ts +2 -1
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +2 -1
- package/dist/components/choicebox.d.ts +9 -5
- package/dist/components/choicebox.d.ts.map +1 -1
- package/dist/components/choicebox.js +9 -5
- package/dist/components/clearable-input.d.ts +2 -1
- package/dist/components/clearable-input.d.ts.map +1 -1
- package/dist/components/clearable-input.js +2 -1
- package/dist/components/code-block.d.ts +13 -10
- package/dist/components/code-block.d.ts.map +1 -1
- package/dist/components/code-block.js +13 -10
- package/dist/components/collection-filters.d.ts +1 -1
- package/dist/components/collection-filters.js +1 -1
- package/dist/components/collection-search.d.ts +11 -7
- package/dist/components/collection-search.d.ts.map +1 -1
- package/dist/components/collection-search.js +11 -7
- package/dist/components/combobox.d.ts +4 -1
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +4 -1
- package/dist/components/command.d.ts +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/company-card.d.ts +28 -5
- package/dist/components/company-card.d.ts.map +1 -1
- package/dist/components/company-card.js +28 -5
- package/dist/components/confirm-dialog.d.ts +3 -2
- package/dist/components/confirm-dialog.d.ts.map +1 -1
- package/dist/components/confirm-dialog.js +2 -2
- package/dist/components/copy-button.d.ts +2 -2
- package/dist/components/copy-button.js +2 -2
- package/dist/components/data-table.d.ts +2 -2
- package/dist/components/data-table.js +2 -2
- package/dist/components/drawer.d.ts +4 -4
- package/dist/components/drawer.d.ts.map +1 -1
- package/dist/components/drawer.js +3 -3
- package/dist/components/dropdown-menu.d.ts +2 -2
- package/dist/components/dropdown-menu.js +2 -2
- package/dist/components/empty-state.d.ts +2 -2
- package/dist/components/empty-state.js +2 -2
- package/dist/components/field.d.ts +4 -0
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +4 -0
- package/dist/components/file-diff.d.ts +5 -2
- package/dist/components/file-diff.d.ts.map +1 -1
- package/dist/components/file-diff.js +5 -2
- package/dist/components/form-dialog.d.ts +1 -1
- package/dist/components/form-dialog.js +1 -1
- package/dist/components/form-drawer.d.ts +1 -1
- package/dist/components/form-drawer.js +1 -1
- package/dist/components/gauge.d.ts +9 -7
- package/dist/components/gauge.d.ts.map +1 -1
- package/dist/components/gauge.js +9 -7
- package/dist/components/hover-card.d.ts +5 -2
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +5 -2
- package/dist/components/identity-mark.d.ts +3 -3
- package/dist/components/identity-mark.js +3 -3
- package/dist/components/input-group.d.ts +1 -0
- package/dist/components/input-group.d.ts.map +1 -1
- package/dist/components/input-group.js +1 -0
- package/dist/components/input-otp.d.ts +5 -3
- package/dist/components/input-otp.d.ts.map +1 -1
- package/dist/components/input-otp.js +5 -3
- package/dist/components/input.d.ts +4 -2
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +4 -2
- package/dist/components/item.d.ts +1 -1
- package/dist/components/item.js +1 -1
- package/dist/components/kbd.d.ts +4 -2
- package/dist/components/kbd.d.ts.map +1 -1
- package/dist/components/kbd.js +4 -2
- package/dist/components/label.d.ts +8 -3
- package/dist/components/label.d.ts.map +1 -1
- package/dist/components/label.js +8 -3
- package/dist/components/load-more-button.d.ts +3 -2
- package/dist/components/load-more-button.d.ts.map +1 -1
- package/dist/components/load-more-button.js +3 -2
- package/dist/components/message-notice.d.ts +1 -1
- package/dist/components/message-notice.js +1 -1
- package/dist/components/multi-select.d.ts +6 -4
- package/dist/components/multi-select.d.ts.map +1 -1
- package/dist/components/multi-select.js +6 -4
- package/dist/components/notice-banner.d.ts +2 -2
- package/dist/components/notice-banner.js +2 -2
- package/dist/components/object-workspace.d.ts +3 -3
- package/dist/components/object-workspace.d.ts.map +1 -1
- package/dist/components/object-workspace.js +2 -2
- package/dist/components/pairing-code.d.ts +2 -2
- package/dist/components/pairing-code.js +2 -2
- package/dist/components/picture-label.d.ts +3 -2
- package/dist/components/picture-label.d.ts.map +1 -1
- package/dist/components/picture-label.js +3 -2
- package/dist/components/popover.d.ts +7 -3
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +7 -3
- package/dist/components/progress-checklist.d.ts +1 -1
- package/dist/components/progress-checklist.js +1 -1
- package/dist/components/progress.d.ts +4 -2
- package/dist/components/progress.d.ts.map +1 -1
- package/dist/components/progress.js +4 -2
- package/dist/components/qr-code.d.ts +5 -2
- package/dist/components/qr-code.d.ts.map +1 -1
- package/dist/components/qr-code.js +5 -2
- package/dist/components/radio-group.d.ts +8 -5
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js +8 -5
- package/dist/components/record-identity.d.ts +1 -1
- package/dist/components/record-identity.js +1 -1
- package/dist/components/record-list.d.ts +2 -2
- package/dist/components/record-list.js +2 -2
- package/dist/components/record-sheet.d.ts +2 -2
- package/dist/components/record-sheet.js +2 -2
- package/dist/components/record-time.d.ts +1 -1
- package/dist/components/record-time.js +1 -1
- package/dist/components/resizable.d.ts +2 -2
- package/dist/components/resizable.js +2 -2
- package/dist/components/row-edit-form.d.ts +1 -1
- package/dist/components/row-edit-form.js +1 -1
- package/dist/components/run-timeline.d.ts +2 -2
- package/dist/components/run-timeline.js +2 -2
- package/dist/components/scroll-area.d.ts +5 -3
- package/dist/components/scroll-area.d.ts.map +1 -1
- package/dist/components/scroll-area.js +5 -3
- package/dist/components/segmented-control.d.ts +1 -1
- package/dist/components/segmented-control.js +1 -1
- package/dist/components/select.d.ts +5 -3
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +5 -3
- package/dist/components/separator.d.ts +4 -2
- package/dist/components/separator.d.ts.map +1 -1
- package/dist/components/separator.js +4 -2
- package/dist/components/settings-facts.d.ts +3 -2
- package/dist/components/settings-facts.d.ts.map +1 -1
- package/dist/components/settings-facts.js +3 -2
- package/dist/components/settings-section.d.ts +1 -1
- package/dist/components/settings-section.js +1 -1
- package/dist/components/sheet.d.ts +6 -3
- package/dist/components/sheet.d.ts.map +1 -1
- package/dist/components/sheet.js +6 -3
- package/dist/components/skeleton.d.ts +1 -1
- package/dist/components/skeleton.js +1 -1
- package/dist/components/slider.d.ts +2 -1
- package/dist/components/slider.d.ts.map +1 -1
- package/dist/components/slider.js +2 -1
- package/dist/components/snippet.d.ts +3 -1
- package/dist/components/snippet.d.ts.map +1 -1
- package/dist/components/snippet.js +3 -1
- package/dist/components/sonner.d.ts +2 -2
- package/dist/components/sonner.js +2 -2
- package/dist/components/status-badge.d.ts +5 -2
- package/dist/components/status-badge.d.ts.map +1 -1
- package/dist/components/status-badge.js +5 -2
- package/dist/components/status-dot.d.ts +2 -1
- package/dist/components/status-dot.d.ts.map +1 -1
- package/dist/components/status-dot.js +2 -1
- package/dist/components/switch.d.ts +7 -6
- package/dist/components/switch.d.ts.map +1 -1
- package/dist/components/switch.js +7 -6
- package/dist/components/table.d.ts +18 -11
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +18 -11
- package/dist/components/tabs.d.ts +19 -13
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +19 -13
- package/dist/components/text-link.d.ts +9 -4
- package/dist/components/text-link.d.ts.map +1 -1
- package/dist/components/text-link.js +9 -4
- package/dist/components/text-with-copy-button.d.ts +2 -2
- package/dist/components/text-with-copy-button.js +2 -2
- package/dist/components/textarea.d.ts +4 -3
- package/dist/components/textarea.d.ts.map +1 -1
- package/dist/components/textarea.js +4 -3
- package/dist/components/tooltip.d.ts +5 -3
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +5 -3
- package/dist/components/usage-meter.d.ts +2 -2
- package/dist/components/usage-meter.js +2 -2
- package/dist/components/waiting-line.d.ts +1 -1
- package/dist/components/waiting-line.js +1 -1
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +147 -147
- package/dist/styles/shadcn.tailwind.css +8 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"qr-code.d.ts","sourceRoot":"","sources":["../../src/components/qr-code.tsx"],"names":[],"mappings":"AAQA
|
|
1
|
+
{"version":3,"file":"qr-code.d.ts","sourceRoot":"","sources":["../../src/components/qr-code.tsx"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH,iBAAS,MAAM,CAAC,EACd,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BA0BA;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -11,9 +11,12 @@ const QUIET_ZONE = 4;
|
|
|
11
11
|
* @when Opening something on a phone from a screen: a mobile sign-in, a download link.
|
|
12
12
|
* @instead Two screens compared by eye is `PairingCode`. A link a person clicks is a link.
|
|
13
13
|
* @behaviour Square dark modules on a white tile in every theme, with the quiet zone a reader
|
|
14
|
-
* needs.
|
|
14
|
+
* needs. It draws a real, scannable `value` and nothing more: the caller shows a readable fallback
|
|
15
|
+
* beside it (the link as text) and an alternative action for when scanning is unavailable, and shows
|
|
16
|
+
* the code's expiry or invalidity from the actual state of the value, not from the drawing.
|
|
15
17
|
* @words The label names what the code opens: *Open Nadia on your phone*.
|
|
16
|
-
* @access `role="img"` named by `label`.
|
|
18
|
+
* @access `role="img"` named by `label`. Keep secrets out of the label; it names what the code
|
|
19
|
+
* opens, never the value.
|
|
17
20
|
*/
|
|
18
21
|
function QrCode({ value, label, size, className, }) {
|
|
19
22
|
const { box, path } = useMemo(() => {
|
|
@@ -34,11 +34,14 @@ type RadioGroupItemProps = Omit<RadioPrimitive.Root.Props, "required"> & Control
|
|
|
34
34
|
* "A greyed-out radio with no reason reads as broken." (https://vercel.com/geist/radio) Ours: the
|
|
35
35
|
* group is named by `aria-label` or `aria-labelledby`, and each `RadioGroupItem` by `aria-label`,
|
|
36
36
|
* `aria-labelledby` or an `id` that a `FieldLabel` points at; one without a name does not compile.
|
|
37
|
-
* Options are 16 px circles 24 px apart (a dense call site passes its own `gap`)
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* disabled option
|
|
37
|
+
* Options are 16 px circles 24 px apart (a dense call site passes its own `gap`); in a `Field`,
|
|
38
|
+
* each label stands 8 px from its circle at 13 px regular weight on a 20 px line. Colour: the
|
|
39
|
+
* circle is unfilled and shows the surface it sits on, an unchecked enabled one greys its edge and
|
|
40
|
+
* fill on hover, and the chosen one darkens its edge to the ink of the primary action and shows an
|
|
41
|
+
* 8 px ink dot; nothing takes a hue, and a disabled option greys edge, dot and label together,
|
|
42
|
+
* with no hover change. On coarse or non-hover input the target grows to the touch target while
|
|
43
|
+
* the mark stays 16 px. The arrows also choose. The reason for a disabled option is written in its
|
|
44
|
+
* own help line.
|
|
42
45
|
* @words "Group label is a Title Case noun like `Deployment Region` or `Billing Cycle`."
|
|
43
46
|
* (https://vercel.com/geist/radio) "Render it via `<legend>` or a sibling label tied with
|
|
44
47
|
* `aria-labelledby`." (https://vercel.com/geist/radio) "Option labels are parallel: same part of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,MAAM,cAAc,GACtB;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5D,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACtF,cAAc,CAAC;AAEjB,KAAK,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,WAAW,CAAC;AAGrF
|
|
1
|
+
{"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../src/components/radio-group.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,MAAM,cAAc,GACtB;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5D,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACtF,cAAc,CAAC;AAEjB,KAAK,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,WAAW,CAAC;AAGrF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,+BAQ3D;AAED,iBAAS,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,mBAAmB,+BAmB7E;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -27,11 +27,14 @@ import { cn } from "../lib/utils.js";
|
|
|
27
27
|
* "A greyed-out radio with no reason reads as broken." (https://vercel.com/geist/radio) Ours: the
|
|
28
28
|
* group is named by `aria-label` or `aria-labelledby`, and each `RadioGroupItem` by `aria-label`,
|
|
29
29
|
* `aria-labelledby` or an `id` that a `FieldLabel` points at; one without a name does not compile.
|
|
30
|
-
* Options are 16 px circles 24 px apart (a dense call site passes its own `gap`)
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* disabled option
|
|
30
|
+
* Options are 16 px circles 24 px apart (a dense call site passes its own `gap`); in a `Field`,
|
|
31
|
+
* each label stands 8 px from its circle at 13 px regular weight on a 20 px line. Colour: the
|
|
32
|
+
* circle is unfilled and shows the surface it sits on, an unchecked enabled one greys its edge and
|
|
33
|
+
* fill on hover, and the chosen one darkens its edge to the ink of the primary action and shows an
|
|
34
|
+
* 8 px ink dot; nothing takes a hue, and a disabled option greys edge, dot and label together,
|
|
35
|
+
* with no hover change. On coarse or non-hover input the target grows to the touch target while
|
|
36
|
+
* the mark stays 16 px. The arrows also choose. The reason for a disabled option is written in its
|
|
37
|
+
* own help line.
|
|
35
38
|
* @words "Group label is a Title Case noun like `Deployment Region` or `Billing Cycle`."
|
|
36
39
|
* (https://vercel.com/geist/radio) "Render it via `<legend>` or a sibling label tied with
|
|
37
40
|
* `aria-labelledby`." (https://vercel.com/geist/radio) "Option labels are parallel: same part of
|
|
@@ -8,7 +8,7 @@ import { type IdentityMarkProps } from "./identity-mark.js";
|
|
|
8
8
|
* @family Status
|
|
9
9
|
* @when The first cell of every collection row: the mark, the name, and one muted line saying what the record is or where it comes from, so the row reads without a heading.
|
|
10
10
|
* @instead An Agent in a gallery is `AgentListRow`; a model is `ModelIdentity`. A descriptive item with prose and actions is `Item`.
|
|
11
|
-
* @behaviour The mark stands 16 px before the name. The name is semibold ink and the detail muted, two lines with no gap between them, so the row is an entity row; `mark` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
|
|
11
|
+
* @behaviour The mark stands 16 px before the name. The name is semibold (600) ink and the detail a muted 14 px line, two lines with no gap between them, so the row is an entity row; `mark` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
|
|
12
12
|
* @words “Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`).” (https://vercel.com/geist/entity)
|
|
13
13
|
* Ours: the name as the record calls itself, and the detail in sentence case: kind, then relation, three to six words, "Company skill · every Agent has it".
|
|
14
14
|
* @access The name is the row link's text; the mark is decorative; the title carries the full name.
|
|
@@ -10,7 +10,7 @@ import { cn } from "../lib/utils.js";
|
|
|
10
10
|
* @family Status
|
|
11
11
|
* @when The first cell of every collection row: the mark, the name, and one muted line saying what the record is or where it comes from, so the row reads without a heading.
|
|
12
12
|
* @instead An Agent in a gallery is `AgentListRow`; a model is `ModelIdentity`. A descriptive item with prose and actions is `Item`.
|
|
13
|
-
* @behaviour The mark stands 16 px before the name. The name is semibold ink and the detail muted, two lines with no gap between them, so the row is an entity row; `mark` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
|
|
13
|
+
* @behaviour The mark stands 16 px before the name. The name is semibold (600) ink and the detail a muted 14 px line, two lines with no gap between them, so the row is an entity row; `mark` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
|
|
14
14
|
* @words “Lead the left column with a scannable identifier: an `Avatar` or icon, a Title Case label, then sentence-case secondary metadata (`Member since Mar 14, 2026`).” (https://vercel.com/geist/entity)
|
|
15
15
|
* Ours: the name as the record calls itself, and the detail in sentence case: kind, then relation, three to six words, "Company skill · every Agent has it".
|
|
16
16
|
* @access The name is the row link's text; the mark is decorative; the title carries the full name.
|
|
@@ -188,8 +188,8 @@ export type RecordListWithout<TRecord extends RowData, Key extends PropertyKey>
|
|
|
188
188
|
* Ours: the records are things a person opens or acts on and that name themselves: projects, deployments, domains, members, integrations, Agents, Skills, mailboxes. A list inside another page: an Overview's exceptions, an object page's "Needs attention". A page whose whole job is the list is a `CollectionPage`, which draws this. Values edited in place (a domain, an environment variable) are the same rows with an `editor`: the row expands into its form. Of the three kinds of list, entity rows and rows edited in place are this; records compared across columns are a `DataTable`.
|
|
189
189
|
* @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
|
|
190
190
|
* “For a static key/value metadata block on a detail page, use `Description`.” (https://vercel.com/geist/entity)
|
|
191
|
-
* Ours: Geist's `Table` is a `DataTable`: this list has no visible headings and at most three facts, so a fourth fact is a table. Its `Description` is `ObjectFacts`. Events in time are an `ActivityFeed`. Reusable things a person adds from a catalogue are a `LibraryShelf`. A descriptive row with prose is an `Item`.
|
|
192
|
-
* @behaviour One bordered card, a 1 px rule between records and none after the last. A `checklist` puts the record's `ProgressChecklist` ring just before its commands, where Vercel ends a project's row with its Production Checklist; the ring opens its own drawer, never the row. Every row has its 32 px mark, its name and, under it, one muted line; `name` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record
|
|
191
|
+
* Ours: Geist's `Table` is a `DataTable`: this list has no visible headings and at most three facts, so a fourth fact is a table, and anything more than a few facts lives on the record's page. A screen gives `RecordList` the records and what each one says, never its own toolbar, table, rows or menus, and nothing else draws a record row. Its `Description` is `ObjectFacts`. Events in time are an `ActivityFeed`. Reusable things a person adds from a catalogue are a `LibraryShelf`. A descriptive row with prose is an `Item`.
|
|
192
|
+
* @behaviour One bordered card, a 1 px rule between records and none after the last. A row is 72 px, with 16 px above and below, and its columns stand left to right at the widths the list declares, so a person reads every list the same way: the `select` box (40 px, only when the list is picked from, an optional column), the identity (the rest: the one column without a size), the facts (each its `size`), the status (`status.size`), the time (`time.size`, tabular), the `checklist` ring (52 px, only when the record has steps to be ready) and the commands (`commandsSize`; left out, 64 px for the three dots alone). A `checklist` puts the record's `ProgressChecklist` ring just before its commands, where Vercel ends a project's row with its Production Checklist; the ring opens its own drawer, never the row. Every row has its 32 px mark, its name (600) and, under it, one muted 14 px line; `name` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open, and it widens for a failed action's next steps only while a row shows one. Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row: a destructive command stays in the three dots. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record shows as its catalogue message inside its own row, never a notice under the row: it replaces the detail line, with its next steps beside its commands, or under the message on a card too narrow for the row's columns. With `open` the whole row is one target and takes the `accent` hover, and a row that only opens ends in a muted chevron; a row that opens nothing never reacts to hover. With `editor` the record's row opens its form under its line. `empty` is required: `null` is the choice to draw nothing for a list with no records, and any other value is the state it draws. A note about the whole list is `footer.note`: one muted line, an optional *Learn more* after it at the left and one secondary action at the right, in a strip of its own under the count and the paging, as Vercel ends its deployments list ("Deployment retention is enabled. Learn more", *View recently deleted*). Colour is neutral, the name in ink and every other cell in the body grey, except the status badge and a failed action's message.
|
|
193
193
|
* “Pick the variant by what the user needs: no-results for a filtered list that returned zero rows, blank slate or informational for a resource the user hasn’t created, cleared for completed work, permission for role or tier denials, error for a failed load.” (https://vercel.com/geist/empty-state)
|
|
194
194
|
* Ours: `failed`, `noMatch` and `empty` are those variants, drawn inside the card.
|
|
195
195
|
* “The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`.” (https://vercel.com/geist/entity)
|
|
@@ -249,8 +249,8 @@ function RecordRows(props) {
|
|
|
249
249
|
* Ours: the records are things a person opens or acts on and that name themselves: projects, deployments, domains, members, integrations, Agents, Skills, mailboxes. A list inside another page: an Overview's exceptions, an object page's "Needs attention". A page whose whole job is the list is a `CollectionPage`, which draws this. Values edited in place (a domain, an environment variable) are the same rows with an `editor`: the row expands into its form. Of the three kinds of list, entity rows and rows edited in place are this; records compared across columns are a `DataTable`.
|
|
250
250
|
* @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
|
|
251
251
|
* “For a static key/value metadata block on a detail page, use `Description`.” (https://vercel.com/geist/entity)
|
|
252
|
-
* Ours: Geist's `Table` is a `DataTable`: this list has no visible headings and at most three facts, so a fourth fact is a table. Its `Description` is `ObjectFacts`. Events in time are an `ActivityFeed`. Reusable things a person adds from a catalogue are a `LibraryShelf`. A descriptive row with prose is an `Item`.
|
|
253
|
-
* @behaviour One bordered card, a 1 px rule between records and none after the last. A `checklist` puts the record's `ProgressChecklist` ring just before its commands, where Vercel ends a project's row with its Production Checklist; the ring opens its own drawer, never the row. Every row has its 32 px mark, its name and, under it, one muted line; `name` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record
|
|
252
|
+
* Ours: Geist's `Table` is a `DataTable`: this list has no visible headings and at most three facts, so a fourth fact is a table, and anything more than a few facts lives on the record's page. A screen gives `RecordList` the records and what each one says, never its own toolbar, table, rows or menus, and nothing else draws a record row. Its `Description` is `ObjectFacts`. Events in time are an `ActivityFeed`. Reusable things a person adds from a catalogue are a `LibraryShelf`. A descriptive row with prose is an `Item`.
|
|
253
|
+
* @behaviour One bordered card, a 1 px rule between records and none after the last. A row is 72 px, with 16 px above and below, and its columns stand left to right at the widths the list declares, so a person reads every list the same way: the `select` box (40 px, only when the list is picked from, an optional column), the identity (the rest: the one column without a size), the facts (each its `size`), the status (`status.size`), the time (`time.size`, tabular), the `checklist` ring (52 px, only when the record has steps to be ready) and the commands (`commandsSize`; left out, 64 px for the three dots alone). A `checklist` puts the record's `ProgressChecklist` ring just before its commands, where Vercel ends a project's row with its Production Checklist; the ring opens its own drawer, never the row. Every row has its 32 px mark, its name (600) and, under it, one muted 14 px line; `name` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open, and it widens for a failed action's next steps only while a row shows one. Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row: a destructive command stays in the three dots. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record shows as its catalogue message inside its own row, never a notice under the row: it replaces the detail line, with its next steps beside its commands, or under the message on a card too narrow for the row's columns. With `open` the whole row is one target and takes the `accent` hover, and a row that only opens ends in a muted chevron; a row that opens nothing never reacts to hover. With `editor` the record's row opens its form under its line. `empty` is required: `null` is the choice to draw nothing for a list with no records, and any other value is the state it draws. A note about the whole list is `footer.note`: one muted line, an optional *Learn more* after it at the left and one secondary action at the right, in a strip of its own under the count and the paging, as Vercel ends its deployments list ("Deployment retention is enabled. Learn more", *View recently deleted*). Colour is neutral, the name in ink and every other cell in the body grey, except the status badge and a failed action's message.
|
|
254
254
|
* “Pick the variant by what the user needs: no-results for a filtered list that returned zero rows, blank slate or informational for a resource the user hasn’t created, cleared for completed work, permission for role or tier denials, error for a failed load.” (https://vercel.com/geist/empty-state)
|
|
255
255
|
* Ours: `failed`, `noMatch` and `empty` are those variants, drawn inside the card.
|
|
256
256
|
* “The right column holds at most one or two controls. If the row needs more, move secondary actions into a `Dots Menu`.” (https://vercel.com/geist/entity)
|
|
@@ -28,9 +28,9 @@ export type RecordSheetProps = {
|
|
|
28
28
|
* @family Compositions
|
|
29
29
|
* @when A list's record holds more than its row shows and is only read, not changed: a Stripe event in Billing, a usage row.
|
|
30
30
|
* @instead A record changed from its list edits in its row with `RowEditForm`; a record with sections and commands of its own has its own page, an `ObjectPage`; a choice from a catalogue is a `CatalogDrawer`.
|
|
31
|
-
* @behaviour Opens from the right
|
|
31
|
+
* @behaviour Opens from the right as an inset card 12 px from the window's edges with 16 px corners, the list still behind it and usable. It is 420 px wide from 640 px, 512 px from 1024 px (the sheet's own width), and the window less its margins below 640 px. The header holds the record's name, one muted line and Close; the body scrolls through its facts as labelled values, then the read-only payload with its copy button; the footer holds one command to the record's owner. A press outside does not close it. It has no states of its own: it opens only on a record.
|
|
32
32
|
* @words The title is the record's own name, as its row shows it. The footer's command names where it goes: "Open Beta Studio".
|
|
33
|
-
* @access A
|
|
33
|
+
* @access A dialog named by its title, not `modal`: no scrim, and focus stays inside it. Escape and Close close it. Focus returns to the row it opened from (`finalFocus`) after every close but a mouse, touch or pen one, as `Sheet` does by default; a caller that passes its own `finalFocus` decides. The payload is a read-only text area named by its label.
|
|
34
34
|
*/
|
|
35
35
|
export declare function RecordSheet({ open, onOpenChange, title, description, closeLabel, facts, code, footer, finalFocus, }: RecordSheetProps): import("react").JSX.Element;
|
|
36
36
|
//# sourceMappingURL=record-sheet.d.ts.map
|
|
@@ -10,9 +10,9 @@ import { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetT
|
|
|
10
10
|
* @family Compositions
|
|
11
11
|
* @when A list's record holds more than its row shows and is only read, not changed: a Stripe event in Billing, a usage row.
|
|
12
12
|
* @instead A record changed from its list edits in its row with `RowEditForm`; a record with sections and commands of its own has its own page, an `ObjectPage`; a choice from a catalogue is a `CatalogDrawer`.
|
|
13
|
-
* @behaviour Opens from the right
|
|
13
|
+
* @behaviour Opens from the right as an inset card 12 px from the window's edges with 16 px corners, the list still behind it and usable. It is 420 px wide from 640 px, 512 px from 1024 px (the sheet's own width), and the window less its margins below 640 px. The header holds the record's name, one muted line and Close; the body scrolls through its facts as labelled values, then the read-only payload with its copy button; the footer holds one command to the record's owner. A press outside does not close it. It has no states of its own: it opens only on a record.
|
|
14
14
|
* @words The title is the record's own name, as its row shows it. The footer's command names where it goes: "Open Beta Studio".
|
|
15
|
-
* @access A
|
|
15
|
+
* @access A dialog named by its title, not `modal`: no scrim, and focus stays inside it. Escape and Close close it. Focus returns to the row it opened from (`finalFocus`) after every close but a mouse, touch or pen one, as `Sheet` does by default; a caller that passes its own `finalFocus` decides. The payload is a read-only text area named by its label.
|
|
16
16
|
*/
|
|
17
17
|
export function RecordSheet({ open, onOpenChange, title, description, closeLabel, facts, code, footer, finalFocus, }) {
|
|
18
18
|
return (_jsx(Sheet, { onOpenChange: onOpenChange, open: open, children: _jsxs(SheetContent, { className: "max-sm:data-[side=right]:left-nadicode-sm max-sm:data-[side=right]:w-auto data-[side=right]:sm:w-[420px] data-[side=right]:sm:max-w-[calc(100%-var(--nc-lg))]", closeLabel: closeLabel, finalFocus: finalFocus, side: "right", children: [_jsxs(SheetHeader, { className: "pr-12", children: [_jsx(SheetTitle, { className: "break-words", children: title }), description ? _jsx(SheetDescription, { children: description }) : null] }), _jsxs("div", { className: "grid min-h-0 flex-1 grid-cols-[minmax(0,1fr)] content-start gap-nadicode-md overflow-y-auto px-nadicode-lg pb-nadicode-lg", "data-slot": "record-sheet-body", children: [_jsx(ObjectFacts, { facts: facts }), code ? (_jsx(CodeBlock, { code: code.value, copiedLabel: code.copiedLabel, copyFailedLabel: code.copyFailedLabel, copyLabel: code.copyLabel, label: code.label })) : null] }), footer ? (_jsx(SheetFooter, { className: "flex-row justify-end", "data-slot": "record-sheet-footer", children: _jsx(PageCommandButton, { command: footer, variant: "outline" }) })) : null] }) }));
|
|
@@ -45,7 +45,7 @@ export declare function recordDate(at: Date | number | string | null | undefined
|
|
|
45
45
|
* @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
|
|
46
46
|
* Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
|
|
47
47
|
* @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
|
|
48
|
-
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
|
|
48
|
+
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing. While `at` does name a moment, `children` (*Queued*) replaces the sentence and the card stays.
|
|
49
49
|
* @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
|
|
50
50
|
* Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
|
|
51
51
|
* @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
|
|
@@ -55,7 +55,7 @@ export function recordDate(at) {
|
|
|
55
55
|
* @instead "For a static date in body prose past 7 days, render `Mar 14, 2026` directly." (https://vercel.com/geist/relative-time-card)
|
|
56
56
|
* Ours: a date a person picks is a Calendar; a span of days a page reads is a DateRangeControl; a run's duration is a fact written by the product (*Took 4 min*).
|
|
57
57
|
* @behaviour "The hover card already shows absolute UTC and local time, so don’t duplicate that copy elsewhere on the row." (https://vercel.com/geist/relative-time-card)
|
|
58
|
-
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing.
|
|
58
|
+
* Ours: relative within a week, then the day and month, with the year only when it is another year; `mode="clock"` prints the time of day in the viewer's zone in tabular figures. Hovering either shows a card that opens above after 150 ms, 13 px from the time, with a stem: the relative reading first, then the exact date and time in UTC and in the viewer's zone, each behind a zone chip, the viewer's by its offset (*GMT+2*). A page rendered on a server passes the viewer's `timeZone` when it knows it, so the server and the browser write the same time; otherwise the server and the hydrating page write UTC and the page then rewrites it in the browser's zone. A time that names no moment draws `children`, a state such as *Pending*, or nothing. While `at` does name a moment, `children` (*Queued*) replaces the sentence and the card stays.
|
|
59
59
|
* @words "Pass `date` as a number (Unix ms or epoch)." "Don’t pre-format the value, and don’t replace `children` with a formatted string." "The component’s short formatter is the canonical form (`2m`, `5h`, `Yesterday`)." "Don’t append `ago` after the component." "The formatter already produces `2m ago` / `5h ago`, so `<RelativeTimeCard /> ago` reads as `2m ago ago`." "Use `children` only for non-time labels (`Just now`, `Pending`, `Queued`) where the formatter can’t describe the state." "Pair with a leading label when the row is ambiguous on its own: `Last deploy <RelativeTimeCard date={ts} />`." (https://vercel.com/geist/relative-time-card)
|
|
60
60
|
* Ours: `at` takes a Date, epoch milliseconds or an ISO string, never a display string such as *3 hours ago*. The reading is the locale's long form (*3 hours ago*, *12 Sep*), not `2m`. The product writes the sentence through `phrase` (*Updated {when}*, *Ran {when}*), so *ago* is never added after it; the clock needs no words. The package formats every date with the person's `locale`.
|
|
61
61
|
* @access Ours: a `<time>` element with the machine-readable moment; assistive technology reads the exact local moment after the visible text.
|
|
@@ -4,8 +4,8 @@ import * as ResizablePrimitive from "react-resizable-panels";
|
|
|
4
4
|
*
|
|
5
5
|
* @family Other
|
|
6
6
|
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
7
|
-
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
|
|
8
|
-
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px
|
|
7
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column. A window too narrow for the panes side by side gets a compact alternative, one pane at a time, instead of squeezed panes.
|
|
8
|
+
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum, set where its content still reads, and its maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px wide hit area centred on it; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else. The group holds sizes only while it is mounted; the product owns persisting them.
|
|
9
9
|
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
10
10
|
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
|
11
11
|
*/
|
|
@@ -7,8 +7,8 @@ import { cn } from "../lib/utils.js";
|
|
|
7
7
|
*
|
|
8
8
|
* @family Other
|
|
9
9
|
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
10
|
-
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column.
|
|
11
|
-
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum and maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px
|
|
10
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle or `DesktopAppShell`. A width a person never changes is a plain grid column. A window too narrow for the panes side by side gets a compact alternative, one pane at a time, instead of squeezed panes.
|
|
11
|
+
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum, set where its content still reads, and its maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px wide hit area centred on it; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else. The group holds sizes only while it is mounted; the product owns persisting them.
|
|
12
12
|
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
13
13
|
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
|
14
14
|
*/
|
|
@@ -17,7 +17,7 @@ export type RowEditFormProps = Omit<ComponentProps<"form">, "children" | "classN
|
|
|
17
17
|
* @family Compositions
|
|
18
18
|
* @when A person changes a record they see in a list: edit a mailbox, a task, an MCP server, a channel. It is a `RecordList`'s `editor` or a `DataTable`'s `rowEditor`.
|
|
19
19
|
* @instead A new record from a few fields is a `FormDialog`; a fact on the record's own page changes in place in its section; a choice from a catalogue is a `CatalogDrawer`.
|
|
20
|
-
* @behaviour The fields open under the record's line; a refusal or a failed save sits above the footer. The footer, one tone below, holds an optional hint at its leading edge, then Cancel and the save rightmost. Save stays off until a field changes: the caller sets `submit.disabled` from its own fields. Cancel holds while the save runs, and the waiting line runs under them.
|
|
20
|
+
* @behaviour The fields open under the record's line, inside its row, and the other rows stay where they are; a refusal or a failed save sits above the footer. The footer, one tone below, holds an optional hint at its leading edge, then Cancel and the save rightmost. Save stays off until a field changes: the caller sets `submit.disabled` from its own fields. Cancel holds while the save runs, and the waiting line runs under them.
|
|
21
21
|
* @words The save says what it does, "Save"; Cancel is "Cancel". The hint is a way on, such as where to find a token, never a restatement of a field's label.
|
|
22
22
|
* @access A form in the row's place, which the caller moves focus into. The running save is marked busy, and the line saying why the save cannot run yet is its description (`submit.describedBy`).
|
|
23
23
|
*/
|
|
@@ -9,7 +9,7 @@ import { FormSubmitButton } from "../internal/form-submit.js";
|
|
|
9
9
|
* @family Compositions
|
|
10
10
|
* @when A person changes a record they see in a list: edit a mailbox, a task, an MCP server, a channel. It is a `RecordList`'s `editor` or a `DataTable`'s `rowEditor`.
|
|
11
11
|
* @instead A new record from a few fields is a `FormDialog`; a fact on the record's own page changes in place in its section; a choice from a catalogue is a `CatalogDrawer`.
|
|
12
|
-
* @behaviour The fields open under the record's line; a refusal or a failed save sits above the footer. The footer, one tone below, holds an optional hint at its leading edge, then Cancel and the save rightmost. Save stays off until a field changes: the caller sets `submit.disabled` from its own fields. Cancel holds while the save runs, and the waiting line runs under them.
|
|
12
|
+
* @behaviour The fields open under the record's line, inside its row, and the other rows stay where they are; a refusal or a failed save sits above the footer. The footer, one tone below, holds an optional hint at its leading edge, then Cancel and the save rightmost. Save stays off until a field changes: the caller sets `submit.disabled` from its own fields. Cancel holds while the save runs, and the waiting line runs under them.
|
|
13
13
|
* @words The save says what it does, "Save"; Cancel is "Cancel". The hint is a way on, such as where to find a token, never a restatement of a field's label.
|
|
14
14
|
* @access A form in the row's place, which the caller moves focus into. The running save is marked busy, and the line saying why the save cannot run yet is its description (`submit.describedBy`).
|
|
15
15
|
*/
|
|
@@ -17,9 +17,9 @@ export type RunTimelineStep = {
|
|
|
17
17
|
* One run of an Agent, read step by step on a neutral rail.
|
|
18
18
|
*
|
|
19
19
|
* @family Data
|
|
20
|
-
* @when The steps of one run, in order: a scheduled task's run, an Agent's handoff. Each step is something the run did or will do.
|
|
20
|
+
* @when The steps of one run, in order, one step per row: a scheduled task's run, an Agent's handoff, a workflow. Each step is something the run did or will do.
|
|
21
21
|
* @instead What happened to a record over time is an ActivityFeed; steps a person follows are NumberedSteps; the stages a system runs on an entry screen are the EntryStageList.
|
|
22
|
-
* @behaviour Each step is a node on one rail, its label and title, one line of detail, and its time at the trailing edge ("—" until it happens). The node marks the step and never grades it: the current step's node is ink, a step to come is drawn in the line colour with its title muted. An outcome that needs a person is the StatusBadge inside its step. Nothing moves.
|
|
22
|
+
* @behaviour Each step is a node on one rail, its label and title, one line of detail, and its time at the trailing edge ("—" until it happens). The node marks the step and never grades it: a done step's node is the body-grey dot, the current step's node is ink, a step to come is drawn in the line colour with its title muted. An outcome that needs a person is the StatusBadge inside its step ("Needs your decision"). Each step's time stands in the feed's column, in the feed's time style. Nothing moves. It is also a framework-neutral CSS component: the `nc-run-timeline` class on the list with the parts `nc-run-timeline-step` (carrying `data-progress` of `done`, `current` or `upcoming`), `-node`, `-content`, `-label`, `-title` and `-detail`, which another renderer can use without this component.
|
|
23
23
|
* @words The label numbers the step ("Step 01"); a done step's title is in the past tense ("Filed the invoices"), a step to come in the imperative ("Send the summary to Marco"); a waiting step's detail says what it waits for ("Waits for your decision on step 03").
|
|
24
24
|
* @access An ordered list; the current step carries `aria-current="step"`; the rail and nodes are hidden from assistive technology, and so is the dash of a step that has not happened.
|
|
25
25
|
*/
|
|
@@ -5,9 +5,9 @@ import { cn } from "../lib/utils.js";
|
|
|
5
5
|
* One run of an Agent, read step by step on a neutral rail.
|
|
6
6
|
*
|
|
7
7
|
* @family Data
|
|
8
|
-
* @when The steps of one run, in order: a scheduled task's run, an Agent's handoff. Each step is something the run did or will do.
|
|
8
|
+
* @when The steps of one run, in order, one step per row: a scheduled task's run, an Agent's handoff, a workflow. Each step is something the run did or will do.
|
|
9
9
|
* @instead What happened to a record over time is an ActivityFeed; steps a person follows are NumberedSteps; the stages a system runs on an entry screen are the EntryStageList.
|
|
10
|
-
* @behaviour Each step is a node on one rail, its label and title, one line of detail, and its time at the trailing edge ("—" until it happens). The node marks the step and never grades it: the current step's node is ink, a step to come is drawn in the line colour with its title muted. An outcome that needs a person is the StatusBadge inside its step. Nothing moves.
|
|
10
|
+
* @behaviour Each step is a node on one rail, its label and title, one line of detail, and its time at the trailing edge ("—" until it happens). The node marks the step and never grades it: a done step's node is the body-grey dot, the current step's node is ink, a step to come is drawn in the line colour with its title muted. An outcome that needs a person is the StatusBadge inside its step ("Needs your decision"). Each step's time stands in the feed's column, in the feed's time style. Nothing moves. It is also a framework-neutral CSS component: the `nc-run-timeline` class on the list with the parts `nc-run-timeline-step` (carrying `data-progress` of `done`, `current` or `upcoming`), `-node`, `-content`, `-label`, `-title` and `-detail`, which another renderer can use without this component.
|
|
11
11
|
* @words The label numbers the step ("Step 01"); a done step's title is in the past tense ("Filed the invoices"), a step to come in the imperative ("Send the summary to Marco"); a waiting step's detail says what it waits for ("Waits for your decision on step 03").
|
|
12
12
|
* @access An ordered list; the current step carries `aria-current="step"`; the rail and nodes are hidden from assistive technology, and so is the dash of a step that has not happened.
|
|
13
13
|
*/
|
|
@@ -35,13 +35,15 @@ type ScrollAreaProps = Omit<ScrollAreaPrimitive.Root.Props, "children" | "render
|
|
|
35
35
|
* “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
|
|
36
36
|
* “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
|
|
37
37
|
* “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
|
|
38
|
-
* Ours: `overflow` is required
|
|
38
|
+
* Ours: `overflow` is required, and `buttonLabels` goes only with `overflow="y"` or `"x"`, never
|
|
39
|
+
* `"both"`. Give the area its height or width with `className`, and a border or
|
|
39
40
|
* radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
|
|
40
41
|
* it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
|
|
41
42
|
* there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
|
|
42
43
|
* wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
|
|
43
|
-
* from the area: above it and centred for `y`, below it and at the start for `x`.
|
|
44
|
-
*
|
|
44
|
+
* from the area: above it and centred for `y`, below it and at the start for `x`. Each moves to the
|
|
45
|
+
* nearest direct child that is clipped at that end, not by a fixed amount, and sits disabled at the
|
|
46
|
+
* end with nothing beyond it. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
|
|
45
47
|
* only.
|
|
46
48
|
* @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
|
|
47
49
|
* Ours: *Scroll installations left*; both labels are required with the buttons.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAM/E,KAAK,YAAY,GAAG;IAClB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,UAAU,GACX;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GAC1D;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC;AAExD,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC,GAChF,UAAU,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAmCJ
|
|
1
|
+
{"version":3,"file":"scroll-area.d.ts","sourceRoot":"","sources":["../../src/components/scroll-area.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAM/E,KAAK,YAAY,GAAG;IAClB,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,UAAU,GACX;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,GAC1D;IAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC;AAExD,KAAK,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC,GAChF,UAAU,GAAG;IACX,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mGAAmG;IACnG,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,oGAAoG;IACpG,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC,CAAC;AAmCJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,eAAe,qBAyEjB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -43,13 +43,15 @@ const buttonIcons = {
|
|
|
43
43
|
* “Auto-scroll buttons target direct children only. If items are wrapped in extra layout nodes the buttons won’t find their target.” (https://vercel.com/geist/scroller)
|
|
44
44
|
* “Show edge fade or shadow affordances on the clipped axis so users see there’s more content past the viewport.” (https://vercel.com/geist/scroller)
|
|
45
45
|
* “Keep item widths and gaps consistent in horizontal scrollers; ragged edges break the snap rhythm and make the rail feel broken.” (https://vercel.com/geist/scroller)
|
|
46
|
-
* Ours: `overflow` is required
|
|
46
|
+
* Ours: `overflow` is required, and `buttonLabels` goes only with `overflow="y"` or `"x"`, never
|
|
47
|
+
* `"both"`. Give the area its height or width with `className`, and a border or
|
|
47
48
|
* radius with `frameClassName`, which draws only the scrolling box and leaves the buttons outside
|
|
48
49
|
* it. The scrollbar is hidden; a 40 px fade of the surface at each clipped edge is the only sign
|
|
49
50
|
* there is more, and it is gone at an edge with nothing beyond it. The viewport scrolls natively, so
|
|
50
51
|
* wheel, touch and keyboard all reach it. `buttonLabels` adds two round 32 px outline buttons, 16 px
|
|
51
|
-
* from the area: above it and centred for `y`, below it and at the start for `x`.
|
|
52
|
-
*
|
|
52
|
+
* from the area: above it and centred for `y`, below it and at the start for `x`. Each moves to the
|
|
53
|
+
* nearest direct child that is clipped at that end, not by a fixed amount, and sits disabled at the
|
|
54
|
+
* end with nothing beyond it. Smooth scrolling gives way to an instant jump under reduced motion. Colour is neutral
|
|
53
55
|
* only.
|
|
54
56
|
* @words “Scroller buttons need `aria-label`s that name the direction and content (`Scroll customer logos left`), not bare `Previous`/`Next`.” (https://vercel.com/geist/scroller)
|
|
55
57
|
* Ours: *Scroll installations left*; both labels are required with the buttons.
|
|
@@ -60,7 +60,7 @@ export type SegmentedControlProps<Value extends string = string> = Omit<RadioGro
|
|
|
60
60
|
* options share the width of the widest, so the fill never resizes as the choice moves; where the
|
|
61
61
|
* row is narrower than that, each option keeps its own word's width rather than cutting it. The track
|
|
62
62
|
* is white with a hairline and a 4 px inset, so it is 32, 36 or 40 px high around options of 24, 28
|
|
63
|
-
* or 32 px. Colour: neutral throughout, the chosen option filled grey with ink words and the others
|
|
63
|
+
* or 32 px. `size` `sm`, `default` and `lg` give options 24, 28 and 32 px high. Colour: neutral throughout, the chosen option filled grey with ink words and the others
|
|
64
64
|
* grey words that turn ink on hover; nothing takes a hue. Icons are 16 px, 20 px at `lg`. A
|
|
65
65
|
* disabled option keeps the chosen fill, lightens only its words and has no hover change. The
|
|
66
66
|
* options are radios in one group: arrows move and choose, and pressing the chosen one changes
|
|
@@ -62,7 +62,7 @@ const segmentedItemVariants = cva("relative flex cursor-pointer items-center jus
|
|
|
62
62
|
* options share the width of the widest, so the fill never resizes as the choice moves; where the
|
|
63
63
|
* row is narrower than that, each option keeps its own word's width rather than cutting it. The track
|
|
64
64
|
* is white with a hairline and a 4 px inset, so it is 32, 36 or 40 px high around options of 24, 28
|
|
65
|
-
* or 32 px. Colour: neutral throughout, the chosen option filled grey with ink words and the others
|
|
65
|
+
* or 32 px. `size` `sm`, `default` and `lg` give options 24, 28 and 32 px high. Colour: neutral throughout, the chosen option filled grey with ink words and the others
|
|
66
66
|
* grey words that turn ink on hover; nothing takes a hue. Icons are 16 px, 20 px at `lg`. A
|
|
67
67
|
* disabled option keeps the chosen fill, lightens only its words and has no hover change. The
|
|
68
68
|
* options are radios in one group: arrows move and choose, and pressing the chosen one changes
|
|
@@ -9,16 +9,18 @@ import { type FieldSize } from "../internal/input-box.js";
|
|
|
9
9
|
* @when "Display a dropdown list of items." (https://vercel.com/geist/select) "Pick `<Select>` for
|
|
10
10
|
* short, fixed lists (under ~10 items) where typing adds nothing; switch to `Combobox` once
|
|
11
11
|
* filtering helps." (https://vercel.com/geist/select) Ours: four or more
|
|
12
|
-
* options, each short enough to need no sentence: how often a task runs.
|
|
12
|
+
* options, each short enough to need no sentence: how often a task runs. A list of two or three
|
|
13
|
+
* static options is a `RadioGroup`, as Geist says.
|
|
13
14
|
* @instead "Use `MultiSelect` when more than one value can be chosen at once; use `Switch` for a
|
|
14
15
|
* 2–3 option segmented choice." (https://vercel.com/geist/select) Ours: two or three options are
|
|
15
16
|
* radios or a segmented control. Inside a native form a long list is `NativeSelect`.
|
|
16
17
|
* @behaviour The trigger is `Input`'s box: its sizes, its ring, hover, focus halo and disabled, the
|
|
17
|
-
* label above it and the message under it
|
|
18
|
+
* label above it and the message under it, in the three sizes `sm`, default and `lg` that `Input`
|
|
19
|
+
* has. Colour sits in one place: an error turns the ring red
|
|
18
20
|
* and fills the halo, and colours the message; the fill, the value, the chevron and the label stay
|
|
19
21
|
* neutral. It shows the chosen value, after an optional `prefix` mark, with the chevron at the end
|
|
20
22
|
* in the muted grey (a `suffix` mark takes the chevron's place), and fills its container; it keeps
|
|
21
|
-
* the hover edge while its list is open. The list, a solid floating surface, opens under it, 8 px away, never covering the
|
|
23
|
+
* the hover edge while its list is open. The list, a solid floating surface with a 12 px corner, opens under it, 8 px away, never covering the
|
|
22
24
|
* trigger (`alignItemWithTrigger` is off), in a 6 px inset, with a 14 px check at the chosen row's
|
|
23
25
|
* end, rows 36 px tall and no gap between them; a row that cannot be chosen turns its text muted,
|
|
24
26
|
* never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/components/select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAKlE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAG9B
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/components/select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAKlE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAG9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,QAAA,MAAM,MAAM,6BAAuB,CAAC;AAEpC,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,qBAQxE;AAED;;;GAGG;AACH,QAAA,MAAM,qBAAqB;;8EAgB1B,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG;IACxE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,kDAAkD;IAClD,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,IAAgB,EAChB,MAAM,EACN,MAAM,EACN,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,qBAyCpB;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,IAAe,EACf,UAAc,EACd,KAAgB,EAChB,WAAe,EACf,oBAA4B,EAC5B,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,GAC5B,IAAI,CACF,eAAe,CAAC,UAAU,CAAC,KAAK,EAChC,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,GAAG,sBAAsB,CACzE,qBA6BF;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,UAAU,CAAC,KAAK,qBAQ7E;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,qBAsBhF;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,CAAC,SAAS,CAAC,KAAK,qBAQhF;AAED,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,aAAa,CAAC,qBAa5D;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,eAAe,CAAC,eAAe,CAAC,qBAa9D;AAED,OAAO,EACL,MAAM,EACN,aAAa,EACb,WAAW,EACX,UAAU,EACV,WAAW,EACX,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,WAAW,GACZ,CAAC"}
|
|
@@ -14,16 +14,18 @@ import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
|
|
|
14
14
|
* @when "Display a dropdown list of items." (https://vercel.com/geist/select) "Pick `<Select>` for
|
|
15
15
|
* short, fixed lists (under ~10 items) where typing adds nothing; switch to `Combobox` once
|
|
16
16
|
* filtering helps." (https://vercel.com/geist/select) Ours: four or more
|
|
17
|
-
* options, each short enough to need no sentence: how often a task runs.
|
|
17
|
+
* options, each short enough to need no sentence: how often a task runs. A list of two or three
|
|
18
|
+
* static options is a `RadioGroup`, as Geist says.
|
|
18
19
|
* @instead "Use `MultiSelect` when more than one value can be chosen at once; use `Switch` for a
|
|
19
20
|
* 2–3 option segmented choice." (https://vercel.com/geist/select) Ours: two or three options are
|
|
20
21
|
* radios or a segmented control. Inside a native form a long list is `NativeSelect`.
|
|
21
22
|
* @behaviour The trigger is `Input`'s box: its sizes, its ring, hover, focus halo and disabled, the
|
|
22
|
-
* label above it and the message under it
|
|
23
|
+
* label above it and the message under it, in the three sizes `sm`, default and `lg` that `Input`
|
|
24
|
+
* has. Colour sits in one place: an error turns the ring red
|
|
23
25
|
* and fills the halo, and colours the message; the fill, the value, the chevron and the label stay
|
|
24
26
|
* neutral. It shows the chosen value, after an optional `prefix` mark, with the chevron at the end
|
|
25
27
|
* in the muted grey (a `suffix` mark takes the chevron's place), and fills its container; it keeps
|
|
26
|
-
* the hover edge while its list is open. The list, a solid floating surface, opens under it, 8 px away, never covering the
|
|
28
|
+
* the hover edge while its list is open. The list, a solid floating surface with a 12 px corner, opens under it, 8 px away, never covering the
|
|
27
29
|
* trigger (`alignItemWithTrigger` is off), in a 6 px inset, with a 14 px check at the chosen row's
|
|
28
30
|
* end, rows 36 px tall and no gap between them; a row that cannot be chosen turns its text muted,
|
|
29
31
|
* never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never
|
|
@@ -5,11 +5,13 @@ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
|
|
|
5
5
|
* @family Other
|
|
6
6
|
* @when Ours: separating groups inside one surface: menu sections, a card's header from its toolbar,
|
|
7
7
|
* inline items in a row. Horizontal between stacked groups, vertical between items in a row.
|
|
8
|
-
* @instead Ours: a
|
|
8
|
+
* @instead Ours: `FieldSeparator` divides a form's fields and the menu and group separators divide a
|
|
9
|
+
* menu's or a group's items, each for its scoped role. A card's footer draws its own seam; a list in a card is a `divided` `ItemGroup`. Never a
|
|
9
10
|
* border around a region.
|
|
10
11
|
* @behaviour “Use `inset` when a divider meets a 1px frame painted over the content. The separator reserves 1px at each end and uses solid `gray-400`. A physical parent border already reserves its edge space and does not need this inset.” (https://vercel.com/geist/separator)
|
|
11
12
|
* Ours: horizontal or vertical, exactly 1 px, in the `border` colour (not `gray-400`) and never any
|
|
12
|
-
* other: a separator has no hue, no state and no padding.
|
|
13
|
+
* other: a separator has no hue, no state and no padding. `inset` keeps 1 px clear at each end,
|
|
14
|
+
* for a divider that meets a frame painted over the content. A vertical one takes its height from the
|
|
13
15
|
* flex row that holds it, so give the row a height and `items-center`.
|
|
14
16
|
* @words None.
|
|
15
17
|
* @access Ours: hidden from assistive technology, since it only paints a line; pass `aria-hidden={false}`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../src/components/separator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI3E
|
|
1
|
+
{"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../src/components/separator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAI3E;;;;;;;;;;;;;;;;;GAiBG;AACH,iBAAS,SAAS,CAAC,EACjB,SAAS,EACT,KAAa,EACb,WAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,kBAAkB,CAAC,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,+BAchD;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -7,11 +7,13 @@ import { cn } from "../lib/utils.js";
|
|
|
7
7
|
* @family Other
|
|
8
8
|
* @when Ours: separating groups inside one surface: menu sections, a card's header from its toolbar,
|
|
9
9
|
* inline items in a row. Horizontal between stacked groups, vertical between items in a row.
|
|
10
|
-
* @instead Ours: a
|
|
10
|
+
* @instead Ours: `FieldSeparator` divides a form's fields and the menu and group separators divide a
|
|
11
|
+
* menu's or a group's items, each for its scoped role. A card's footer draws its own seam; a list in a card is a `divided` `ItemGroup`. Never a
|
|
11
12
|
* border around a region.
|
|
12
13
|
* @behaviour “Use `inset` when a divider meets a 1px frame painted over the content. The separator reserves 1px at each end and uses solid `gray-400`. A physical parent border already reserves its edge space and does not need this inset.” (https://vercel.com/geist/separator)
|
|
13
14
|
* Ours: horizontal or vertical, exactly 1 px, in the `border` colour (not `gray-400`) and never any
|
|
14
|
-
* other: a separator has no hue, no state and no padding.
|
|
15
|
+
* other: a separator has no hue, no state and no padding. `inset` keeps 1 px clear at each end,
|
|
16
|
+
* for a divider that meets a frame painted over the content. A vertical one takes its height from the
|
|
15
17
|
* flex row that holds it, so give the row a height and `items-center`.
|
|
16
18
|
* @words None.
|
|
17
19
|
* @access Ours: hidden from assistive technology, since it only paints a line; pass `aria-hidden={false}`
|
|
@@ -53,8 +53,9 @@ export type SettingsFactsSectionProps = SettingsFactsBase & ({
|
|
|
53
53
|
* compared across records are a table. A relation is its identity or a `Tag`, never its own card.
|
|
54
54
|
* @behaviour "Use `<Description>` for definition-list metadata: a short Title Case key paired with a single value (`Last Deployed`, `Region`, `Plan`)." (https://vercel.com/geist/description)
|
|
55
55
|
* Ours: required: the description and the footer's left line (`footerHint`), as on a
|
|
56
|
-
* `SettingsSection`; `footer` holds actions, never a Save.
|
|
57
|
-
*
|
|
56
|
+
* `SettingsSection`; `footer` holds actions, never a Save. Facts are plain pairs, the label above
|
|
57
|
+
* its value, in two equal columns from 640 px (`sm`) and one column below it. Every label stays when its value is missing,
|
|
58
|
+
* as *—*. A long value
|
|
58
59
|
* spans both columns. No fact gets a box of its own. In a side column, `presentation="summary"`
|
|
59
60
|
* drops the card, the description and the footer line.
|
|
60
61
|
* @words "Title slot is Title Case noun (`Last Deployed`, `Build Duration`); content is sentence case unless the value is a literal identifier, ID, or timestamp that should be preserved verbatim." (https://vercel.com/geist/description)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-facts.d.ts","sourceRoot":"","sources":["../../src/components/settings-facts.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAM7E,OAAO,EACL,IAAI,EAMJ,KAAK,WAAW,EACjB,MAAM,QAAQ,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,KAAK,iBAAiB,GAAG,IAAI,CAAC,wBAAwB,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG;IAC7F,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,GACvD,CACI;IACE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,6FAA6F;IAC7F,UAAU,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,wBAAwB,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;CACtD,GACD;IACE,YAAY,EAAE,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,CACJ,CAAC;AAEJ
|
|
1
|
+
{"version":3,"file":"settings-facts.d.ts","sourceRoot":"","sources":["../../src/components/settings-facts.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAM7E,OAAO,EACL,IAAI,EAMJ,KAAK,WAAW,EACjB,MAAM,QAAQ,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,KAAK,iBAAiB,GAAG,IAAI,CAAC,wBAAwB,CAAC,SAAS,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG;IAC7F,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,iBAAiB,GACvD,CACI;IACE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,6FAA6F;IAC7F,UAAU,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,wBAAwB,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;CACtD,GACD;IACE,YAAY,EAAE,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;CACd,CACJ,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,YAAqB,EACrB,WAAW,EACX,KAAK,EACL,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,KAAK,EACL,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,yBAAyB,+BAiE3B"}
|
|
@@ -16,8 +16,9 @@ import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle,
|
|
|
16
16
|
* compared across records are a table. A relation is its identity or a `Tag`, never its own card.
|
|
17
17
|
* @behaviour "Use `<Description>` for definition-list metadata: a short Title Case key paired with a single value (`Last Deployed`, `Region`, `Plan`)." (https://vercel.com/geist/description)
|
|
18
18
|
* Ours: required: the description and the footer's left line (`footerHint`), as on a
|
|
19
|
-
* `SettingsSection`; `footer` holds actions, never a Save.
|
|
20
|
-
*
|
|
19
|
+
* `SettingsSection`; `footer` holds actions, never a Save. Facts are plain pairs, the label above
|
|
20
|
+
* its value, in two equal columns from 640 px (`sm`) and one column below it. Every label stays when its value is missing,
|
|
21
|
+
* as *—*. A long value
|
|
21
22
|
* spans both columns. No fact gets a box of its own. In a side column, `presentation="summary"`
|
|
22
23
|
* drops the card, the description and the footer line.
|
|
23
24
|
* @words "Title slot is Title Case noun (`Last Deployed`, `Build Duration`); content is sentence case unless the value is a literal identifier, ID, or timestamp that should be preserved verbatim." (https://vercel.com/geist/description)
|
|
@@ -99,7 +99,7 @@ export type SavingSettingsSectionProps = SettingsSectionBase & SavingSection;
|
|
|
99
99
|
* @family Compositions
|
|
100
100
|
* @when One setting a person changes on a SettingsPage or as a section of an ObjectPage: Personal details, Company identity, Notifications. A typed value takes `save`; a switch or a short reversible choice applies at once through its own control's change, with no Save. Also a plan-gated feature, a delete card, one read-only value (an ID in a read-only mono InputGroup with its copy button, no Save), and a paid quantity (its stepper field, the price as the description, a two-fact summary under it).
|
|
101
101
|
* @instead Read-only facts of an object are a SettingsFactsSection; a table or a list of records is a TableCard; Theme and Language live in the account menu; a record's edit in a list is a RowEditForm.
|
|
102
|
-
* @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card: a single SettingsField, the description its only help. One more shape exists, declared by a part and never by classes at the call site. A card of several settings holds SettingsRows, label left and control right, only when every row is a switch or every row is a select. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: that switch is `headerSwitch`: at the title's right, named by the title, the footer holding only its line, no Save; a switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with Save. Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` for a permanent loss, `warning` for a disruptive command that can be undone. A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` is the reason,
|
|
102
|
+
* @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card: a single SettingsField, the description its only help. A typed value (a name, a URL, a server, a port, a key) gets its own card. A semantic subgroup of related controls inside a field, such as radios or checkboxes, is a `FieldSet` with a `FieldLegend`. One more shape exists, declared by a part and never by classes at the call site. A card of several settings holds SettingsRows, label left and control right, only when every row is a switch or every row is a select. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: that switch is `headerSwitch`: at the title's right, named by the title, the footer holding only its line, no Save; a switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with its own Save in the footer, always visible. The section owns the changed state: Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled, with no saved state in the footer. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it, the line saying the condition in words; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` (red) for a permanent loss (Delete), `warning` (amber) for a disruptive command that can be undone (Pause, Archive). A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` (Geist's disabled wall) is the reason, written as the footer's line, not in a tooltip; it keeps the fields in view, inert with muted text, under a not-allowed cursor, the title and line unchanged; `unlock` is the way to get access, left out when nothing the person does unlocks it. A locked section has no `save` and no header `actions`.
|
|
103
103
|
* @words "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input) Ours: the description is that helper text for the whole card, and no field has its own. "Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation." (https://vercel.com/geist/toggle) Ours: a header-switch card's description says what turning it on does. The title names the values ("Personal details"); the description says what changing them does, in one line; the footer line is a Learn more link, a limit ("Use 32 characters at most."), what stays unaffected, or what is blocked and why ("Ask an owner to change this."); Save and Saving come from the product's catalogue, and so does the toast a `saved` callback raises; a delete card's description opens "Permanently delete".
|
|
104
104
|
* @access "Provide an accessible name through `children`, `aria-label`, or `aria-labelledby`." (https://vercel.com/geist/toggle) Ours: the title is the section's h2 and names the form that saves it, and the header switch. The footer's line is one status, announced politely; a failure under a field marks the control invalid and describes it. Locked fields are inert, so the section's title, description and reason are what a screen reader meets.
|
|
105
105
|
*/
|