@nadicodeai/ui 12.1.129 → 12.1.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/components/agent-list-row.d.ts +4 -7
  2. package/dist/components/agent-list-row.d.ts.map +1 -1
  3. package/dist/components/agent-list-row.js +5 -6
  4. package/dist/components/combobox.d.ts +9 -2
  5. package/dist/components/combobox.d.ts.map +1 -1
  6. package/dist/components/combobox.js +14 -5
  7. package/dist/components/data-table.d.ts +5 -3
  8. package/dist/components/data-table.d.ts.map +1 -1
  9. package/dist/components/data-table.js +2 -1
  10. package/dist/components/identity-mark.d.ts +10 -5
  11. package/dist/components/identity-mark.d.ts.map +1 -1
  12. package/dist/components/identity-mark.js +9 -5
  13. package/dist/components/record-identity.d.ts +1 -1
  14. package/dist/components/record-identity.d.ts.map +1 -1
  15. package/dist/components/record-identity.js +3 -3
  16. package/dist/components/record-list.d.ts +1 -1
  17. package/dist/components/record-list.js +2 -2
  18. package/dist/components/select.d.ts +8 -2
  19. package/dist/components/select.d.ts.map +1 -1
  20. package/dist/components/select.js +15 -7
  21. package/dist/components/settings-section.d.ts +1 -1
  22. package/dist/components/settings-section.d.ts.map +1 -1
  23. package/dist/components/settings-section.js +7 -3
  24. package/dist/eslint/rules/no-shadcn-appearance-override.js +1 -1
  25. package/dist/internal/table-compact-line.d.ts +4 -0
  26. package/dist/internal/table-compact-line.d.ts.map +1 -1
  27. package/dist/internal/table-compact-line.js +15 -2
  28. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  29. package/dist/showcase/specimens/navigation.js +1 -1
  30. package/dist/showcase/usage.generated.js +13 -13
  31. package/dist/styles/components.css +37 -0
  32. package/package.json +2 -2
@@ -1,6 +1,5 @@
1
1
  import type { CSSProperties } from "react";
2
2
  import { type AgentOrbFigure, type AgentOrbState } from "./agent-orb.js";
3
- import { type StatusBadgeTone } from "./status-badge.js";
4
3
  /**
5
4
  * One Agent in a list of them: the orb, the name, and the line that says what
6
5
  * the Agent is doing now or what it is for.
@@ -8,11 +7,11 @@ import { type StatusBadgeTone } from "./status-badge.js";
8
7
  * @family Navigation
9
8
  * @when Nadia's Agents in her window's sidebar, and a website scene that shows a list of Agents.
10
9
  * @instead An Agent as a record among others in a page's list is a RecordList row with an agent IdentityMark; an Agent's own page heads with ObjectPage.
11
- * @behaviour It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. A state tone draws the state line as a small StatusBadge; without a tone it stays plain text. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.
12
- * @words The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). The tone never says more than the line does. Nadia's list says "Working", "Idle" or "Needs you"; the badge marks a state that needs the person ("Needs you", a failed set-up), and the orb shows working by itself.
13
- * @access The orb is decorative; the name and the state line are the row's text, read by its control. StatusBadge owns its decorative shape, so the line carries its meaning.
10
+ * @behaviour It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. The orb carries the Agent's state, working, waiting on the person or blocked, so the state line is plain muted text and never a badge. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.
11
+ * @words The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). Nadia's list says "Working", "Idle" or "Needs you".
12
+ * @access The orb is decorative; the name and the state line are the row's text, read by its control.
14
13
  */
15
- export declare function AgentListRow({ className, color, current, form, motionKey, name, narrow, size, state, stateLine, stateTone, ...props }: Omit<React.ComponentProps<"span">, "color"> & {
14
+ export declare function AgentListRow({ className, color, current, form, motionKey, name, narrow, size, state, stateLine, ...props }: Omit<React.ComponentProps<"span">, "color"> & {
16
15
  /** The pigment of the Agent's chosen form; Nadia's striped ribbon keeps her own. */
17
16
  color?: CSSProperties["color"];
18
17
  /** The row the list is on now. */
@@ -26,7 +25,5 @@ export declare function AgentListRow({ className, color, current, form, motionKe
26
25
  state?: AgentOrbState;
27
26
  /** What the Agent is doing, or what it is for. Absent, the name stands alone. */
28
27
  stateLine?: string;
29
- /** How the state line stands: a failure is `danger`. Absent, the line stays plain text. */
30
- stateTone?: StatusBadgeTone;
31
28
  }): import("react").JSX.Element;
32
29
  //# sourceMappingURL=agent-list-row.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent-list-row.d.ts","sourceRoot":"","sources":["../../src/components/agent-list-row.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,EAAY,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG9E;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,OAAe,EACf,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,MAAc,EACd,IAAS,EACT,KAAc,EACd,SAAS,EACT,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG;IAC/C,oFAAoF;IACpF,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,+BAoCA"}
1
+ {"version":3,"file":"agent-list-row.d.ts","sourceRoot":"","sources":["../../src/components/agent-list-row.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,EAAY,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG3F;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,OAAe,EACf,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,MAAc,EACd,IAAS,EACT,KAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG;IAC/C,oFAAoF;IACpF,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAgCA"}
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AgentOrb } from "./agent-orb.js";
4
- import { StatusBadge } from "./status-badge.js";
5
4
  import { cn } from "../lib/utils.js";
6
5
  /**
7
6
  * One Agent in a list of them: the orb, the name, and the line that says what
@@ -10,10 +9,10 @@ import { cn } from "../lib/utils.js";
10
9
  * @family Navigation
11
10
  * @when Nadia's Agents in her window's sidebar, and a website scene that shows a list of Agents.
12
11
  * @instead An Agent as a record among others in a page's list is a RecordList row with an agent IdentityMark; an Agent's own page heads with ObjectPage.
13
- * @behaviour It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. A state tone draws the state line as a small StatusBadge; without a tone it stays plain text. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.
14
- * @words The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). The tone never says more than the line does. Nadia's list says "Working", "Idle" or "Needs you"; the badge marks a state that needs the person ("Needs you", a failed set-up), and the orb shows working by itself.
15
- * @access The orb is decorative; the name and the state line are the row's text, read by its control. StatusBadge owns its decorative shape, so the line carries its meaning.
12
+ * @behaviour It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. The orb carries the Agent's state, working, waiting on the person or blocked, so the state line is plain muted text and never a badge. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.
13
+ * @words The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). Nadia's list says "Working", "Idle" or "Needs you".
14
+ * @access The orb is decorative; the name and the state line are the row's text, read by its control.
16
15
  */
17
- export function AgentListRow({ className, color, current = false, form, motionKey, name, narrow = false, size = 40, state = "idle", stateLine, stateTone, ...props }) {
18
- return (_jsxs("span", { className: cn("flex w-full min-w-0 items-center gap-3 text-left text-sm", size === 64 && "gap-1", narrow && "justify-center", className), "data-slot": "agent-list-row", "data-current": current || undefined, ...props, children: [_jsx(AgentOrb, { className: cn(size === 64 && "-my-1.5 -ml-1"), color: color, decorative: true, form: form, motionKey: motionKey, size: size, state: state }), _jsxs("span", { className: cn("grid min-w-0", narrow && "sr-only"), children: [_jsx("span", { className: cn("truncate text-foreground", current && "font-medium"), children: name }), stateLine ? (_jsx("span", { className: "flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground", children: stateTone ? (_jsx(StatusBadge, { label: stateLine, size: "sm", tone: stateTone })) : (_jsx("span", { className: "truncate", children: stateLine })) })) : null] })] }));
16
+ export function AgentListRow({ className, color, current = false, form, motionKey, name, narrow = false, size = 40, state = "idle", stateLine, ...props }) {
17
+ return (_jsxs("span", { className: cn("flex w-full min-w-0 items-center gap-3 text-left text-sm", size === 64 && "gap-1", narrow && "justify-center", className), "data-slot": "agent-list-row", "data-current": current || undefined, ...props, children: [_jsx(AgentOrb, { className: cn(size === 64 && "-my-1.5 -ml-1"), color: color, decorative: true, form: form, motionKey: motionKey, size: size, state: state }), _jsxs("span", { className: cn("grid min-w-0", narrow && "sr-only"), children: [_jsx("span", { className: cn("truncate text-foreground", current && "font-medium"), children: name }), stateLine ? (_jsx("span", { className: "flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground", children: _jsx("span", { className: "truncate", children: stateLine }) })) : null] })] }));
19
18
  }
@@ -29,7 +29,11 @@ import { type FieldSize } from "../internal/input-box.js";
29
29
  * the placeholder, marks and list stay neutral. `label` and `error` go on `ComboboxInput`, and a
30
30
  * string `label` requires `id`; a box with no name does not compile. The list, a solid floating surface, opens 8 px under it
31
31
  * at its width (a narrower `className` width centres under the box), in a 6 px inset, up to five
32
- * and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap.
32
+ * and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap;
33
+ * a `long` list, one people scan by section, shows twelve and a half rows (462 px).
34
+ * A trigger that opens a list with its own search puts `ComboboxInput` first in `ComboboxContent`:
35
+ * there the box draws no ring or halo, spans the list on its surface, and a hairline divides it
36
+ * from the rows, wherever it sits in the content.
33
37
  * A row is one line that ends in an ellipsis, with a 16 px mark 12 px before the name and a 14 px
34
38
  * check at the chosen row's end, after the name. A row that cannot be chosen turns its text muted,
35
39
  * never dimmed. Typing filters the list. "Options can opt out of the fixed row height with `ignoreDefaultHeight`
@@ -98,7 +102,10 @@ declare function ComboboxContent({ className, side, sideOffset, align, alignOffs
98
102
  /** What the list says when nothing matches, quoting the query; `null` while a search runs. */
99
103
  empty: string | null;
100
104
  }): React.JSX.Element;
101
- declare function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props): React.JSX.Element;
105
+ declare function ComboboxList({ className, long, ...props }: ComboboxPrimitive.List.Props & {
106
+ /** A list people scan by section, such as the models of every lab: twelve and a half rows. */
107
+ long?: boolean;
108
+ }): React.JSX.Element;
102
109
  declare function ComboboxItem({ className, children, ...props }: ComboboxPrimitive.Item.Props): React.JSX.Element;
103
110
  declare function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props): React.JSX.Element;
104
111
  declare function ComboboxLabel({ className, ...props }: ComboboxPrimitive.GroupLabel.Props): React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.tsx"],"names":[],"mappings":"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"}
@@ -34,7 +34,11 @@ import { ChevronDownIcon, XIcon, CheckIcon, SearchIcon } from "lucide-react";
34
34
  * the placeholder, marks and list stay neutral. `label` and `error` go on `ComboboxInput`, and a
35
35
  * string `label` requires `id`; a box with no name does not compile. The list, a solid floating surface, opens 8 px under it
36
36
  * at its width (a narrower `className` width centres under the box), in a 6 px inset, up to five
37
- * and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap.
37
+ * and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap;
38
+ * a `long` list, one people scan by section, shows twelve and a half rows (462 px).
39
+ * A trigger that opens a list with its own search puts `ComboboxInput` first in `ComboboxContent`:
40
+ * there the box draws no ring or halo, spans the list on its surface, and a hairline divides it
41
+ * from the rows, wherever it sits in the content.
38
42
  * A row is one line that ends in an ellipsis, with a 16 px mark 12 px before the name and a 14 px
39
43
  * check at the chosen row's end, after the name. A row that cannot be chosen turns its text muted,
40
44
  * never dimmed. Typing filters the list. "Options can opt out of the fixed row height with `ignoreDefaultHeight`
@@ -84,15 +88,20 @@ function ComboboxTrigger({ className, children, ...props }) {
84
88
  function ComboboxClear({ className, ...props }) {
85
89
  return (_jsx(ComboboxPrimitive.Clear, { "data-slot": "combobox-clear", render: _jsx(InputGroupButton, { variant: "ghost", size: "icon", "aria-label": props["aria-label"] }), className: cn(className), ...props, children: _jsx(XIcon, { className: "pointer-events-none size-3.5" }) }));
86
90
  }
91
+ /** True inside `ComboboxContent`, where `ComboboxInput` is the list's own search. */
92
+ const InComboboxList = React.createContext(false);
87
93
  function ComboboxInput({ className, children, disabled = false, showTrigger = true, triggerLabel, showClear = false, clearLabel, size, label, error, ...props }) {
88
94
  const hasButton = showTrigger || showClear;
89
- return (_jsx(FieldFrame, { label: label, error: error, size: size, control: props, children: (aria) => (_jsxs(InputGroup, { size: size, className: className, children: [_jsx(InputGroupAddon, { children: _jsx(SearchIcon, { "aria-hidden": "true" }) }), _jsx(ComboboxPrimitive.Input, { render: _jsx(InputGroupControl, { disabled: disabled, className: cn("aria-invalid:text-destructive", hasButton && "pr-0") }), ...props, ...aria }), hasButton ? (_jsxs(InputGroupAddon, { align: "inline-end", children: [showTrigger && triggerLabel !== undefined ? (_jsx(InputGroupButton, { size: "icon", variant: "ghost", "aria-label": triggerLabel, render: _jsx(ComboboxTrigger, {}), "data-slot": "input-group-button", className: "group-data-[size=default]/input-group:h-7.5 group-data-[size=default]/input-group:self-center group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent", disabled: disabled })) : null, showClear && clearLabel !== undefined ? (_jsx(ComboboxClear, { "aria-label": clearLabel, disabled: disabled })) : null] })) : null, children] })) }));
95
+ const inList = React.useContext(InComboboxList);
96
+ return (_jsx(FieldFrame, { label: label, error: error, size: size, control: props, children: (aria) => (_jsxs(InputGroup, { size: size, className: cn(inList && "rounded-none border-b border-border bg-transparent shadow-none", className), children: [_jsx(InputGroupAddon, { children: _jsx(SearchIcon, { "aria-hidden": "true" }) }), _jsx(ComboboxPrimitive.Input, { render: _jsx(InputGroupControl, { disabled: disabled, className: cn("aria-invalid:text-destructive", hasButton && "pr-0") }), ...props, ...aria }), hasButton ? (_jsxs(InputGroupAddon, { align: "inline-end", children: [showTrigger && triggerLabel !== undefined ? (_jsx(InputGroupButton, { size: "icon", variant: "ghost", "aria-label": triggerLabel, render: _jsx(ComboboxTrigger, {}), "data-slot": "input-group-button", className: "group-data-[size=default]/input-group:h-7.5 group-data-[size=default]/input-group:self-center group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent", disabled: disabled })) : null, showClear && clearLabel !== undefined ? (_jsx(ComboboxClear, { "aria-label": clearLabel, disabled: disabled })) : null] })) : null, children] })) }));
90
97
  }
91
98
  function ComboboxContent({ className, side = "bottom", sideOffset = 8, align = "center", alignOffset = 0, anchor, empty, children, ...props }) {
92
- return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: "isolate z-50", children: _jsxs(ComboboxPrimitive.Popup, { "data-slot": "combobox-content", className: cn("pointer-events-auto", "group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) overflow-hidden rounded-lg border-0 bg-popover text-popover-foreground nc-elevation-floating *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-control-height *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:shadow-[0_0_0_1px_color-mix(in_oklab,var(--input)_30%,transparent)]", anchoredOverlayMotion, className), ...props, children: [empty === null ? null : _jsx(ComboboxEmpty, { children: empty }), children] }) }) }));
99
+ return (_jsx(ComboboxPrimitive.Portal, { children: _jsx(ComboboxPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, anchor: anchor, className: "isolate z-50", children: _jsx(ComboboxPrimitive.Popup, { "data-slot": "combobox-content", className: cn("pointer-events-auto", "group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) overflow-hidden rounded-lg border-0 bg-popover text-popover-foreground nc-elevation-floating", anchoredOverlayMotion, className), ...props, children: _jsxs(InComboboxList.Provider, { value: true, children: [empty === null ? null : _jsx(ComboboxEmpty, { children: empty }), children] }) }) }) }));
93
100
  }
