@nadicodeai/ui 12.1.125 → 12.1.127

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 (40) hide show
  1. package/dist/components/account-menu.d.ts +5 -4
  2. package/dist/components/account-menu.d.ts.map +1 -1
  3. package/dist/components/account-menu.js +4 -4
  4. package/dist/components/action-menu.d.ts +1 -1
  5. package/dist/components/action-menu.js +3 -3
  6. package/dist/components/agent-list-row.d.ts +2 -2
  7. package/dist/components/agent-list-row.d.ts.map +1 -1
  8. package/dist/components/agent-list-row.js +2 -2
  9. package/dist/components/page-header.d.ts +4 -4
  10. package/dist/components/page-header.js +4 -4
  11. package/dist/components/reading-column.d.ts +5 -4
  12. package/dist/components/reading-column.d.ts.map +1 -1
  13. package/dist/components/reading-column.js +5 -4
  14. package/dist/components/record-identity.d.ts +3 -2
  15. package/dist/components/record-identity.d.ts.map +1 -1
  16. package/dist/components/record-identity.js +1 -1
  17. package/dist/components/record-list.d.ts +4 -4
  18. package/dist/components/record-list.d.ts.map +1 -1
  19. package/dist/components/record-list.js +1 -1
  20. package/dist/components/settings-page.d.ts +5 -8
  21. package/dist/components/settings-page.d.ts.map +1 -1
  22. package/dist/components/settings-page.js +6 -7
  23. package/dist/components/settings-section.d.ts +6 -24
  24. package/dist/components/settings-section.d.ts.map +1 -1
  25. package/dist/components/settings-section.js +5 -5
  26. package/dist/components/switch.d.ts +4 -5
  27. package/dist/components/switch.d.ts.map +1 -1
  28. package/dist/components/switch.js +4 -5
  29. package/dist/components/theme-mode-switcher.d.ts +1 -1
  30. package/dist/components/theme-mode-switcher.js +1 -1
  31. package/dist/eslint/index.js +2 -0
  32. package/dist/eslint/rules/no-stock-error-words.js +1 -1
  33. package/dist/eslint/rules/test-files-from-one-definition.js +67 -0
  34. package/dist/internal/record-menu-items.d.ts.map +1 -1
  35. package/dist/internal/record-menu-items.js +1 -1
  36. package/dist/showcase/specimens/compositions.js +1 -1
  37. package/dist/showcase/usage.generated.d.ts.map +1 -1
  38. package/dist/showcase/usage.generated.js +17 -17
  39. package/dist/standalone/index.js +1 -1
  40. package/package.json +2 -2