94
- function ComboboxList({ className, ...props }) {
95
- return (_jsx(ComboboxPrimitive.List, { "data-slot": "combobox-list", className: cn("no-scrollbar max-h-[min(--spacing(52.5),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1.5 data-empty:p-0", className), ...props }));
101
+ function ComboboxList({ className, long = false, ...props }) {
102
+ return (_jsx(ComboboxPrimitive.List, { "data-slot": "combobox-list", className: cn("no-scrollbar scroll-py-1 overflow-y-auto overscroll-contain p-1.5 data-empty:p-0", long
103
+ ? "max-h-[min(--spacing(115.5),calc(var(--available-height)---spacing(9)))]"
104
+ : "max-h-[min(--spacing(52.5),calc(var(--available-height)---spacing(9)))]", className), ...props }));
96
105
  }
97
106
  function ComboboxItem({ className, children, ...props }) {
98
107
  return (_jsxs(ComboboxPrimitive.Item, { "data-slot": "combobox-item", className: cn("relative flex min-h-touch-target w-full cursor-default items-center gap-3 rounded-sm px-2 py-2 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:text-muted-foreground [@media(hover:hover)_and_(pointer:fine)]:min-h-0 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [React.Children.map(children, (child) => React.isValidElement(child) ? (child) : (_jsx("span", { className: "min-w-0 truncate text-left", children: child }))), _jsx(ComboboxPrimitive.ItemIndicator, { render: _jsx("span", { className: "pointer-events-none ml-auto flex shrink-0 items-center" }), children: _jsx(CheckIcon, { className: "pointer-events-none size-3.5" }) })] }));
@@ -41,9 +41,11 @@ type DataTableFeatures = {
41
41
  * muted line under the name; `text` joins it as the column's value (its accessor's) instead of
42
42
  * its cell, for a cell that is a link or a control, since an entity row's line sits inside the
43
43
  * row's own link; `dropped` leaves it out, for a fact the record's page holds and the phone's
44
- * line can spare. A column in `primaryColumns` stays in the row and says none of them.
44
+ * line can spare; `name` stands beside an entity row's name, which ends in an ellipsis before
45
+ * it, for the exception no ellipsis may hide, such as a status, and joins the line in any other
46
+ * table. A column in `primaryColumns` stays in the row and says none of them.
45
47
  */
46
- compact?: "line" | "text" | "dropped";
48
+ compact?: "line" | "text" | "dropped" | "name";
47
49
  };
48
50
  };
49
51
  /** A column definition typed for this table's feature set. Every column has a heading, because a table is read across its columns. */
@@ -226,7 +228,7 @@ export declare function columnMenuLabel<TData extends RowData, TValue extends Ce
226
228
  * @instead “For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table)
227
229
  * “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table)
228
230
  * Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows="entities"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.
229
- * @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
231
+ * @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, or beside an entity row's name, which ends in an ellipsis before it, when it says `name`, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
230
232
  * “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table)
231
233
  * “After an async filter change, wrap the region in `aria-live="polite"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state)
232
234
  * Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced.
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/components/data-table.tsx"],"names":[],"mappings":"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"}
@@ -183,7 +183,7 @@ function DefaultToolbar({ actions }) {
183
183
  * @instead “For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table)
184
184
  * “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table)
185
185
  * Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows="entities"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.
186
- * @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
186
+ * @behaviour Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, or beside an entity row's name, which ends in an ellipsis before it, when it says `name`, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` ("Page 2 of 7") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends "Deployment retention is enabled. Learn more" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries.
187
187
  * “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table)
188
188
  * “After an async filter change, wrap the region in `aria-live="polite"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state)
189
189
  * Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced.
@@ -289,6 +289,7 @@ function RecordsTable({ kind, columns, data, getRowId, filterColumnId, filterPla
289
289
  ? String(cell.getValue() ?? "")
290
290
  : renderCell(cell),
291
291
  wraps: cell.column.columnDef.meta?.wraps === true,
292
+ besideName: entities && cell.column.columnDef.meta?.compact === "name",
292
293
  }));
293
294
  // An entity row keeps its record on one 72 px row on a narrow card: the facts that leave the
294
295
  // row join the line under the name, which `RecordIdentity` draws, instead of a row of their own.
@@ -34,6 +34,10 @@ export type IdentityMarkProps = {
34
34
  logo?: string;
35
35
  /** The company's standing, independent of which directory opened it. */
36
36
  edition?: "company" | "partner";
37
+ } | {
38
+ kind: "model";
39
+ /** The model maker's author slug, as `ModelMark` takes it: a key held at that maker. */
40
+ author: string;
37
41
  } | {
38
42
  kind: "person";
39
43
  name: string;
@@ -49,14 +53,15 @@ export type IdentityMarkProps = {
49
53
  });
50
54
  /**
51
55
  * What says which thing a record is, at a fixed size at the start of its row,
52
- * its object's head or its feed line: an Agent's orb, an app's logo, a
53
- * company's initials, a person's picture, or a record kind's icon on its tile.
56
+ * its object's head or its feed line: an Agent's orb, an app's logo, a model
57
+ * maker's mark, a company's initials, a person's picture, or a record kind's
58
+ * icon on its tile.
54
59
  *
55
60
  * @family Status
56
61
  * @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
57
- * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`.
58
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.
59
- * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, and no other kind takes letters.
62
+ * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
63
+ * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.
64
+ * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
60
65
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
61
66
  */
62
67
  export declare function IdentityMark(props: IdentityMarkProps): ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,0FAA0F;IAC1F,IAAI,EAAE,aAAa,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AA+EF;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAwEhE"}