@@ -79,9 +79,10 @@ export type AccountMenuProps = {
79
79
  theme: ComponentProps<typeof ThemeModeMenu>;
80
80
  language?: MenuChoiceRowProps<string>;
81
81
  choices?: readonly AccountMenuChoice[];
82
+ /** The product's commands that stand first, above Theme: Nadia's Usage. */
83
+ leadingCommands?: readonly AccountMenuCommand[];
84
+ /** The product's commands after its choices, above Sign out. */
82
85
  commands?: readonly AccountMenuCommand[];
83
- /** Where the product's commands stand: first, above Theme, or after its choices. */
84
- commandsAt?: "end" | "start";
85
86
  signOut: AccountMenuSignOut;
86
87
  /**
87
88
  * The trigger shows the picture alone, for a navigation rail drawn too narrow
@@ -100,9 +101,9 @@ export type AccountMenuProps = {
100
101
  * @family Menus
101
102
  * @when The account at the sidebar's foot in the Portal, Nadia and Alveare: the gear to the account's settings, Theme, Language, a product's own settings, its commands, and Sign out.
102
103
  * @instead A record's or a page's commands are an ActionMenu; a setting with more than a few options or one that needs a Save belongs on a SettingsPage.
103
- * @behaviour The menu opens 6 px above its trigger, 288 px wide, as Vercel's does: a header of the name and every line under it with the gear at its end and no picture, one divider, then 36 px rows, each its label leading and its icon or control trailing in muted ink: Theme and Language as small round pills, the product's choices as submenus, its commands with any reading before their icon, and Sign out last in the body colour, since signing out destroys nothing. Ruled by the owner on 16 October 2026. Theme and Language apply at once and keep the menu open. While signing out, Sign out says its pending word, the menu stays open and the trigger is locked; a failure shows under it. A Sign out that `confirms` closes the menu instead, for the product's own confirmation.
104
+ * @behaviour The menu opens 6 px above its trigger, 288 px wide, as Vercel's does: a header of the name and every line under it with the gear at its end and no picture, one divider, then 36 px rows, each its label leading and its icon or control trailing in muted ink: the product's leading commands first, Theme and Language as small round pills, the product's choices as submenus, its other commands, each command with any reading before its icon, and Sign out last in the body colour, since signing out destroys nothing. Ruled by the owner on 16 October 2026; on 19 October 2026 Nadia, a desktop app, also gets a Settings row after Language. Theme and Language apply at once and keep the menu open. While signing out, Sign out says its pending word, the menu stays open and the trigger is locked; a failure shows under it. A Sign out that `confirms` closes the menu instead, for the product's own confirmation.
104
105
  * @words The menu's name ("Account"), the person's name and lines, then each row's noun or verb from the product's catalogue: "Theme", "Language", "Usage", "Sign out" and "Signing out".
105
106
  * @access The trigger and the menu are named "{label}: {name}"; the gear carries its label; the pending sign-out is aria-busy and announced through a status; a failure is an alert.
106
107
  */
107
- export declare function AccountMenu({ align, choices, commands, commandsAt, identity, label, language, onOpenChange, pictureOnly, settings, side, signOut, theme, }: AccountMenuProps): import("react").JSX.Element;
108
+ export declare function AccountMenu({ align, choices, commands, identity, label, language, leadingCommands, onOpenChange, pictureOnly, settings, side, signOut, theme, }: AccountMenuProps): import("react").JSX.Element;
108
109
  //# sourceMappingURL=account-menu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../src/components/account-menu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../src/components/account-menu.tsx"],"names":[],"mappings":"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"}
@@ -25,14 +25,14 @@ export function AccountMenuIdentity({ className, identity, pictureOnly = false,
25
25
  * @family Menus
26
26
  * @when The account at the sidebar's foot in the Portal, Nadia and Alveare: the gear to the account's settings, Theme, Language, a product's own settings, its commands, and Sign out.
27
27
  * @instead A record's or a page's commands are an ActionMenu; a setting with more than a few options or one that needs a Save belongs on a SettingsPage.
28
- * @behaviour The menu opens 6 px above its trigger, 288 px wide, as Vercel's does: a header of the name and every line under it with the gear at its end and no picture, one divider, then 36 px rows, each its label leading and its icon or control trailing in muted ink: Theme and Language as small round pills, the product's choices as submenus, its commands with any reading before their icon, and Sign out last in the body colour, since signing out destroys nothing. Ruled by the owner on 16 October 2026. Theme and Language apply at once and keep the menu open. While signing out, Sign out says its pending word, the menu stays open and the trigger is locked; a failure shows under it. A Sign out that `confirms` closes the menu instead, for the product's own confirmation.
28
+ * @behaviour The menu opens 6 px above its trigger, 288 px wide, as Vercel's does: a header of the name and every line under it with the gear at its end and no picture, one divider, then 36 px rows, each its label leading and its icon or control trailing in muted ink: the product's leading commands first, Theme and Language as small round pills, the product's choices as submenus, its other commands, each command with any reading before its icon, and Sign out last in the body colour, since signing out destroys nothing. Ruled by the owner on 16 October 2026; on 19 October 2026 Nadia, a desktop app, also gets a Settings row after Language. Theme and Language apply at once and keep the menu open. While signing out, Sign out says its pending word, the menu stays open and the trigger is locked; a failure shows under it. A Sign out that `confirms` closes the menu instead, for the product's own confirmation.
29
29
  * @words The menu's name ("Account"), the person's name and lines, then each row's noun or verb from the product's catalogue: "Theme", "Language", "Usage", "Sign out" and "Signing out".
30
30
  * @access The trigger and the menu are named "{label}: {name}"; the gear carries its label; the pending sign-out is aria-busy and announced through a status; a failure is an alert.
31
31
  */
32
- export function AccountMenu({ align = "start", choices = [], commands = [], commandsAt = "end", identity, label, language, onOpenChange, pictureOnly = false, settings, side = "top", signOut, theme, }) {
32
+ export function AccountMenu({ align = "start", choices = [], commands = [], identity, label, language, leadingCommands = [], onOpenChange, pictureOnly = false, settings, side = "top", signOut, theme, }) {
33
33
  const name = `${label}: ${identity.name}`;
34
- const commandRows = commands.map(({ value, ...command }) => (_jsx(AccountMenuRow, { "aria-label": command.accessibleName, disabled: command.locked === true || command.disabledReason !== undefined, icon: command.icon, reason: command.locked ? command.reason : command.disabledReason, value: value, ...menuItemAction(command), children: command.label }, command.label)));
35
- return (_jsxs(DropdownMenu, { onOpenChange: onOpenChange, children: [_jsx(DropdownMenuTrigger, { "aria-label": name, className: cn("group/account flex min-h-9 min-w-0 items-center rounded-full outline-none focus-visible:nc-focus-outline focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50", pictureOnly ? "justify-center" : "w-full pr-2 pl-2.5"), disabled: signOut.pending, children: _jsx(AccountMenuIdentity, { identity: identity, pictureOnly: pictureOnly }) }), _jsxs(DropdownMenuContent, { align: align, "aria-label": name, className: "w-72 max-w-[calc(100vw-2rem)] p-1.5", density: "comfortable", side: side, sideOffset: 6, children: [_jsxs(DropdownMenuGroup, { className: "flex min-w-0 items-center gap-2 py-1.5 pl-2", "data-slot": "account-menu-header", children: [_jsxs("span", { className: "grid min-w-0 flex-1 gap-0.5 text-left", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: identity.name }), identity.notice ? _jsx("span", { className: "text-xs", children: identity.notice }) : null, identity.lines?.map((line, index) => (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: line }, index)))] }), settings ? (_jsx(DropdownMenuItem, { "aria-label": settings.label, className: "text-muted-foreground", iconOnly: true, ...menuItemAction(settings), children: _jsx(Settings, { "aria-hidden": "true" }) })) : null] }), _jsx(DropdownMenuSeparator, { className: "-mx-1.5 my-1.5" }), _jsxs(DropdownMenuGroup, { children: [commandsAt === "start" ? commandRows : null, _jsx(ThemeModeMenu, { ...theme }), language ? _jsx(MenuChoiceRow, { ...language }) : null, choices.map((choice) => (_jsx(AccountMenuChoiceRow, { choice: choice }, choice.label))), commandsAt === "end" ? commandRows : null, _jsx(AccountMenuRow, { "aria-busy": signOut.pending || undefined, closeOnClick: signOut.confirms === true, disabled: signOut.pending, icon: _jsx(LogOut, {}), onClick: () => {
34
+ const commandRows = (rows) => rows.map(({ value, ...command }) => (_jsx(AccountMenuRow, { "aria-label": command.accessibleName, disabled: command.locked === true || command.disabledReason !== undefined, icon: command.icon, reason: command.locked ? command.reason : command.disabledReason, value: value, ...menuItemAction(command), children: command.label }, command.label)));
35
+ return (_jsxs(DropdownMenu, { onOpenChange: onOpenChange, children: [_jsx(DropdownMenuTrigger, { "aria-label": name, className: cn("group/account flex min-h-9 min-w-0 items-center rounded-full outline-none focus-visible:nc-focus-outline focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50", pictureOnly ? "justify-center" : "w-full pr-2 pl-2.5"), disabled: signOut.pending, children: _jsx(AccountMenuIdentity, { identity: identity, pictureOnly: pictureOnly }) }), _jsxs(DropdownMenuContent, { align: align, "aria-label": name, className: "w-72 max-w-[calc(100vw-2rem)] p-1.5", density: "comfortable", side: side, sideOffset: 6, children: [_jsxs(DropdownMenuGroup, { className: "flex min-w-0 items-center gap-2 py-1.5 pl-2", "data-slot": "account-menu-header", children: [_jsxs("span", { className: "grid min-w-0 flex-1 gap-0.5 text-left", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: identity.name }), identity.notice ? _jsx("span", { className: "text-xs", children: identity.notice }) : null, identity.lines?.map((line, index) => (_jsx("span", { className: "truncate text-xs text-muted-foreground", children: line }, index)))] }), settings ? (_jsx(DropdownMenuItem, { "aria-label": settings.label, className: "text-muted-foreground", iconOnly: true, ...menuItemAction(settings), children: _jsx(Settings, { "aria-hidden": "true" }) })) : null] }), _jsx(DropdownMenuSeparator, { className: "-mx-1.5 my-1.5" }), _jsxs(DropdownMenuGroup, { children: [commandRows(leadingCommands), _jsx(ThemeModeMenu, { ...theme }), language ? _jsx(MenuChoiceRow, { ...language }) : null, choices.map((choice) => (_jsx(AccountMenuChoiceRow, { choice: choice }, choice.label))), commandRows(commands), _jsx(AccountMenuRow, { "aria-busy": signOut.pending || undefined, closeOnClick: signOut.confirms === true, disabled: signOut.pending, icon: _jsx(LogOut, {}), onClick: () => {
36
36
  if (!signOut.pending)
37
37
  signOut.onSignOut();
38
38
  }, children: _jsx(PendingLabel, { pending: signOut.pending, pendingLabel: signOut.pendingLabel, children: signOut.label }) }), signOut.pending ? (_jsx("span", { className: "sr-only", role: "status", children: signOut.pendingLabel })) : null, signOut.failure ? (_jsxs(FieldError, { className: "mx-2 mb-1 break-words", "data-message-code": signOut.failure.code, children: [_jsx("span", { className: "block font-medium", children: signOut.failure.title }), bodyBeyondTitle(signOut.failure) ? (_jsx("span", { className: "block", children: bodyBeyondTitle(signOut.failure) })) : null] })) : null] })] })] }));
@@ -41,7 +41,7 @@ export type ActionMenuProps = RecordMenu & {
41
41
  * @family Menus
42
42
  * @when "An overflow menu triggered by a three-dot icon that reveals additional actions in a dropdown." (https://vercel.com/geist/dots-menu) "Use Menu for a discoverable trigger that opens a list of actions on a single resource (a dots menu on a row, a dropdown on a primary entity)." (https://vercel.com/geist/menu) Ours: the secondary commands of one record from a visible trigger: the row's three dots, or the page's, which comes last in the title row. A record's one main task is a visible button beside the dots; one non-destructive command that can run, alone, is drawn as a button by `RecordList` and `PageActions`, never as a menu; one that cannot run or is locked stays in the menu so its reason is read.
43
43
  * @instead "For right-click or long-press on a row, use `ContextMenu`. For global commands behind `⌘K`, use `CommandMenu`. For two related primary actions, use a split button rather than burying the secondary action." (https://vercel.com/geist/menu) Ours: for a record's main task use a visible button (Edit opens the row). For finding across everything use `CommandDialog`. For a value to choose use `Select`. For right-click use the mirror, `ActionContextMenu`.
44
- * @behaviour "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`, which is required: the row stays in place, inert, with a lock at its end and the reason under its label. The trigger is a ghost icon button at `{spacing.control-height}` (36 px) wherever it stands, named for its record ("More for pec@acme.it"), and comes last, after any button; it keeps its fill while open. The menu opens 10 px under the trigger, aligned to its end: the record's name, the commands with their icons first and the value one acts on in mono under it, then the destructive ones after a divider in the error colour. A command that cannot run now takes `disabledReason`: it stays in place, 36 px like the rest, with its text muted, never dimmed, and says why in a line under its label; a destructive one is muted, not red; a running one takes `pending` and `pendingLabel`. Nothing renders with no command.
44
+ * @behaviour "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`, which is required: the row stays in place, inert, with a lock at its end and the reason under its label. The menu is at most 288 px wide, as the account menu is, and the record's name heading it is one line, cut with an ellipsis and whole in its tooltip, so a long record, a memory or a sentence, never widens it. The trigger is a ghost icon button at `{spacing.control-height}` (36 px) wherever it stands, named for its record ("More for pec@acme.it"), and comes last, after any button; it keeps its fill while open. The menu opens 10 px under the trigger, aligned to its end: the record's name, the commands with their icons first and the value one acts on in mono under it, then the destructive ones after a divider in the error colour. A command that cannot run now takes `disabledReason`: it stays in place, 36 px like the rest, with its text muted, never dimmed, and says why in a line under its label; a destructive one is muted, not red; a running one takes `pending` and `pendingLabel`. Nothing renders with no command.
45
45
  * @words "Item children are Title Case `Verb + Noun` (`Rename Project`, `Duplicate Deployment`). Bare verbs like `Rename` or `Edit` are wrong outside obvious single-object context." (https://vercel.com/geist/menu) "End an item with `…` only when activating it opens a follow-up dialog (`Rename…`, `Transfer to Team…`)." (https://vercel.com/geist/menu) "Group destructive items at the bottom, separated by a divider, and keep the destructive copy as `Verb + Noun` (`Delete Project`, never bare `Delete`)." (https://vercel.com/geist/menu) "Cap a Menu around 10 items. Past that, group with `MenuSection` or move secondary actions to a settings page." (https://vercel.com/geist/menu) Ours: sentence case, "Remove mailbox", not Title Case. The trigger reads "More for {record}"; the header is the record's name. Rows wrap, never truncate.
46
46
  * @access "Typeahead jumps to the next item whose label starts with the typed character; keep the visible label first so typeahead matches what the user sees." (https://vercel.com/geist/menu) "Return focus to the trigger on close so keyboard users keep their place in the row." (https://vercel.com/geist/menu) Ours: the trigger is a ghost icon button named by `label`, which is required, `aria-expanded` while open. `role="menu"`, items `menuitem` in a group named by `record`, which is required; every command requires its `icon`. The value a command acts on and its reason are the item's description; icons hidden.
47
47
  */
@@ -12,7 +12,7 @@ const MAX_COMMANDS = 10;
12
12
  * @family Menus
13
13
  * @when "An overflow menu triggered by a three-dot icon that reveals additional actions in a dropdown." (https://vercel.com/geist/dots-menu) "Use Menu for a discoverable trigger that opens a list of actions on a single resource (a dots menu on a row, a dropdown on a primary entity)." (https://vercel.com/geist/menu) Ours: the secondary commands of one record from a visible trigger: the row's three dots, or the page's, which comes last in the title row. A record's one main task is a visible button beside the dots; one non-destructive command that can run, alone, is drawn as a button by `RecordList` and `PageActions`, never as a menu; one that cannot run or is locked stays in the menu so its reason is read.
14
14
  * @instead "For right-click or long-press on a row, use `ContextMenu`. For global commands behind `⌘K`, use `CommandMenu`. For two related primary actions, use a split button rather than burying the secondary action." (https://vercel.com/geist/menu) Ours: for a record's main task use a visible button (Edit opens the row). For finding across everything use `CommandDialog`. For a value to choose use `Select`. For right-click use the mirror, `ActionContextMenu`.
15
- * @behaviour "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`, which is required: the row stays in place, inert, with a lock at its end and the reason under its label. The trigger is a ghost icon button at `{spacing.control-height}` (36 px) wherever it stands, named for its record ("More for pec@acme.it"), and comes last, after any button; it keeps its fill while open. The menu opens 10 px under the trigger, aligned to its end: the record's name, the commands with their icons first and the value one acts on in mono under it, then the destructive ones after a divider in the error colour. A command that cannot run now takes `disabledReason`: it stays in place, 36 px like the rest, with its text muted, never dimmed, and says why in a line under its label; a destructive one is muted, not red; a running one takes `pending` and `pendingLabel`. Nothing renders with no command.
15
+ * @behaviour "Open on click, not hover; hover-open menus collide with screen readers and trackpad scrolls." (https://vercel.com/geist/menu) "Position auto-flips based on window bounds; don’t hardcode a side that clips on narrow viewports." (https://vercel.com/geist/menu) "Close on item activation, Escape, and outside-click. Don’t auto-close on a hover-out." (https://vercel.com/geist/menu) "Use `MenuItemLocked` for permission-gated actions so the lock icon and disabled state explain why the row is inert." (https://vercel.com/geist/menu) Ours: that is `locked` with its `reason`, which is required: the row stays in place, inert, with a lock at its end and the reason under its label. The menu is at most 288 px wide, as the account menu is, and the record's name heading it is one line, cut with an ellipsis and whole in its tooltip, so a long record, a memory or a sentence, never widens it. The trigger is a ghost icon button at `{spacing.control-height}` (36 px) wherever it stands, named for its record ("More for pec@acme.it"), and comes last, after any button; it keeps its fill while open. The menu opens 10 px under the trigger, aligned to its end: the record's name, the commands with their icons first and the value one acts on in mono under it, then the destructive ones after a divider in the error colour. A command that cannot run now takes `disabledReason`: it stays in place, 36 px like the rest, with its text muted, never dimmed, and says why in a line under its label; a destructive one is muted, not red; a running one takes `pending` and `pendingLabel`. Nothing renders with no command.
16
16
  * @words "Item children are Title Case `Verb + Noun` (`Rename Project`, `Duplicate Deployment`). Bare verbs like `Rename` or `Edit` are wrong outside obvious single-object context." (https://vercel.com/geist/menu) "End an item with `…` only when activating it opens a follow-up dialog (`Rename…`, `Transfer to Team…`)." (https://vercel.com/geist/menu) "Group destructive items at the bottom, separated by a divider, and keep the destructive copy as `Verb + Noun` (`Delete Project`, never bare `Delete`)." (https://vercel.com/geist/menu) "Cap a Menu around 10 items. Past that, group with `MenuSection` or move secondary actions to a settings page." (https://vercel.com/geist/menu) Ours: sentence case, "Remove mailbox", not Title Case. The trigger reads "More for {record}"; the header is the record's name. Rows wrap, never truncate.
17
17
  * @access "Typeahead jumps to the next item whose label starts with the typed character; keep the visible label first so typeahead matches what the user sees." (https://vercel.com/geist/menu) "Return focus to the trigger on close so keyboard users keep their place in the row." (https://vercel.com/geist/menu) Ours: the trigger is a ghost icon button named by `label`, which is required, `aria-expanded` while open. `role="menu"`, items `menuitem` in a group named by `record`, which is required; every command requires its `icon`. The value a command acts on and its reason are the item's description; icons hidden.
18
18
  */
@@ -24,7 +24,7 @@ export function ActionMenu({ label, record, commands, triggerId, open, onOpenCha
24
24
  }
25
25
  if (commands.length === 0)
26
26
  return null;
27
- return (_jsxs(DropdownMenu, { modal: modal, onOpenChange: onOpenChange ? (next) => onOpenChange(next) : undefined, open: open, children: [_jsx(DropdownMenuTrigger, { id: triggerId, render: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": label }), children: _jsx(EllipsisIcon, { "aria-hidden": "true" }) }), _jsx(DropdownMenuContent, { align: "end", finalFocus: finalFocus, side: side, children: _jsx(RecordMenuItems, { commands: commands, record: record }) })] }));
27
+ return (_jsxs(DropdownMenu, { modal: modal, onOpenChange: onOpenChange ? (next) => onOpenChange(next) : undefined, open: open, children: [_jsx(DropdownMenuTrigger, { id: triggerId, render: _jsx(Button, { variant: "ghost", size: "icon", "aria-label": label }), children: _jsx(EllipsisIcon, { "aria-hidden": "true" }) }), _jsx(DropdownMenuContent, { align: "end", className: "max-w-72", finalFocus: finalFocus, side: side, children: _jsx(RecordMenuItems, { commands: commands, record: record }) })] }));
28
28
  }
29
29
  /**
30
30
  * A record's menu opened from its row by a right-click: the mirror of its `ActionMenu`.
@@ -40,5 +40,5 @@ export function ActionContextMenu({ label, record, commands, children }) {
40
40
  const none = commands.length === 0;
41
41
  // The row stays one element whether or not it has commands, so a menu that appears or goes
42
42
  // never remounts the row; with none the browser keeps its own menu and the row its selection.
43
- return (_jsxs(ContextMenu, { disabled: none, children: [_jsx(ContextMenuTrigger, { className: none ? "select-auto" : undefined, render: children }), none ? null : (_jsx(ContextMenuContent, { "aria-label": label, children: _jsx(RecordMenuItems, { commands: commands, record: record }) }))] }));
43
+ return (_jsxs(ContextMenu, { disabled: none, children: [_jsx(ContextMenuTrigger, { className: none ? "select-auto" : undefined, render: children }), none ? null : (_jsx(ContextMenuContent, { "aria-label": label, className: "max-w-72", children: _jsx(RecordMenuItems, { commands: commands, record: record }) }))] }));
44
44
  }
@@ -8,7 +8,7 @@ import { type StatusBadgeTone } from "./status-badge.js";
8
8
  * @family Navigation
9
9
  * @when Nadia's Agents in her window's sidebar, and a website scene that shows a list of Agents.
10
10
  * @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. In Nadia's list the row is at least 52 px high, her orb at 32 px in her real state, in the narrow column from 640 to 899 px as in the wide one.
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
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
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 mark, so the line carries its meaning.
14
14
  */
@@ -22,7 +22,7 @@ export declare function AgentListRow({ className, color, current, form, motionKe
22
22
  name: string;
23
23
  /** No room for the words: the orb alone, the rest for a screen reader. */
24
24
  narrow?: boolean;
25
- size?: 24 | 32 | 40;
25
+ size?: 24 | 32 | 40 | 64;
26
26
  state?: AgentOrbState;
27
27
  /** What the Agent is doing, or what it is for. Absent, the name stands alone. */
28
28
  stateLine?: string;
@@ -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,CAAC;IACpB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B,+BAkCA"}
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"}
@@ -10,10 +10,10 @@ import { cn } from "../lib/utils.js";
10
10
  * @family Navigation
11
11
  * @when Nadia's Agents in her window's sidebar, and a website scene that shows a list of Agents.
12
12
  * @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. In Nadia's list the row is at least 52 px high, her orb at 32 px in her real state, in the narrow column from 640 to 899 px as in the wide one.
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
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
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 mark, so the line carries its meaning.
16
16
  */
17
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", narrow && "justify-center", className), "data-slot": "agent-list-row", "data-current": current || undefined, ...props, children: [_jsx(AgentOrb, { 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] })] }));
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] })] }));
19
19
  }
@@ -3,14 +3,14 @@ import * as React from "react";
3
3
  * The top of a product page: its title, and the page's actions on the title's row.
4
4
  *
5
5
  * @family Compositions
6
- * @when The top of every collection and working page: the title at heading size, `PageActions` at
7
- * the trailing edge of its row.
6
+ * @when The top of every page, collection, working page and settings page alike: the title at heading
7
+ * size, `PageActions` at the trailing edge of its row.
8
8
  * @instead An object's own header is `ObjectPage`'s. The path above it is the top bar's
9
9
  * `Breadcrumb`; filters, search and sort sit in the toolbar below.
10
10
  * @behaviour The title is always there and the actions arrive through the `PageActions` slot, so
11
11
  * the page draws its commands once. On a phone the title keeps its row with one action, as Vercel's
12
- * does; it gives way, and the actions wrap under it, only when they leave it less than 128 px. Under the title only the `description` may sit: one muted line
13
- * saying what the page's records are for, for a page whose kind needs explaining. It ends in a link
12
+ * does; it gives way, and the actions wrap under it, only when they leave it less than 128 px. Under the title sits the `description`: one muted line
13
+ * saying what the page's concept is, on every page that is a destination or a section. It ends in a link
14
14
  * to learn more when there is one, and never counts or introduces anything else. The description
15
15
  * is neutral; no hue sits in the header.
16
16
  * @words The title is the page's name as the sidebar writes it: *Customers*, *Agents*. The
@@ -5,14 +5,14 @@ import { PageActionsSlot } from "./page-actions.js";
5
5
  * The top of a product page: its title, and the page's actions on the title's row.
6
6
  *
7
7
  * @family Compositions
8
- * @when The top of every collection and working page: the title at heading size, `PageActions` at
9
- * the trailing edge of its row.
8
+ * @when The top of every page, collection, working page and settings page alike: the title at heading
9
+ * size, `PageActions` at the trailing edge of its row.
10
10
  * @instead An object's own header is `ObjectPage`'s. The path above it is the top bar's
11
11
  * `Breadcrumb`; filters, search and sort sit in the toolbar below.
12
12
  * @behaviour The title is always there and the actions arrive through the `PageActions` slot, so
13
13
  * the page draws its commands once. On a phone the title keeps its row with one action, as Vercel's
14
- * does; it gives way, and the actions wrap under it, only when they leave it less than 128 px. Under the title only the `description` may sit: one muted line
15
- * saying what the page's records are for, for a page whose kind needs explaining. It ends in a link
14
+ * does; it gives way, and the actions wrap under it, only when they leave it less than 128 px. Under the title sits the `description`: one muted line
15
+ * saying what the page's concept is, on every page that is a destination or a section. It ends in a link
16
16
  * to learn more when there is one, and never counts or introduces anything else. The description
17
17
  * is neutral; no hue sits in the header.
18
18
  * @words The title is the page's name as the sidebar writes it: *Customers*, *Agents*. The
@@ -1,11 +1,12 @@
1
1
  import * as React from "react";
2
- export type ReadingColumnWidth = "full" | "reading" | "configuration";
2
+ export type ReadingColumnWidth = "full" | "reading" | "settings";
3
3
  /**
4
- * The column a page's content stands in: full, reading or configuration width.
4
+ * The column a page's content stands in: full, reading or settings width.
5
5
  *
6
6
  * @family Other
7
- * @when Setting a page's measure: `reading` for prose and conversations, `configuration` for
8
- * settings, `full` for collections.
7
+ * @when Setting a page's measure: `reading` (768 px) for prose and conversations, `settings` (960 px)
8
+ * for a page of settings, as Vercel's settings stop, and `full` (1280 px, the Portal shell's width)
9
+ * for collections, which fill the page as Vercel's lists do.
9
10
  * @instead A settings page's column is `SettingsPage`'s. A card row is `CardRow`.
10
11
  * @behaviour Centred with a maximum width per kind; full takes the content's width.
11
12
  * @words None of its own.
@@ -1 +1 @@
1
- {"version":3,"file":"reading-column.d.ts","sourceRoot":"","sources":["../../src/components/reading-column.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,eAAe,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,iBAAS,aAAa,CAAC,EACrB,KAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,kBAAkB,CAAA;CAAE,qBAc9D;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"reading-column.d.ts","sourceRoot":"","sources":["../../src/components/reading-column.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC;AAEjE;;;;;;;;;;;GAWG;AACH,iBAAS,aAAa,CAAC,EACrB,KAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,kBAAkB,CAAA;CAAE,qBAe9D;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -1,17 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../lib/utils.js";
3
3
  /**
4
- * The column a page's content stands in: full, reading or configuration width.
4
+ * The column a page's content stands in: full, reading or settings width.
5
5
  *
6
6
  * @family Other
7
- * @when Setting a page's measure: `reading` for prose and conversations, `configuration` for
8
- * settings, `full` for collections.
7
+ * @when Setting a page's measure: `reading` (768 px) for prose and conversations, `settings` (960 px)
8
+ * for a page of settings, as Vercel's settings stop, and `full` (1280 px, the Portal shell's width)
9
+ * for collections, which fill the page as Vercel's lists do.
9
10
  * @instead A settings page's column is `SettingsPage`'s. A card row is `CardRow`.
10
11
  * @behaviour Centred with a maximum width per kind; full takes the content's width.
11
12
  * @words None of its own.
12
13
  * @access A layout container.
13
14
  */
14
15
  function ReadingColumn({ width = "reading", className, ...props }) {
15
- return (_jsx("div", { "data-slot": "reading-column", "data-width": width, className: cn("mx-auto flex w-full min-w-0 flex-col gap-6", width === "reading" && "max-w-3xl", width === "configuration" && "max-w-2xl", className), ...props }));
16
+ return (_jsx("div", { "data-slot": "reading-column", "data-width": width, className: cn("mx-auto flex w-full min-w-0 flex-col gap-6", width === "reading" && "max-w-3xl", width === "settings" && "max-w-[60rem]", width === "full" && "max-w-7xl", className), ...props }));
16
17
  }
17
18
  export { ReadingColumn };
@@ -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` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
11
+ * @behaviour The mark stands 16 px before the name. The name is semibold (600) ink and the detail a muted 14 px line, two lines with no gap between them, so the row is an entity row; `mark` 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.
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.
@@ -19,7 +19,8 @@ declare function RecordIdentity({ name, mark, hint, detail, wraps, }: {
19
19
  mark: IdentityMarkProps;
20
20
  /** Read after the name in its title, such as an identifier the row does not show. */
21
21
  hint?: string;
22
- detail: NonNullable<ReactNode>;
22
+ /** The muted line under the name; absent, the row is the name alone. */
23
+ detail?: ReactNode;
23
24
  wraps?: boolean;
24
25
  }): import("react").JSX.Element;
25
26
  export { RecordIdentity };
@@ -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,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IAC/B,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,+BAmCA;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -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` and `detail` are both required, and a record with nothing to say in the detail passes the dash of `TableValue`. The name holds one line and ends in an ellipsis, whole in its title, with a `hint` such as an ID read after it. The detail is one line too and ends in an ellipsis, whole in its title when it is text; in a row on a card narrower than its columns, the facts that leave the row join it after a middle dot, so the record stays the name over one line. `wraps` only when the name is the whole record, such as a memory, and then the detail wraps too. The table owns the link.
13
+ * @behaviour The mark stands 16 px before the name. The name is semibold (600) ink and the detail a muted 14 px line, two lines with no gap between them, so the row is an entity row; `mark` 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.
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.
@@ -14,10 +14,10 @@ export type RecordName = {
14
14
  /** One line, ending in an ellipsis and whole in its title, unless the list `wraps`. */
15
15
  name: string;
16
16
  /**
17
- * The muted line under the name: what it is or where it comes from. Every row has one; a record
18
- * with nothing to say passes `<TableValue missingLabel="…" value={null} />`, the dash.
17
+ * The muted line under the name: what it is or where it comes from. A record with nothing to
18
+ * say leaves it out and is the name alone, never a dash.
19
19
  */
20
- detail: NonNullable<ReactNode>;
20
+ detail?: ReactNode;
21
21
  /** Its identity mark, drawn at 32. Every row has one: an initials mark when the record has no picture. */
22
22
  mark: IdentityMarkProps;
23
23
  };
@@ -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` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open, and it widens for a failed action's next steps only while a row shows one. Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row: a destructive command stays in the three dots. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record shows as its catalogue message inside its own row, never a notice under the row: it replaces the detail line, with its next steps beside its commands, or under the message on a card too narrow for the row's columns. With `open` the whole row is one target and takes the `accent` hover, and a row that only opens ends in a muted chevron; a row that opens nothing never reacts to hover. With `editor` the record's row opens its form under its line. `empty` is required: `null` is the choice to draw nothing for a list with no records, and any other value is the state it draws. A note about the whole list is `footer.note`: one muted line, an optional *Learn more* after it at the left and one secondary action at the right, in a strip of its own under the count and the paging, as Vercel ends its deployments list ("Deployment retention is enabled. Learn more", *View recently deleted*). Colour is neutral, the name in ink and every other cell in the body grey, except the status badge and a failed action's message.
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.
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)
@@ -1 +1 @@
1
- {"version":3,"file":"record-list.d.ts","sourceRoot":"","sources":["../../src/components/record-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAiB,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAEzE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAIjG,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAK9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,KAAK,UAAU,EAAqC,MAAM,wBAAwB,CAAC;AAG5F,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,MAAM,MAAM,UAAU,GAAG;IACvB,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IAC/B,0GAA0G;IAC1G,IAAI,EAAE,iBAAiB,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,SAAS,CAAC;IACnC,+FAA+F;IAC/F,IAAI,EAAE,MAAM,CAAC;IACb,gHAAgH;IAChH,KAAK,CAAC,EAAE,IAAI,CAAC;CACd,CAAC;AAEF,kGAAkG;AAClG,MAAM,MAAM,WAAW,CAAC,OAAO,IAC3B,SAAS,EAAE,GACX,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GAC9B,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,GACnD,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AAE7E,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AA2CpE,MAAM,MAAM,gBAAgB,CAAC,OAAO,IAAI;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnE,6EAA6E;IAC7E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IAClD,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,OAAO,IAAI;IACrC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IACnC,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IACtC,eAAe,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iBAAiB;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE;QACN,KAAK,CAAC,EAAE,SAAS,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;QAClC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;KAC/B,CAAC;IACF,2IAA2I;IAC3I,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEF,KAAK,cAAc,CAAC,OAAO,SAAS,OAAO,IAAI;IAC7C,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,CAAC;IACxC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;IACnC,gHAAgH;IAChH,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,CAAC;IACtC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAClC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,yDAAyD;IACzD,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,YAAY,GAAG,IAAI,CAAC;QAC7C,gGAAgG;QAChG,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,IAAI,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACjC;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,0DAA0D;QAC1D,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,sBAAsB,GAAG,IAAI,CAAC;KACxD,CAAC;IACF,mEAAmE;IACnE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IACvF,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC;QACzC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;QACnC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,SAAS,CAAC;KAC1D,CAAC;IACF;;;;OAIG;IACH,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,SAAS,CAAA;KAAE,CAAC;IAChE,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClC;;;OAGG;IACH,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IACxE,kDAAkD;IAClD,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACpD;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,SAAS,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IACvE,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B,CAAC;AAEF,KAAK,kBAAkB,CAAC,OAAO,SAAS,OAAO,IAC3C;IAAE,OAAO,CAAC,EAAE,KAAK,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD;IACE;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IACxF,iFAAiF;IACjF,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,GAAG,IAAI,CAAC;IAC/C;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN,MAAM,MAAM,eAAe,CAAC,OAAO,SAAS,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,GAC5E,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAE9B,KAAK,WAAW,CAAC,IAAI,EAAE,GAAG,SAAS,WAAW,IAAI,IAAI,SAAS,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAEjG,iGAAiG;AACjG,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,OAAO,EAAE,GAAG,SAAS,WAAW,IAAI,WAAW,CAC3F,eAAe,CAAC,OAAO,CAAC,EACxB,GAAG,CACJ,CAAC;AAoUF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,UAAU,CAAC,OAAO,SAAS,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,sCAwClF"}
1
+ {"version":3,"file":"record-list.d.ts","sourceRoot":"","sources":["../../src/components/record-list.tsx"],"names":[],"mappings":"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"}
@@ -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` is required and so are the mark and the line, and a record with nothing to say passes the dash. Give every column a `size` in pixels; the name takes the rest. With `layout="line"`, as on Vercel's Projects page, the facts and the status share one muted line, joined by a middle dot, in a column as wide as the name's, and the row stays one line (mark, name over its line, that summary, the time, the ring, the three dots) on a card from 448 px, and on a narrower card the summary and the time move under the name as one muted line joined by a middle dot, in the same row, their labels read by assistive technology only. Rows of `columns` follow the same rule once the card is narrower than their columns: the facts, the status and the time leave the row for that one line, ending in an ellipsis, never a labelled list. `facts` takes at most three. A menu of one command that is not destructive, with no row command, is that command's button, except in a `line` row, which keeps it in the three dots as Vercel's project row does; without a `commandsSize` the column is as wide as the widest such button, so its label is never cut. Status is only for the exception, empty for the usual record, and its column stands only while a record in the list shows one, so the name and its line keep the room; the commands column likewise stands only while a record has a command, a menu or a message, or the rows open, and it widens for a failed action's next steps only while a row shows one. Never the three dots before the button, a decorative icon for the record's mark, a status on every row, or a destructive button on every row: a destructive command stays in the three dots. A `line` row's summary joins only the facts the record has, so it never ends in a dot. A failed or refused action of the record shows as its catalogue message inside its own row, never a notice under the row: it replaces the detail line, with its next steps beside its commands, or under the message on a card too narrow for the row's columns. With `open` the whole row is one target and takes the `accent` hover, and a row that only opens ends in a muted chevron; a row that opens nothing never reacts to hover. With `editor` the record's row opens its form under its line. `empty` is required: `null` is the choice to draw nothing for a list with no records, and any other value is the state it draws. A note about the whole list is `footer.note`: one muted line, an optional *Learn more* after it at the left and one secondary action at the right, in a strip of its own under the count and the paging, as Vercel ends its deployments list ("Deployment retention is enabled. Learn more", *View recently deleted*). Colour is neutral, the name in ink and every other cell in the body grey, except the status badge and a failed action's message.
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.
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)
@@ -1,8 +1,5 @@
1
- import type { ComponentProps, ReactElement, ReactNode } from "react";
1
+ import type { ReactElement, ReactNode } from "react";
2
2
  export type SettingsPageProps = {
3
- /** A screen-reader h1, where the product's chrome does not draw one: the path already names the place. */
4
- title?: string;
5
- headingProps?: Omit<ComponentProps<"h1">, "children">;
6
3
  /** The section cards, in order: SettingsSection, SettingsFactsSection. */
7
4
  children: ReactNode;
8
5
  };
@@ -12,9 +9,9 @@ export type SettingsPageProps = {
12
9
  * @family Compositions
13
10
  * @when A place whose job is changing how something behaves: an account's profile, a company's identity, Nadia's notifications.
14
11
  * @instead One object's page with a settings card among its sections is an ObjectPage; "Place it once per app, in the footer or settings, not duplicated across pages." (https://vercel.com/geist/theme-switcher) Ours: Theme and Language, which apply on change, stay in the account menu.
15
- * @behaviour One setting per card (the card's shapes are SettingsSection's: one field, a row of short parts of one value, rows of switches or of selects, a header switch), the cards stacked 24 apart across the page's content width under the page's title row, as Vercel's settings cards fill their column, with no heading between them; a field inside keeps its own bound. A page that mixes cards with other content, such as a table or a list of rules, is not a SettingsPage: its sections take a plain h2 above each card. The page draws no header and no save of its own: each SettingsSection saves from its footer. The danger zone closes the page, in rising severity: transfer, then pause, then delete; only delete is `tone="error"`, and only delete and pause take a button in a hue.
16
- * @words `title` names the place as the navigation does ("Profile"); the sections' titles and lines carry the rest. A card's title is never the page's h1.
17
- * @access `title` becomes a visually hidden h1 for a product whose chrome shows the place without a heading; leave it out where the chrome already draws the h1.
12
+ * @behaviour One setting per card (the card's shapes are SettingsSection's: one field, a row of short parts of one value, rows of switches or of selects), the cards stacked 24 apart in the settings column (`ReadingColumn` `settings`, 960 px) under the page's header, which the product's page frame draws with its title and description, as Vercel's settings cards fill their column and stop there, with no heading between them; a field inside keeps its own bound. A page that mixes cards with other content, such as a table or a list of rules, is not a SettingsPage: its sections take a plain h2 above each card. The page draws no header and no save of its own: each SettingsSection saves from its footer. The danger zone closes the page, in rising severity: transfer, then pause, then delete; only delete is `tone="error"`, and only delete and pause take a button in a hue.
13
+ * @words The sections' titles and lines; a card's title is never the page's h1.
14
+ * @access Draws no heading of its own: the page frame's header is the page's h1.
18
15
  */
19
- export declare function SettingsPage({ title, headingProps, children }: SettingsPageProps): ReactElement;
16
+ export declare function SettingsPage({ children }: SettingsPageProps): ReactElement;
20
17
  //# sourceMappingURL=settings-page.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings-page.d.ts","sourceRoot":"","sources":["../../src/components/settings-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKrE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,0GAA0G;IAC1G,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;IACtD,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,YAAY,CAW/F"}
1
+ {"version":3,"file":"settings-page.d.ts","sourceRoot":"","sources":["../../src/components/settings-page.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIrD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,YAAY,CAE1E"}
@@ -1,5 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cn } from "../lib/utils.js";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
3
2
  import { ReadingColumn } from "./reading-column.js";
4
3
  /**
5
4
  * A page of settings: section cards across the page's width under its title, each saving its own values.
@@ -7,10 +6,10 @@ import { ReadingColumn } from "./reading-column.js";
7
6
  * @family Compositions
8
7
  * @when A place whose job is changing how something behaves: an account's profile, a company's identity, Nadia's notifications.
9
8
  * @instead One object's page with a settings card among its sections is an ObjectPage; "Place it once per app, in the footer or settings, not duplicated across pages." (https://vercel.com/geist/theme-switcher) Ours: Theme and Language, which apply on change, stay in the account menu.
10
- * @behaviour One setting per card (the card's shapes are SettingsSection's: one field, a row of short parts of one value, rows of switches or of selects, a header switch), the cards stacked 24 apart across the page's content width under the page's title row, as Vercel's settings cards fill their column, with no heading between them; a field inside keeps its own bound. A page that mixes cards with other content, such as a table or a list of rules, is not a SettingsPage: its sections take a plain h2 above each card. The page draws no header and no save of its own: each SettingsSection saves from its footer. The danger zone closes the page, in rising severity: transfer, then pause, then delete; only delete is `tone="error"`, and only delete and pause take a button in a hue.
11
- * @words `title` names the place as the navigation does ("Profile"); the sections' titles and lines carry the rest. A card's title is never the page's h1.
12
- * @access `title` becomes a visually hidden h1 for a product whose chrome shows the place without a heading; leave it out where the chrome already draws the h1.
9
+ * @behaviour One setting per card (the card's shapes are SettingsSection's: one field, a row of short parts of one value, rows of switches or of selects), the cards stacked 24 apart in the settings column (`ReadingColumn` `settings`, 960 px) under the page's header, which the product's page frame draws with its title and description, as Vercel's settings cards fill their column and stop there, with no heading between them; a field inside keeps its own bound. A page that mixes cards with other content, such as a table or a list of rules, is not a SettingsPage: its sections take a plain h2 above each card. The page draws no header and no save of its own: each SettingsSection saves from its footer. The danger zone closes the page, in rising severity: transfer, then pause, then delete; only delete is `tone="error"`, and only delete and pause take a button in a hue.
10
+ * @words The sections' titles and lines; a card's title is never the page's h1.
11
+ * @access Draws no heading of its own: the page frame's header is the page's h1.
13
12
  */
14
- export function SettingsPage({ title, headingProps, children }) {
15
- return (_jsxs(ReadingColumn, { width: "full", children: [title ? (_jsx("h1", { ...headingProps, className: cn("sr-only", headingProps?.className), children: title })) : null, children] }));
13
+ export function SettingsPage({ children }) {
14
+ return _jsx(ReadingColumn, { width: "settings", children: children });
16
15
  }