1
+ {"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,0FAA0F;IAC1F,IAAI,EAAE,aAAa,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AA+EF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CA0EhE"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { AgentOrb, } from "./agent-orb.js";
3
3
  import { AppMark } from "./app-mark.js";
4
4
  import { Avatar, AvatarFallback, AvatarImage } from "./avatar.js";
5
+ import { ModelMark } from "./model-mark.js";
5
6
  import { CompanyLogo } from "../internal/company-logo.js";
6
7
  import { cn } from "../lib/utils.js";
7
8
  const MEASURES = {
@@ -46,14 +47,15 @@ function Tile({ kind, label, size, tone, children, }) {
46
47
  }
47
48
  /**
48
49
  * What says which thing a record is, at a fixed size at the start of its row,
49
- * its object's head or its feed line: an Agent's orb, an app's logo, a
50
- * company's initials, a person's picture, or a record kind's icon on its tile.
50
+ * its object's head or its feed line: an Agent's orb, an app's logo, a model
51
+ * maker's mark, a company's initials, a person's picture, or a record kind's
52
+ * icon on its tile.
51
53
  *
52
54
  * @family Status
53
55
  * @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
54
- * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`.
55
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.
56
- * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, and no other kind takes letters.
56
+ * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
57
+ * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.
58
+ * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
57
59
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
58
60
  */
59
61
  export function IdentityMark(props) {
@@ -66,6 +68,8 @@ export function IdentityMark(props) {
66
68
  }
67
69
  case "app":
68
70
  return props.platform ? (_jsx(AppMark, { app: props.app, label: props.label, platform: props.platform, size: size })) : (_jsx(AppMark, { app: props.app, label: props.label, logo: props.logo, size: size }));
71
+ case "model":
72
+ return _jsx(ModelMark, { author: props.author, label: props.label, size: size });
69
73
  case "person":
70
74
  return (_jsxs(Avatar, { "data-kind": "person", "data-slot": "identity-mark", style: { width: size, height: size }, ...avatarName(props.label), children: [props.image ? _jsx(AvatarImage, { alt: "", src: props.image }) : null, _jsx(AvatarFallback, { style: { fontSize: measures.initials }, children: identityInitials(props.name) })] }));
71
75
  case "company": {
@@ -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 (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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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, and a status that leaves the row stands beside the name, which ends in an ellipsis before it. `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.
@@ -1 +1 @@
1
- {"version":3,"file":"record-identity.d.ts","sourceRoot":"","sources":["../../src/components/record-identity.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIlF;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,KAAa,GACd,EAAE;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,8FAA8F;IAC9F,IAAI,EAAE,iBAAiB,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,+BAmCA;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"record-identity.d.ts","sourceRoot":"","sources":["../../src/components/record-identity.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIlF;;;;;;;;;;;;GAYG;AACH,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,KAAa,GACd,EAAE;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,8FAA8F;IAC9F,IAAI,EAAE,iBAAiB,CAAC;IACxB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,+BAsCA;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { IdentityMark } from "./identity-mark.js";
3
- import { TableCompactFacts } from "../internal/table-compact-line.js";
3
+ import { TableCompactFacts, TableCompactNameFacts } from "../internal/table-compact-line.js";
4
4
  import { cn } from "../lib/utils.js";
5
5
  /**
6
6
  * A record's identity in a row (DESIGN.md "Tables and missing values"): its
@@ -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 (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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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, and a status that leaves the row stands beside the name, which ends in an ellipsis before it. `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.
@@ -18,7 +18,7 @@ import { cn } from "../lib/utils.js";
18
18
  function RecordIdentity({ name, mark, hint, detail, wraps = false, }) {
19
19
  // oxlint-disable-next-line anti-slop/no-runtime-typeof -- name is a ReactNode; only a string can be a title attribute.
20
20
  const title = typeof name === "string" ? (hint ? `${name} · ${hint}` : name) : undefined;
21
- return (_jsxs("span", { className: "flex min-w-0 items-center gap-4", "data-slot": "record-identity", children: [_jsx(IdentityMark, { ...mark, size: 32 }), _jsxs("span", { className: "grid min-w-0 in-[table]:w-0 in-[table]:flex-1", children: [_jsx("span", { className: cn("min-w-0 font-semibold text-foreground", wraps ? "break-words whitespace-pre-wrap" : "truncate"), title: wraps ? undefined : title, children: name }), _jsxs("span", { className: cn(
21
+ return (_jsxs("span", { className: "flex min-w-0 items-center gap-4", "data-slot": "record-identity", children: [_jsx(IdentityMark, { ...mark, size: 32 }), _jsxs("span", { className: "grid min-w-0 in-[table]:w-0 in-[table]:flex-1", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: cn("min-w-0 font-semibold text-foreground", wraps ? "break-words whitespace-pre-wrap" : "truncate"), title: wraps ? undefined : title, children: name }), _jsx(TableCompactNameFacts, {})] }), _jsxs("span", { className: cn(
22
22
  // The line is the containing block of the facts' screen-reader labels, so what it cuts
23
23
  // stays cut instead of widening the table.
24
24
  "relative text-sm text-muted-foreground", wraps
@@ -189,7 +189,7 @@ export type RecordListWithout<TRecord extends RowData, Key extends PropertyKey>
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
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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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.
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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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 and the time leave the row for that one line, ending in an ellipsis, never a labelled list, and the status stands beside the name, which ends in an ellipsis before it, so the exception is never the part a phone's line cuts. `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)
@@ -180,7 +180,7 @@ function recordColumns(props) {
180
180
  header: status.label,
181
181
  accessorFn: status.of,
182
182
  size: status.size,
183
- meta: { optional: true },
183
+ meta: { optional: true, compact: "name" },
184
184
  cell: StatusCell,
185
185
  });
186
186
  }
@@ -250,7 +250,7 @@ function RecordRows(props) {
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
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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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.
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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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 and the time leave the row for that one line, ending in an ellipsis, never a labelled list, and the status stands beside the name, which ends in an ellipsis before it, so the exception is never the part a phone's line cuts. `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)
@@ -26,7 +26,10 @@ import { type FieldSize } from "../internal/input-box.js";
26
26
  * never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never
27
27
  * an option. `label` and `error` go on `SelectTrigger`, and a string `label` requires `id`; a
28
28
  * trigger with no name does not compile. "Group options past ~10 items with native `<optgroup>`;
29
- * Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: group the
29
+ * Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: `look="inline"`
30
+ * draws the trigger as a ghost `Button` of its size, for a toolbar such as a chat bar's reasoning
31
+ * level: no box and no field ring, the fill only when hovered or open, the Button's focus outline
32
+ * and its disabled dimming; the list is the same. Group the
30
33
  * options with `SelectGroup`. "Validate on blur and pass a string to `error`; messages name the
31
34
  * field and end in a period (`Select a framework.`)." (https://vercel.com/geist/select) "Don’t wrap
32
35
  * a labelled `<Select>` in a `Tooltip`; put the hint on a sibling icon button so the label stays
@@ -50,10 +53,13 @@ declare function SelectValue({ className, ...props }: SelectPrimitive.Value.Prop
50
53
  * `SelectTrigger`, such as `MultiSelectTrigger`, wears the same box.
51
54
  */
52
55
  declare const selectTriggerVariants: (props?: ({
56
+ look?: "inline" | "field" | null | undefined;
53
57
  size?: "default" | "sm" | "lg" | null | undefined;
54
58
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
55
59
  type SelectTriggerProps = Omit<SelectPrimitive.Trigger.Props, "prefix"> & {
56
60
  size?: FieldSize;
61
+ /** `inline` sits among a toolbar's ghost buttons, such as a chat bar's reasoning level, and is drawn as one. */
62
+ look?: "field" | "inline";
57
63
  /** A mark before the value, such as an icon. */
58
64
  prefix?: React.ReactNode;
59
65
  /** A mark at the end, in place of the chevron. */
@@ -63,7 +69,7 @@ type SelectTriggerProps = Omit<SelectPrimitive.Trigger.Props, "prefix"> & {
63
69
  /** The message under the box, in the product's words; it also marks the box invalid. */
64
70
  error?: string;
65
71
  } & FieldName;
66
- declare function SelectTrigger({ className, size, prefix, suffix, label, description, error, children, ...props }: SelectTriggerProps): React.JSX.Element;
72
+ declare function SelectTrigger({ className, size, look, prefix, suffix, label, description, error, children, ...props }: SelectTriggerProps): React.JSX.Element;
67
73
  declare function SelectContent({ className, children, side, sideOffset, align, alignOffset, alignItemWithTrigger, ...props }: SelectPrimitive.Popup.Props & Pick<SelectPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "alignItemWithTrigger">): React.JSX.Element;
68
74
  declare function SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel.Props): React.JSX.Element;
69
75
  declare function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Props): React.JSX.Element;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
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;AAMlE,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAG9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;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;;;8EAkB1B,CAAC;AAEF,KAAK,kBAAkB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG;IACxE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gHAAgH;IAChH,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,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,IAAc,EACd,MAAM,EACN,MAAM,EACN,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,qBA+CpB;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"}
@@ -4,6 +4,7 @@ import { Select as SelectPrimitive } from "@base-ui/react/select";
4
4
  import { cva } from "class-variance-authority";
5
5
  import { cn } from "../lib/utils.js";
6
6
  import { anchoredOverlayMotion } from "../lib/motion.js";
7
+ import { buttonVariants } from "./button.js";
7
8
  import { FieldFrame } from "../internal/field-frame.js";
8
9
  import { fieldDisabled, fieldOpen, fieldRing, fieldStates, } from "../internal/input-box.js";
9
10
  import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
@@ -31,7 +32,10 @@ import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
31
32
  * never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never
32
33
  * an option. `label` and `error` go on `SelectTrigger`, and a string `label` requires `id`; a
33
34
  * trigger with no name does not compile. "Group options past ~10 items with native `<optgroup>`;
34
- * Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: group the
35
+ * Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: `look="inline"`
36
+ * draws the trigger as a ghost `Button` of its size, for a toolbar such as a chat bar's reasoning
37
+ * level: no box and no field ring, the fill only when hovered or open, the Button's focus outline
38
+ * and its disabled dimming; the list is the same. Group the
35
39
  * options with `SelectGroup`. "Validate on blur and pass a string to `error`; messages name the
36
40
  * field and end in a period (`Select a framework.`)." (https://vercel.com/geist/select) "Don’t wrap
37
41
  * a labelled `<Select>` in a `Tooltip`; put the hint on a sibling icon button so the label stays
@@ -59,21 +63,25 @@ function SelectValue({ className, ...props }) {
59
63
  * `SelectTrigger`, such as `MultiSelectTrigger`, wears the same box.
60
64
  */
61
65
  const selectTriggerVariants = cva([
62
- "flex min-h-touch-target w-full items-center justify-between gap-1.5 bg-(--nc-field,var(--background)) py-0 pr-3 pl-control-padding-inline text-sm whitespace-nowrap select-none data-placeholder:text-placeholder [@media(hover:hover)_and_(pointer:fine)]:min-h-0 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
63
- fieldRing,
64
- fieldDisabled,
66
+ "flex min-h-touch-target w-full items-center justify-between gap-1.5 py-0 pr-3 pl-control-padding-inline text-sm whitespace-nowrap select-none data-placeholder:text-placeholder [@media(hover:hover)_and_(pointer:fine)]:min-h-0 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
65
67
  ], {
66
68
  variants: {
69
+ look: {
70
+ field: ["bg-(--nc-field,var(--background))", fieldRing, fieldDisabled],
71
+ inline: "",
72
+ },
67
73
  size: {
68
74
  sm: "h-nadicode-control-height-sm rounded-sm",
69
75
  default: "h-control-height rounded-sm",
70
76
  lg: "h-nadicode-control-height-lg rounded-md text-base",
71
77
  },
72
78
  },
73
- defaultVariants: { size: "default" },
79
+ defaultVariants: { look: "field", size: "default" },
74
80
  });
75
- function SelectTrigger({ className, size = "default", prefix, suffix, label, description, error, children, ...props }) {
76
- return (_jsx(FieldFrame, { label: label, description: description, error: error, size: size, control: props, children: (aria) => (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, "data-field-frame": "", className: cn(selectTriggerVariants({ size }), fieldStates, fieldOpen, className), ...props, ...aria, children: [prefix ? (_jsx("span", { "data-slot": "select-prefix", "aria-hidden": "true", className: "mr-1.5 flex shrink-0 items-center text-muted-foreground", children: prefix })) : null, children, suffix ? (_jsx("span", { "data-slot": "select-suffix", "aria-hidden": "true", className: "flex shrink-0 items-center text-muted-foreground", children: suffix })) : (_jsx(SelectPrimitive.Icon, { render: _jsx(ChevronDownIcon, { className: "pointer-events-none size-3.5 text-muted-foreground" }) }))] })) }));
81
+ function SelectTrigger({ className, size = "default", look = "field", prefix, suffix, label, description, error, children, ...props }) {
82
+ return (_jsx(FieldFrame, { label: label, description: description, error: error, size: size, control: props, children: (aria) => (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, "data-field-frame": look === "field" ? "" : undefined, className: cn(selectTriggerVariants({ look, size }), look === "field"
83
+ ? [fieldStates, fieldOpen]
84
+ : [buttonVariants({ variant: "ghost", size }), "w-fit min-w-0 justify-between"], className), ...props, ...aria, children: [prefix ? (_jsx("span", { "data-slot": "select-prefix", "aria-hidden": "true", className: "mr-1.5 flex shrink-0 items-center text-muted-foreground", children: prefix })) : null, children, suffix ? (_jsx("span", { "data-slot": "select-suffix", "aria-hidden": "true", className: "flex shrink-0 items-center text-muted-foreground", children: suffix })) : (_jsx(SelectPrimitive.Icon, { render: _jsx(ChevronDownIcon, { className: "pointer-events-none size-3.5 text-muted-foreground" }) }))] })) }));
77
85
  }
78
86
  function SelectContent({ className, children, side = "bottom", sideOffset = 8, align = "center", alignOffset = 0, alignItemWithTrigger = false, ...props }) {
79
87
  return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, alignItemWithTrigger: alignItemWithTrigger, className: "isolate z-50", children: _jsxs(SelectPrimitive.Popup, { "data-slot": "select-content", "data-align-trigger": alignItemWithTrigger, className: cn("pointer-events-auto", "relative isolate z-50 max-h-(--available-height) w-auto max-w-(--available-width) min-w-(--anchor-width) overflow-x-hidden overflow-y-auto rounded-lg border-0 bg-popover text-popover-foreground nc-elevation-floating data-[align-trigger=true]:transition-none", anchoredOverlayMotion, className), ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.List, { className: "p-1.5", children: children }), _jsx(SelectScrollDownButton, {})] }) }) }));
@@ -81,7 +81,7 @@ export type SavingSettingsSectionProps = SettingsSectionBase & SavingSection;
81
81
  * @family Compositions
82
82
  * @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).
83
83
  * @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.
84
- * @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: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. 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`.
84
+ * @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: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. 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, and when the title's longest word would not fit beside them they move under the title, so they never cover it. 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`.
85
85
  * @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".
86
86
  * @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.
87
87
  */
@@ -1 +1 @@
1
- {"version":3,"file":"settings-section.d.ts","sourceRoot":"","sources":["../../src/components/settings-section.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings-section.d.ts","sourceRoot":"","sources":["../../src/components/settings-section.tsx"],"names":[],"mappings":"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"}
@@ -14,15 +14,19 @@ const toneClassNames = {
14
14
  error: "border border-destructive *:data-[slot=card-footer]:border-destructive *:data-[slot=card-footer]:bg-destructive-soft *:data-[slot=card-footer]:*:data-[slot=settings-section-hint]:text-destructive-soft-foreground",
15
15
  warning: "border border-warning *:data-[slot=card-footer]:border-warning *:data-[slot=card-footer]:bg-warning-soft *:data-[slot=card-footer]:*:data-[slot=settings-section-hint]:text-warning-soft-foreground",
16
16
  };
17
- /** Below a 28 rem card the actions keep the title's row and the description takes the card's width under both. */
18
- const ACTIONS_ON_TITLE_ROW_WHEN_NARROW = "@max-md/settings-section:[&>[data-slot=card-action]]:row-span-1 @max-md/settings-section:[&>[data-slot=card-action]]:row-start-1 @max-md/settings-section:[&>[data-slot=card-description]]:col-span-2 @max-md/settings-section:[&>[data-slot=card-description]]:col-start-1";
17
+ /**
18
+ * Below a 28 rem card the actions keep the title's row while the title's longest word fits beside
19
+ * them, and move under the title when it does not, so they never cover it; the description takes
20
+ * the card's width under both.
21
+ */
22
+ const ACTIONS_ON_TITLE_ROW_WHEN_NARROW = "@max-md/settings-section:flex @max-md/settings-section:flex-wrap @max-md/settings-section:[&>[data-slot=card-title]]:grow @max-md/settings-section:[&>[data-slot=card-title]]:basis-[min-content] @max-md/settings-section:[&>[data-slot=card-action]]:order-1 @max-md/settings-section:[&>[data-slot=card-description]]:order-2 @max-md/settings-section:[&>[data-slot=card-description]]:basis-full";
19
23
  /**
20
24
  * A card of one setting that says what changing it does and ends in a footer.
21
25
  *
22
26
  * @family Compositions
23
27
  * @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).
24
28
  * @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.
25
- * @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: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. 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`.
29
+ * @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: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. 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, and when the title's longest word would not fit beside them they move under the title, so they never cover it. 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`.
26
30
  * @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".
27
31
  * @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.
28
32
  */
@@ -167,7 +167,7 @@ function isRingOrOutlineMechanic(utility) {
167
167
  * `better-tailwindcss/no-unknown-classes` reports it as one. That is what
168
168
  * retired the hand-written colour-name list this rule used to carry.
169
169
  */
170
- function isAppearanceUtility(utility) {
170
+ export function isAppearanceUtility(utility) {
171
171
  const base = withoutVariants(utility);
172
172
  return (
173
173
  /^appearance-/.test(base) ||
@@ -6,6 +6,8 @@ export type TableDetailFact = {
6
6
  value: React.ReactNode;
7
7
  /** The value is prose a reader needs whole, such as why a check failed: the line wraps instead of ending in an ellipsis. */
8
8
  wraps?: boolean;
9
+ /** The value stands beside the record's name instead, which ends in an ellipsis before it: a status. */
10
+ besideName?: boolean;
9
11
  };
10
12
  export declare function DetailFacts({ facts, leadingSeparator, }: {
11
13
  facts: readonly TableDetailFact[];
@@ -25,6 +27,8 @@ export declare function TableCompactLine({ children, ...value }: TableCompactLin
25
27
  }): React.JSX.Element;
26
28
  /** The compact facts of the row this stands in, after a middle dot; nothing outside such a row or on a card wide enough for the columns. */
27
29
  export declare function TableCompactFacts(): React.JSX.Element | null;
30
+ /** The compact facts that stand beside the name of the row this stands in, which no ellipsis cuts; nothing outside such a row or on a card wide enough for the columns. */
31
+ export declare function TableCompactNameFacts(): React.JSX.Element | null;
28
32
  /**
29
33
  * Whether the entity rows around it are laid out compact now, read from the layout the browser
30
34
  * drew: a row's cells move what does not fit beside the name under it instead.
@@ -1 +1 @@
1
- {"version":3,"file":"table-compact-line.d.ts","sourceRoot":"","sources":["../../src/internal/table-compact-line.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4HAA4H;IAC5H,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,gBAAwB,GACzB,EAAE;IACD,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,uBAQA;AAED,KAAK,qBAAqB,GAAG;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAI/F;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,qBAEvD;AAED,4IAA4I;AAC5I,wBAAgB,iBAAiB,6BAehC;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,qBAEA;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
1
+ {"version":3,"file":"table-compact-line.d.ts","sourceRoot":"","sources":["../../src/internal/table-compact-line.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4HAA4H;IAC5H,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wGAAwG;IACxG,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,gBAAwB,GACzB,EAAE;IACD,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,uBAQA;AAED,KAAK,qBAAqB,GAAG;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAI/F;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,qBAEvD;AAED,4IAA4I;AAC5I,wBAAgB,iBAAiB,6BAiBhC;AAED,2KAA2K;AAC3K,wBAAgB,qBAAqB,6BAkBpC;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,qBAEA;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
@@ -18,9 +18,22 @@ export function TableCompactLine({ children, ...value }) {
18
18
  /** The compact facts of the row this stands in, after a middle dot; nothing outside such a row or on a card wide enough for the columns. */
19
19
  export function TableCompactFacts() {
20
20
  const line = React.useContext(TableCompactLineContext);
21
- if (!line || line.facts.length === 0)
21
+ if (!line)
22
22
  return null;
23
- return (_jsx("span", { className: cn("[&_[data-slot=tag]]:contents [&>span>:is(div,p,.block,.grid,.flex)]:inline", tableCompactLayouts[line.layout].details), "data-slot": "table-detail-line", "data-wraps": line.facts.some((fact) => fact.wraps) || undefined, children: _jsx(DetailFacts, { facts: line.facts, leadingSeparator: true }) }));
23
+ const facts = line.facts.filter((fact) => !fact.besideName);
24
+ if (facts.length === 0)
25
+ return null;
26
+ return (_jsx("span", { className: cn("[&_[data-slot=tag]]:contents [&>span>:is(div,p,.block,.grid,.flex)]:inline", tableCompactLayouts[line.layout].details), "data-slot": "table-detail-line", "data-wraps": facts.some((fact) => fact.wraps) || undefined, children: _jsx(DetailFacts, { facts: facts, leadingSeparator: true }) }));
27
+ }
28
+ /** The compact facts that stand beside the name of the row this stands in, which no ellipsis cuts; nothing outside such a row or on a card wide enough for the columns. */
29
+ export function TableCompactNameFacts() {
30
+ const line = React.useContext(TableCompactLineContext);
31
+ if (!line)
32
+ return null;
33
+ const facts = line.facts.filter((fact) => fact.besideName);
34
+ if (facts.length === 0)
35
+ return null;
36
+ return (_jsx("span", { className: cn("flex shrink-0 items-center gap-2", tableCompactLayouts[line.layout].details), "data-slot": "table-name-facts", children: facts.map((fact) => (_jsxs("span", { className: "flex items-center", children: [_jsxs("span", { className: "sr-only", children: [fact.label, ": "] }), fact.value] }, fact.id))) }));
24
37
  }
25
38
  const TableLaidOutCompactContext = React.createContext(false);
26
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/navigation.tsx"],"names":[],"mappings":"AAoEA,iBAAS,qBAAqB,gCAoC7B;AAED,iBAAS,qBAAqB,gCAmB7B;AAED,iBAAS,uBAAuB,gCAiE/B;AAED,iBAAS,YAAY,gCAqCpB;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;CAmRI,CAAC"}
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/navigation.tsx"],"names":[],"mappings":"AAoEA,iBAAS,qBAAqB,gCAoC7B;AAED,iBAAS,qBAAqB,gCAmB7B;AAED,iBAAS,uBAAuB,gCAiE/B;AAED,iBAAS,YAAY,gCAqCpB;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;CAkRI,CAAC"}
@@ -86,7 +86,7 @@ function TabsSpecimen() {
86
86
  return (_jsxs("div", { className: "grid gap-8", children: [_jsxs(Tabs, { onValueChange: setPlain, value: plain, children: [_jsxs(TabsList, { "aria-label": "Rossi Ottica", children: [_jsx(TabsTrigger, { value: "overview", children: "Overview" }), _jsx(TabsTrigger, { value: "installations", children: "Installations" }), _jsx(TabsTrigger, { disabled: true, disabledReason: "Only owners see billing", value: "billing", children: "Billing" })] }), _jsx(TabsContent, { className: "pt-3 text-sm text-muted-foreground", value: "overview", children: "What the customer runs, at a glance." }), _jsx(TabsContent, { className: "pt-3 text-sm text-muted-foreground", value: "installations", children: "Every machine Nadia is installed on." })] }), _jsxs(Tabs, { onValueChange: setLined, value: lined, children: [_jsxs(TabsList, { "aria-label": "Rossi Ottica, with a rule", variant: "line", children: [_jsx(TabsTrigger, { value: "overview", children: "Overview" }), _jsx(TabsTrigger, { value: "installations", children: "Installations" }), _jsx(TabsTrigger, { disabled: true, disabledReason: "Only owners see billing", value: "billing", children: "Billing" })] }), _jsx(TabsContent, { className: "pt-3 text-sm text-muted-foreground", value: "overview", children: "What the customer runs, at a glance." }), _jsx(TabsContent, { className: "pt-3 text-sm text-muted-foreground", value: "installations", children: "Every machine Nadia is installed on." })] })] }));
87
87
  }
88
88
  export const NAVIGATION = {
89
- AgentListRow: () => (_jsxs("ul", { className: "grid max-w-xs gap-1", children: [_jsx("li", { children: _jsx(AgentListRow, { color: COBALTO, current: true, form: "orbit", name: "Invoices", state: "working", stateLine: "Drafting October's invoices" }) }), _jsx("li", { children: _jsx(AgentListRow, { color: VERDE, form: "lattice", name: "Orders", state: "waiting", stateLine: "Waiting for you", stateTone: "warning" }) })] })),
89
+ AgentListRow: () => (_jsxs("ul", { className: "grid max-w-xs gap-1", children: [_jsx("li", { children: _jsx(AgentListRow, { color: COBALTO, current: true, form: "orbit", name: "Invoices", state: "working", stateLine: "Drafting October's invoices" }) }), _jsx("li", { children: _jsx(AgentListRow, { color: VERDE, form: "lattice", name: "Orders", state: "waiting", stateLine: "Waiting for you" }) })] })),
90
90
  Breadcrumb: () => (_jsxs("div", { className: "grid gap-4", children: [_jsx(Breadcrumb, { "aria-label": "Path", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica" }) })] }) }), _jsx(Breadcrumb, { "aria-label": "Path with a closed ancestor", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { disabled: true, children: "Partners" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica" }) })] }) }), _jsx(Breadcrumb, { "aria-label": "Long path", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbEllipsis, { label: "More" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#installations", children: "Installations" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica, Milano" }) })] }) })] })),
91
91
  CommandDialog: CommandDialogSpecimen,
92
92
  Footer: () => (_jsx(Footer, { children: _jsxs(FooterInner, { children: [_jsx(FooterBrand, { "aria-label": "nadicode", href: "#top", children: _jsx(BrandWordmark, { alt: "" }) }), _jsx(FooterIdentity, { children: "Agents that do the work, for Italian companies." }), _jsxs(FooterNav, { "aria-label": "Company", children: [_jsx("a", { href: "#privacy", children: "Privacy" }), _jsx("a", { href: "#terms", children: "Terms" })] }), _jsx(FooterMeta, { children: "\u00A9 2026 nadicode" })] }) })),
@@ -186,7 +186,7 @@ export const USAGE = [
186
186
  summary: "Entity rows: objects a person opens or acts on, one line each on one resting card: the identity mark and name over what it is, a few facts, a status only for the exception, when it happened, at most two row commands, and the three dots last.",
187
187
  when: "“Use `<Entity>` for a row of descriptive content paired with one or two controls (member rows, integration rows, domain rows).” (https://vercel.com/geist/entity) 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`.",
188
188
  instead: "“For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity) “For a static key/value metadata block on a detail page, use `Description`.” (https://vercel.com/geist/entity) 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`.",
189
- 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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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. “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) Ours: `failed`, `noMatch` and `empty` are those variants, drawn inside the card. “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) Ours: one or two row commands (outline buttons of 32 px) stand before the three dots (36 px), the Dots Menu. “Render the Skeleton variant (`entity-with-skeleton`) during load instead of an empty row, and swap to real content once data resolves.” (https://vercel.com/geist/entity) Ours: three still skeleton rows hold the place, in a region that announces what replaces them; then the first that holds: the failed read, no match, the empty state, the rows.",
189
+ 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` and the mark are required; a record with nothing to say under its name leaves the line out and is the name alone, never a 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 and the time leave the row for that one line, ending in an ellipsis, never a labelled list, and the status stands beside the name, which ends in an ellipsis before it, so the exception is never the part a phone's line cuts. `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. “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) Ours: `failed`, `noMatch` and `empty` are those variants, drawn inside the card. “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) Ours: one or two row commands (outline buttons of 32 px) stand before the three dots (36 px), the Dots Menu. “Render the Skeleton variant (`entity-with-skeleton`) during load instead of an empty row, and swap to real content once data resolves.” (https://vercel.com/geist/entity) Ours: three still skeleton rows hold the place, in a region that announces what replaces them; then the first that holds: the failed read, no match, the empty state, the rows.",
190
190
  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) Ours: the name is the record\'s own and the labels around it are sentence case, not Title Case. “Keep right-column buttons Verb + Noun (`Remove Member`, `Resend Invite`). Bare verbs like `Remove` or `Confirm` lose context once the row scrolls offscreen.” (https://vercel.com/geist/entity) Ours: every string is the product\'s: `label` names the list, a time\'s `phrase` writes its sentence ("Updated {when}"), `missing` is what a screen reader hears for a record with no time, the menu\'s `label` reads "More for {record}". A row command names its result in sentence case ("Edit domain"). A status is the exception\'s word ("Needs attention"), never "Active" on every row.',
191
191
  access: '“Wrap the loading region in `aria-busy="true"` and announce completion with `aria-live="polite"` on the destination container, not the skeleton itself.” (https://vercel.com/geist/skeleton) Ours: the loading rows sit in one `SkeletonRegion` that is busy while they stand and announces what replaces them. A table named by `label`, its column headings read by assistive technology only. The row link carries `open.label`; the three dots carry the menu\'s `label`, and the menu\'s first line names the record. The loading rows are a status named by `loadingLabel`, inside the one live region that announces what replaces them. “For multi-select rows, the leading `Checkbox` carries `aria-label="Select {entity name}"` so the row is selectable without relying on the visual label.” (https://vercel.com/geist/entity) Ours: each box is named by `select.label`, which reads "Select {record}".',
192
192
  },
@@ -230,7 +230,7 @@ export const USAGE = [
230
230
  summary: "A card of one setting that says what changing it does and ends in a footer.",
231
231
  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).",
232
232
  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.",
233
- 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: a switch never applies on change; it is a row of the card, a draft until the footer\'s Save, as Vercel\'s settings cards are. 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`.',
233
+ 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: a switch never applies on change; it is a row of the card, a draft until the footer\'s Save, as Vercel\'s settings cards are. 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, and when the title\'s longest word would not fit beside them they move under the title, so they never cover it. 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`.',
234
234
  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".',
235
235
  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.",
236
236
  },
@@ -483,7 +483,7 @@ export const USAGE = [
483
483
  summary: "Type to find one value, or several, in a known set.",
484
484
  when: '"Filters large lists to selectable options based on the matching query." (https://vercel.com/geist/combobox) "Pick `<Combobox>` when users type to filter a known list of values (regions, frameworks, env-var names)." (https://vercel.com/geist/combobox) Ours: assign an Agent, choose a time zone, add several Agents at once with `multiple`.',
485
485
  instead: '"For short, fixed lists where typing adds nothing, switch to `Select`." (https://vercel.com/geist/combobox) "When more than one value can be chosen at once, use `MultiSelect`." (https://vercel.com/geist/combobox) "For free-form filter strings that don’t resolve to a single option, drop in `Input` with the `search` variant." (https://vercel.com/geist/combobox) Ours: several values chosen from a list you scan rather than type into is a `MultiSelect`; `Combobox` takes several with `multiple`. `Input` has no `search` variant, so free text is an `Input` and narrowing a collection is `CollectionFilters`.',
486
- behaviour: 'The parts are `ComboboxInput`, `ComboboxContent`, `ComboboxList`, `ComboboxItem`, `ComboboxGroup` with its `ComboboxLabel`, `ComboboxLoading`, and `ComboboxChips` with its `ComboboxChip` and `ComboboxChipsInput` for `multiple`; the line for no match is the `empty` of `ComboboxContent`. The box fills its container and is `Input`\'s: its three sizes (`size` on `ComboboxInput`), its ring, hover, focus halo and disabled, with the search mark at the start, a `placeholder` that names the scope, and the open-list or clear button flush at the end, in the muted grey until hovered (the open-list button is 30 px high and centred at the default size, full height at `sm` and `lg`). Colour sits in one place: an error turns the ring red, fills the halo and colours the typed text; the placeholder, marks and list stay neutral. `label` and `error` go on `ComboboxInput`, and a string `label` requires `id`; a box with no name does not compile. The list, a solid floating surface, opens 8 px under it at its width (a narrower `className` width centres under the box), in a 6 px inset, up to five and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap. A row is one line that ends in an ellipsis, with a 16 px mark 12 px before the name and a 14 px check at the chosen row\'s end, after the name. A row that cannot be chosen turns its text muted, never dimmed. Typing filters the list. "Options can opt out of the fixed row height with `ignoreDefaultHeight` to render multi-line content (e.g. a shared environment variable name plus its target). The list sizes each row to its content and stays scrollable." (https://vercel.com/geist/combobox) Ours: there is no `ignoreDefaultHeight`; a two-line row is an explicit column child. "Show a loading state for async results; don’t collapse the list while the request is in flight." (https://vercel.com/geist/combobox) Ours: while results load the list stays and `ComboboxLoading` says so, and the chosen value stays; `ComboboxContent` requires `empty`, the sentence for no match, or `null` while a search is still running. "Render a custom empty state of the form `No {items} match "{query}"` rather than a bare `No results`." (https://vercel.com/geist/combobox) "Keep arrow-key navigation through `<Combobox.Option>` items; don’t hijack Enter to submit the surrounding form while the list is open." (https://vercel.com/geist/combobox) "Set `clearable` to show a clear button when a value is selected." (https://vercel.com/geist/combobox) Ours: `showClear` with a `clearLabel` does it; clear empties the box and keeps focus there. With `multiple`, each choice is a chip with its own remove; Backspace in an empty box removes the last. "It is common to use Combobox inside a Modal. On mobile, the Modal automatically renders a Dialog instead." (https://vercel.com/geist/combobox) "Inside a `Modal`, Geist switches to a Dialog on mobile automatically; don’t layer a second portal." (https://vercel.com/geist/combobox) Ours: our overlay is `Dialog`, and `ComboboxContent` is the list\'s one portal.',
486
+ behaviour: 'The parts are `ComboboxInput`, `ComboboxContent`, `ComboboxList`, `ComboboxItem`, `ComboboxGroup` with its `ComboboxLabel`, `ComboboxLoading`, and `ComboboxChips` with its `ComboboxChip` and `ComboboxChipsInput` for `multiple`; the line for no match is the `empty` of `ComboboxContent`. The box fills its container and is `Input`\'s: its three sizes (`size` on `ComboboxInput`), its ring, hover, focus halo and disabled, with the search mark at the start, a `placeholder` that names the scope, and the open-list or clear button flush at the end, in the muted grey until hovered (the open-list button is 30 px high and centred at the default size, full height at `sm` and `lg`). Colour sits in one place: an error turns the ring red, fills the halo and colours the typed text; the placeholder, marks and list stay neutral. `label` and `error` go on `ComboboxInput`, and a string `label` requires `id`; a box with no name does not compile. The list, a solid floating surface, opens 8 px under it at its width (a narrower `className` width centres under the box), in a 6 px inset, up to five and a half rows tall (210 px) so a cut row shows there is more, with rows 36 px tall and no gap; a `long` list, one people scan by section, shows twelve and a half rows (462 px). A trigger that opens a list with its own search puts `ComboboxInput` first in `ComboboxContent`: there the box draws no ring or halo, spans the list on its surface, and a hairline divides it from the rows, wherever it sits in the content. A row is one line that ends in an ellipsis, with a 16 px mark 12 px before the name and a 14 px check at the chosen row\'s end, after the name. A row that cannot be chosen turns its text muted, never dimmed. Typing filters the list. "Options can opt out of the fixed row height with `ignoreDefaultHeight` to render multi-line content (e.g. a shared environment variable name plus its target). The list sizes each row to its content and stays scrollable." (https://vercel.com/geist/combobox) Ours: there is no `ignoreDefaultHeight`; a two-line row is an explicit column child. "Show a loading state for async results; don’t collapse the list while the request is in flight." (https://vercel.com/geist/combobox) Ours: while results load the list stays and `ComboboxLoading` says so, and the chosen value stays; `ComboboxContent` requires `empty`, the sentence for no match, or `null` while a search is still running. "Render a custom empty state of the form `No {items} match "{query}"` rather than a bare `No results`." (https://vercel.com/geist/combobox) "Keep arrow-key navigation through `<Combobox.Option>` items; don’t hijack Enter to submit the surrounding form while the list is open." (https://vercel.com/geist/combobox) "Set `clearable` to show a clear button when a value is selected." (https://vercel.com/geist/combobox) Ours: `showClear` with a `clearLabel` does it; clear empties the box and keeps focus there. With `multiple`, each choice is a chip with its own remove; Backspace in an empty box removes the last. "It is common to use Combobox inside a Modal. On mobile, the Modal automatically renders a Dialog instead." (https://vercel.com/geist/combobox) "Inside a `Modal`, Geist switches to a Dialog on mobile automatically; don’t layer a second portal." (https://vercel.com/geist/combobox) Ours: our overlay is `Dialog`, and `ComboboxContent` is the list\'s one portal.',
487
487
  words: '"Visible label is a short Title Case noun (`Region`, `Environment Variable Name`)." (https://vercel.com/geist/combobox) "Placeholder is the inline hint: `Search regions`, `DATABASE_URL`. Never bare `Search…` and never the label restated." (https://vercel.com/geist/combobox) "Option text is Title Case for short values and matches canonical branding (`Next.js`, not `NextJS`); same register across the list." (https://vercel.com/geist/combobox) "Validation names the field and constraint, sentence case with a period (`Select a region.`)." (https://vercel.com/geist/combobox) Ours: the label and the rows are sentence case. The hint is scoped: *Find an Agent*. No match quotes the query: *No Agent matches “Xy”.* A chip reads as the record\'s name.',
488
488
  access: '"`<Combobox>` has no `label` prop; pair a sibling `<Label htmlFor>` with the root `id`, or set `aria-label` on the root for icon-only triggers." (https://vercel.com/geist/combobox) "The root accepts `aria-label` only; there is no `aria-labelledby` prop, so the sibling-label path is the way to reference visible text." (https://vercel.com/geist/combobox) "Trap focus inside the popover when nested in a `Modal` so Tab cycles options instead of the page behind it." (https://vercel.com/geist/combobox) Ours: `ComboboxInput` takes a visible `label` tied to the box by `id`, or `aria-label` or `aria-labelledby`; combobox and listbox roles; the open-list and clear buttons are named by `triggerLabel` and `clearLabel`; each chip\'s remove is named: *Remove Acme Quotes*. An Agent\'s orb in a row is a decorative mark beside her name.',
489
489
  },
@@ -549,7 +549,7 @@ export const USAGE = [
549
549
  summary: "A short fixed list in our style, opened from a trigger that shows the choice.",
550
550
  when: '"Display a dropdown list of items." (https://vercel.com/geist/select) "Pick `<Select>` for short, fixed lists (under ~10 items) where typing adds nothing; switch to `Combobox` once filtering helps." (https://vercel.com/geist/select) Ours: four or more options, each short enough to need no sentence: how often a task runs. A list of two or three static options is a `RadioGroup`, as Geist says.',
551
551
  instead: '"Use `MultiSelect` when more than one value can be chosen at once; use `Switch` for a 2–3 option segmented choice." (https://vercel.com/geist/select) Ours: two or three options are radios or a segmented control. Inside a native form a long list is `NativeSelect`.',
552
- behaviour: 'The trigger is `Input`\'s box: its sizes, its ring, hover, focus halo and disabled, the label above it and the message under it, in the three sizes `sm`, default and `lg` that `Input` has. Colour sits in one place: an error turns the ring red and fills the halo, and colours the message; the fill, the value, the chevron and the label stay neutral. It shows the chosen value, after an optional `prefix` mark, with the chevron at the end in the muted grey (a `suffix` mark takes the chevron\'s place), and fills its container; it keeps 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 trigger (`alignItemWithTrigger` is off), in a 6 px inset, with a 14 px check at the chosen row\'s end, rows 36 px tall and no gap between them; a row that cannot be chosen turns its text muted, never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never an option. `label` and `error` go on `SelectTrigger`, and a string `label` requires `id`; a trigger with no name does not compile. "Group options past ~10 items with native `<optgroup>`; Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: group the options with `SelectGroup`. "Validate on blur and pass a string to `error`; messages name the field and end in a period (`Select a framework.`)." (https://vercel.com/geist/select) "Don’t wrap a labelled `<Select>` in a `Tooltip`; put the hint on a sibling icon button so the label stays announced." (https://vercel.com/geist/select) Other form rules are `Field`\'s.',
552
+ behaviour: 'The trigger is `Input`\'s box: its sizes, its ring, hover, focus halo and disabled, the label above it and the message under it, in the three sizes `sm`, default and `lg` that `Input` has. Colour sits in one place: an error turns the ring red and fills the halo, and colours the message; the fill, the value, the chevron and the label stay neutral. It shows the chosen value, after an optional `prefix` mark, with the chevron at the end in the muted grey (a `suffix` mark takes the chevron\'s place), and fills its container; it keeps 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 trigger (`alignItemWithTrigger` is off), in a 6 px inset, with a 14 px check at the chosen row\'s end, rows 36 px tall and no gap between them; a row that cannot be chosen turns its text muted, never dimmed. Arrows, typing, Enter, Escape. A placeholder reads in the muted grey and is never an option. `label` and `error` go on `SelectTrigger`, and a string `label` requires `id`; a trigger with no name does not compile. "Group options past ~10 items with native `<optgroup>`; Geist `<Select>` has no `.Group` static." (https://vercel.com/geist/select) Ours: `look="inline"` draws the trigger as a ghost `Button` of its size, for a toolbar such as a chat bar\'s reasoning level: no box and no field ring, the fill only when hovered or open, the Button\'s focus outline and its disabled dimming; the list is the same. Group the options with `SelectGroup`. "Validate on blur and pass a string to `error`; messages name the field and end in a period (`Select a framework.`)." (https://vercel.com/geist/select) "Don’t wrap a labelled `<Select>` in a `Tooltip`; put the hint on a sibling icon button so the label stays announced." (https://vercel.com/geist/select) Other form rules are `Field`\'s.',
553
553
  words: '"Options are Title Case when short and match canonical branding (`Next.js`, not `NextJS`); keep the same register across the list." (https://vercel.com/geist/select) "Label is a short Title Case noun (`Framework`, `Region`); accept the prop directly on `<Select>`." (https://vercel.com/geist/select) "Placeholder is action-oriented (`Select a framework`), never `Choose one…`, `Pick`, or the label restated." (https://vercel.com/geist/select) Ours: options are parallel phrases in sentence case (*Every hour*, *Every weekday*), the label is a short noun in sentence case, and the trigger never says *Select…* or *Choose one*.',
554
554
  access: "A visible label tied to the trigger by `id`, or `aria-label` or `aria-labelledby`. Listbox and option roles from Base UI; focus returns to the trigger on close. The prefix and suffix are decorative and not part of the trigger's name.",
555
555
  },
@@ -711,11 +711,11 @@ export const USAGE = [
711
711
  name: "IdentityMark",
712
712
  module: "identity-mark",
713
713
  family: "Status",
714
- summary: "What says which thing a record is, at a fixed size at the start of its row, its object's head or its feed line: an Agent's orb, an app's logo, a company's initials, a person's picture, or a record kind's icon on its tile.",
714
+ summary: "What says which thing a record is, at a fixed size at the start of its row, its object's head or its feed line: an Agent's orb, an app's logo, a model maker's mark, a company's initials, a person's picture, or a record kind's icon on its tile.",
715
715
  when: "The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.",
716
- instead: "An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`.",
717
- behaviour: "Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.",
718
- words: "None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, and no other kind takes letters.",
716
+ instead: "An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.",
717
+ behaviour: "Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in a neutral tile in its original colours and proportions, as Vercel shows a project's favicon; its two initials on a compact arch, cobalto for a company and arancio for an approved Partner, until a logo is found or when the stored logo does not load. The edition follows the company's standing, never the directory it was opened from; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A company arch has a semicircular top and `{rounded.sm}` bottom corners; a record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; an app's tile takes `{rounded.md}` at every size.",
718
+ words: "None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.",
719
719
  access: "Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.",
720
720
  },
721
721
  {
@@ -780,7 +780,7 @@ export const USAGE = [
780
780
  summary: 'A record\'s identity in a row (DESIGN.md "Tables and missing values"): its mark at 32, its name, and under it one muted `detail` line saying what the record is or where it comes from, so the row reads without a column heading.',
781
781
  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.",
782
782
  instead: "An Agent in a gallery is `AgentListRow`; a model is `ModelIdentity`. A descriptive item with prose and actions is `Item`.",
783
- 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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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.",
783
+ 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` is required; a record with nothing to say under its name leaves `detail` out and is the name alone, never a dash, which is a table cell's missing value and not a record's. 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, and a status that leaves the row stands beside the name, which ends in an ellipsis before it. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.",
784
784
  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) 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".',
785
785
  access: "The name is the row link's text; the mark is decorative; the title carries the full name.",
786
786
  },
@@ -813,9 +813,9 @@ export const USAGE = [
813
813
  summary: "One Agent in a list of them: the orb, the name, and the line that says what the Agent is doing now or what it is for.",
814
814
  when: "Nadia's Agents in her window's sidebar, and a website scene that shows a list of Agents.",
815
815
  instead: "An Agent as a record among others in a page's list is a RecordList row with an agent IdentityMark; an Agent's own page heads with ObjectPage.",
816
- behaviour: "It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. A state tone draws the state line as a small StatusBadge; without a tone it stays plain text. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.",
817
- words: 'The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). The tone never says more than the line does. Nadia\'s list says "Working", "Idle" or "Needs you"; the badge marks a state that needs the person ("Needs you", a failed set-up), and the orb shows working by itself.',
818
- access: "The orb is decorative; the name and the state line are the row's text, read by its control. StatusBadge owns its decorative shape, so the line carries its meaning.",
816
+ behaviour: "It is the row's presentation alone: the consumer owns the control around it (Nadia's button that opens the Agent, a scene's list item that opens nothing). The current row's name is set in 500. The orb carries the Agent's state, working, waiting on the person or blocked, so the state line is plain muted text and never a badge. Narrow, the orb stands alone and the words stay for a screen reader; the consumer names it with its state line in a tooltip, as Nadia's list does. Only the orb moves in the list. The name is 14 px and the state line 12 px at every size. The drawn orb leaves about 10 px of its 64 px box empty, so at 64 px that empty edge overlaps the row's padding (6 px above and below, 4 px at the start) and the words stand 4 px from the box: the row hugs the visible orb and the name sits beside it, as beside a solid picture. In Nadia's list her orb is 64 px in her real state, and 40 px in the narrow column from 640 to 899 px.",
817
+ words: 'The name, then one state line: what she is doing now ("Answering on Telegram", "Working") or what she is for ("Sorts requests"). Nadia\'s list says "Working", "Idle" or "Needs you".',
818
+ access: "The orb is decorative; the name and the state line are the row's text, read by its control.",
819
819
  },
820
820
  {
821
821
  name: "Breadcrumb",
@@ -1022,7 +1022,7 @@ export const USAGE = [
1022
1022
  summary: "Records compared across columns: the same facts for every record, read down a column and across a row, inside their `TableCard`.",
1023
1023
  when: "“Use `<Table>` for tabular data where rows share the same shape and at least one column is sortable or comparable across rows.” (https://vercel.com/geist/table) Ours: the person compares: usage per Agent, statements, invoices, customers with their partner and count. The columns are fixed, each has a heading, and at least one is a figure or can be sorted. There are three kinds of list. Objects a person opens (a project, a deployment, a member, an integration) are entity rows: a `RecordList`. Values edited in place (a domain, an environment variable) are entity rows that expand into their form: a `RecordList`'s `editor`. Records compared across columns are this table.",
1024
1024
  instead: "“For a row of descriptive content paired with a single action (membership row, integration row), use `Entity` instead.” (https://vercel.com/geist/table) “For a key/value metadata block on a detail page, use `Description`, not a two-column table.” (https://vercel.com/geist/table) Ours: Geist's `Entity` is a `RecordList` row. A registry of entities whose columns `RecordList` cannot hold, more than three facts beside a filter bar the product owns, as Vercel's Deployments list, is this table with `rows=\"entities\"`, which draws the same rows: headings for assistive technology only, 72 px rows, a `RecordIdentity` in the identity column. Its `Description` is `ObjectFacts`. A list on a page of its own is a `CollectionPage`. A descriptive list is `ItemGroup`.",
1025
- behaviour: "Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` (\"Page 2 of 7\") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends \"Deployment retention is enabled. Learn more\" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries. “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table) “After an async filter change, wrap the region in `aria-live=\"polite\"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state) Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced. “Sortable column headers are buttons. The visible label stays Title Case; the sort-direction arrow is decorative and the button announces the next sort state to assistive tech.” (https://vercel.com/geist/table) Ours: the order has one owner, the app's `sorting`, which the URL holds, so no heading is a button and every page of a paged list follows one order. “Apply `tabular-nums` (or Geist Mono) to numeric columns so digits align across rows for comparison.” (https://vercel.com/geist/table) Ours: a numeric column trails in tabular figures.",
1025
+ behaviour: "Every column has a `header`; a column without one does not compile. The headings are always visible, medium weight in the cells' body grey, 48 px high, with 12 px of room under the labels and then the rule, so the first row starts at the rule like every other; rows are 40 px. Each column is as wide as its definition's `size`, in pixels, and the columns without one share the rest, so a table gives a size to every column but the one that takes the spare width; a value too long for its column ends in an ellipsis, whole in its title (a record's name carries its own), unless the column `wraps`; a column marked `identifier` holds ids or paths and is cut in the middle instead. The last column trails unless it `wraps` or is `centered`; a `centered` column's heading and values sit in the middle of it. Records are divided by a 1 px rule, none after the last. The first and last columns stand in from the card's edges by the card's spacing, so the first lines up with the title. Records of several kinds stand in one table under `group` headings (Vercel's Usage page: *Delivery network*, *Functions*): a heading row that spans the columns, in ink, medium text, 36 px high with the same rule under it, one per group in the order the groups first appear, never a second table; a heading is the group's name and carries no figure of its own. A row that opens a record takes `accent` on hover, and any row on focus within and while its menu is open; a row that opens nothing never reacts to hover. A selected row takes `muted`; headers and footers never highlight and carry no fill. A row never scrolls sideways: on a card narrower than its columns (the sized ones and 160 px for each without a size) the row keeps its name and its `primaryColumns`, and every other column leaves it, its value joining the one muted line under the name, joined by a middle dot and ending in an ellipsis (a `Tag` reads as its text there, and a `wraps` column's prose wraps the line whole), or `dropped` when its `compact` says so, or beside an entity row's name, which ends in an ellipsis before it, when it says `name`, as Vercel's lists read on a phone: no labels, no second line; an `optional` column's empty value is left out of the line. A table whose every column is in `primaryColumns`, a settings matrix, lays out by its content there instead, so the name wraps beside the columns. A document's table, such as a legal page's, is read whole instead: its columns take the `wraps` option, so their words wrap and the row grows, and it keeps its header row; in the compact layout every cell but the identity wraps between words. A bounded page's paging stands in the card's footer strip at its trailing edge, opposite `footer`, which stands at the leading edge: its `status` (\"Page 2 of 7\") before Previous and Next, which are the product's router links (`previousLink`, `nextLink`) when each page is its own address, and buttons otherwise; the one that leads nowhere stays, disabled. A note about the whole table is `footerNote`, in a strip of its own under that one: one muted line, an optional *Learn more* after it at the left and one secondary action at the right (Vercel's deployments list ends \"Deployment retention is enabled. Learn more\" with *View recently deleted*); it is the one place a table says a sentence. Colour is neutral: headings and cells in the body grey, no hue, except a status badge or a tone the cell itself carries. “When the underlying list is empty (filter cleared, never created), render `Empty State` outside the table rather than an empty `<Table.Body>`.” (https://vercel.com/geist/table) “After an async filter change, wrap the region in `aria-live=\"polite\"` so screen readers announce the new state.” (https://vercel.com/geist/empty-state) Ours: empty sits outside the body, in a polite live region that stays in place so a filter that empties the table is announced. “Sortable column headers are buttons. The visible label stays Title Case; the sort-direction arrow is decorative and the button announces the next sort state to assistive tech.” (https://vercel.com/geist/table) Ours: the order has one owner, the app's `sorting`, which the URL holds, so no heading is a button and every page of a paged list follows one order. “Apply `tabular-nums` (or Geist Mono) to numeric columns so digits align across rows for comparison.” (https://vercel.com/geist/table) Ours: a numeric column trails in tabular figures.",
1026
1026
  words: '“Column headers (`<Table.Head>`) are Title Case nouns or noun phrases: `Last Used`, `Requests (7d)`, `Created`, `Status`. Never sentences.” (https://vercel.com/geist/table) “Render `—` in cells where a value is unknown or not applicable. Don’t substitute `N/A`, `null`, or an empty string.” (https://vercel.com/geist/table) “Use the canonical short relative-time form in cells (`2m ago`, `5h ago`); switch to `Mar 14, 2026` past 7 days. See `Relative Time Card`.” (https://vercel.com/geist/table) “Pagination labels are `Previous` and `Next`. Page-count copy reads `Page 2 of 7` or `21–40 of 142` with an en-dash inside the range.” (https://vercel.com/geist/table) Ours: headings are sentence case nouns with their unit, "Cost (€)", "Tokens", where Geist writes Title Case. The words of a time and of Previous and Next are the product\'s catalogue, in both languages. The footer is a count or the paging; totals and paging each stand in a footer zone of their own, the paging at the trailing edge; the summary row is a labelled total. Italian headings run a third longer and never wrap.',
1027
1027
  access: 'A native table named by `tableLabel`, which is required; `th scope="col"`; the record\'s name is the row\'s one link. A sorted column\'s heading carries `aria-sort`. Ours: a missing value is a hidden "—" with screen-reader text, never blank.',
1028
1028
  },
@@ -94,6 +94,43 @@
94
94
  box-shadow: var(--nc-elevation-modal);
95
95
  }
96
96
 
97
+ /*
98
+ * Small state changes share one cadence instead of component-local defaults
99
+ * (design-system DESIGN.md "Motion"). Declared as utilities, beside the
100
+ * elevation rungs, so a host that takes this file and not the design system's
101
+ * whole stylesheet still runs them, and variant prefixes can gate them.
102
+ */
103
+ @utility nc-transition-paint {
104
+ transition-property: background-color, border-color, color, opacity;
105
+ transition-duration: var(--nc-duration-confirm);
106
+ transition-timing-function: var(--nc-ease-out-strong);
107
+ }
108
+
109
+ @utility nc-transition-opacity {
110
+ transition-property: opacity;
111
+ transition-duration: var(--nc-duration-confirm);
112
+ transition-timing-function: var(--nc-ease-out-strong);
113
+ }
114
+
115
+ @utility nc-transition-transform {
116
+ transition-property: transform, translate, scale;
117
+ transition-duration: var(--nc-duration-confirm);
118
+ transition-timing-function: var(--nc-ease-out-strong);
119
+
120
+ @media (prefers-reduced-motion: reduce) {
121
+ transition: none;
122
+ }
123
+ }
124
+
125
+ /* A list that scrolls under its own fade or edge, such as Command's and Combobox's, draws no scrollbar. */
126
+ @utility no-scrollbar {
127
+ scrollbar-width: none;
128
+
129
+ &::-webkit-scrollbar {
130
+ display: none;
131
+ }
132
+ }
133
+
97
134
  /*
98
135
  * The proxy focus outline: the one restatement of the canonical treatment
99
136
  * above, for an element that carries the indicator on another element's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/ui",
3
- "version": "12.1.129",
3
+ "version": "12.1.131",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -83,7 +83,7 @@
83
83
  "@base-ui/react": "^1.9.0",
84
84
  "@iconify-icons/logos": "^2.0.3",
85
85
  "@iconify/react": "^6.0.2",
86
- "@nadicodeai/design-system": "12.1.129",
86
+ "@nadicodeai/design-system": "12.1.131",
87
87
  "@tanstack/react-table": "^9.3.1",
88
88
  "@vgpu/wgsl": "0.6.0",
89
89
  "class-variance-authority": "^0.7.1",