@nadicodeai/ui 12.1.111 → 12.1.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/AGENTS.md +11 -9
  2. package/README.md +3 -2
  3. package/dist/components/account-menu.d.ts +1 -1
  4. package/dist/components/account-menu.js +1 -1
  5. package/dist/components/action-menu.d.ts +2 -2
  6. package/dist/components/action-menu.js +2 -2
  7. package/dist/components/activity-feed.d.ts +1 -1
  8. package/dist/components/activity-feed.js +1 -1
  9. package/dist/components/agent-card.d.ts +5 -3
  10. package/dist/components/agent-card.d.ts.map +1 -1
  11. package/dist/components/agent-card.js +5 -3
  12. package/dist/components/agent-list-row.d.ts +2 -2
  13. package/dist/components/agent-list-row.js +2 -2
  14. package/dist/components/agent-orb.d.ts +31 -7
  15. package/dist/components/agent-orb.d.ts.map +1 -1
  16. package/dist/components/agent-orb.js +29 -5
  17. package/dist/components/agent-profile.d.ts +6 -2
  18. package/dist/components/agent-profile.d.ts.map +1 -1
  19. package/dist/components/agent-profile.js +6 -2
  20. package/dist/components/aspect-ratio.d.ts +7 -3
  21. package/dist/components/aspect-ratio.d.ts.map +1 -1
  22. package/dist/components/aspect-ratio.js +7 -3
  23. package/dist/components/avatar.d.ts +11 -5
  24. package/dist/components/avatar.d.ts.map +1 -1
  25. package/dist/components/avatar.js +11 -5
  26. package/dist/components/breadcrumb.d.ts +1 -1
  27. package/dist/components/breadcrumb.js +1 -1
  28. package/dist/components/button.d.ts +23 -10
  29. package/dist/components/button.d.ts.map +1 -1
  30. package/dist/components/button.js +23 -10
  31. package/dist/components/card-row.d.ts +4 -2
  32. package/dist/components/card-row.d.ts.map +1 -1
  33. package/dist/components/card-row.js +4 -2
  34. package/dist/components/card.d.ts +1 -1
  35. package/dist/components/card.js +1 -1
  36. package/dist/components/carousel.d.ts +9 -4
  37. package/dist/components/carousel.d.ts.map +1 -1
  38. package/dist/components/carousel.js +9 -4
  39. package/dist/components/catalog-drawer.d.ts +1 -1
  40. package/dist/components/catalog-drawer.js +1 -1
  41. package/dist/components/chart-card.d.ts +1 -1
  42. package/dist/components/chart-card.js +1 -1
  43. package/dist/components/checkbox.d.ts +2 -1
  44. package/dist/components/checkbox.d.ts.map +1 -1
  45. package/dist/components/checkbox.js +2 -1
  46. package/dist/components/choicebox.d.ts +9 -5
  47. package/dist/components/choicebox.d.ts.map +1 -1
  48. package/dist/components/choicebox.js +9 -5
  49. package/dist/components/clearable-input.d.ts +2 -1
  50. package/dist/components/clearable-input.d.ts.map +1 -1
  51. package/dist/components/clearable-input.js +2 -1
  52. package/dist/components/code-block.d.ts +13 -10
  53. package/dist/components/code-block.d.ts.map +1 -1
  54. package/dist/components/code-block.js +13 -10
  55. package/dist/components/collection-filters.d.ts +1 -1
  56. package/dist/components/collection-filters.js +1 -1
  57. package/dist/components/collection-search.d.ts +11 -7
  58. package/dist/components/collection-search.d.ts.map +1 -1
  59. package/dist/components/collection-search.js +11 -7
  60. package/dist/components/combobox.d.ts +4 -1
  61. package/dist/components/combobox.d.ts.map +1 -1
  62. package/dist/components/combobox.js +4 -1
  63. package/dist/components/command.d.ts +1 -1
  64. package/dist/components/command.js +1 -1
  65. package/dist/components/company-card.d.ts +28 -5
  66. package/dist/components/company-card.d.ts.map +1 -1
  67. package/dist/components/company-card.js +28 -5
  68. package/dist/components/confirm-dialog.d.ts +3 -2
  69. package/dist/components/confirm-dialog.d.ts.map +1 -1
  70. package/dist/components/confirm-dialog.js +2 -2
  71. package/dist/components/copy-button.d.ts +2 -2
  72. package/dist/components/copy-button.js +2 -2
  73. package/dist/components/data-table.d.ts +2 -2
  74. package/dist/components/data-table.js +2 -2
  75. package/dist/components/drawer.d.ts +4 -4
  76. package/dist/components/drawer.d.ts.map +1 -1
  77. package/dist/components/drawer.js +3 -3
  78. package/dist/components/dropdown-menu.d.ts +2 -2
  79. package/dist/components/dropdown-menu.js +2 -2
  80. package/dist/components/empty-state.d.ts +2 -2
  81. package/dist/components/empty-state.js +2 -2
  82. package/dist/components/field.d.ts +4 -0
  83. package/dist/components/field.d.ts.map +1 -1
  84. package/dist/components/field.js +4 -0
  85. package/dist/components/file-diff.d.ts +5 -2
  86. package/dist/components/file-diff.d.ts.map +1 -1
  87. package/dist/components/file-diff.js +5 -2
  88. package/dist/components/form-dialog.d.ts +1 -1
  89. package/dist/components/form-dialog.js +1 -1
  90. package/dist/components/form-drawer.d.ts +1 -1
  91. package/dist/components/form-drawer.js +1 -1
  92. package/dist/components/gauge.d.ts +9 -7
  93. package/dist/components/gauge.d.ts.map +1 -1
  94. package/dist/components/gauge.js +9 -7
  95. package/dist/components/hover-card.d.ts +5 -2
  96. package/dist/components/hover-card.d.ts.map +1 -1
  97. package/dist/components/hover-card.js +5 -2
  98. package/dist/components/identity-mark.d.ts +3 -3
  99. package/dist/components/identity-mark.js +3 -3
  100. package/dist/components/input-group.d.ts +1 -0
  101. package/dist/components/input-group.d.ts.map +1 -1
  102. package/dist/components/input-group.js +1 -0
  103. package/dist/components/input-otp.d.ts +5 -3
  104. package/dist/components/input-otp.d.ts.map +1 -1
  105. package/dist/components/input-otp.js +5 -3
  106. package/dist/components/input.d.ts +4 -2
  107. package/dist/components/input.d.ts.map +1 -1
  108. package/dist/components/input.js +4 -2
  109. package/dist/components/item.d.ts +1 -1
  110. package/dist/components/item.js +1 -1
  111. package/dist/components/kbd.d.ts +4 -2
  112. package/dist/components/kbd.d.ts.map +1 -1
  113. package/dist/components/kbd.js +4 -2
  114. package/dist/components/label.d.ts +8 -3
  115. package/dist/components/label.d.ts.map +1 -1
  116. package/dist/components/label.js +8 -3
  117. package/dist/components/load-more-button.d.ts +3 -2
  118. package/dist/components/load-more-button.d.ts.map +1 -1
  119. package/dist/components/load-more-button.js +3 -2
  120. package/dist/components/message-notice.d.ts +1 -1
  121. package/dist/components/message-notice.js +1 -1
  122. package/dist/components/multi-select.d.ts +6 -4
  123. package/dist/components/multi-select.d.ts.map +1 -1
  124. package/dist/components/multi-select.js +6 -4
  125. package/dist/components/notice-banner.d.ts +2 -2
  126. package/dist/components/notice-banner.js +2 -2
  127. package/dist/components/object-workspace.d.ts +3 -3
  128. package/dist/components/object-workspace.d.ts.map +1 -1
  129. package/dist/components/object-workspace.js +2 -2
  130. package/dist/components/pairing-code.d.ts +2 -2
  131. package/dist/components/pairing-code.js +2 -2
  132. package/dist/components/picture-label.d.ts +3 -2
  133. package/dist/components/picture-label.d.ts.map +1 -1
  134. package/dist/components/picture-label.js +3 -2
  135. package/dist/components/popover.d.ts +7 -3
  136. package/dist/components/popover.d.ts.map +1 -1
  137. package/dist/components/popover.js +7 -3
  138. package/dist/components/progress-checklist.d.ts +1 -1
  139. package/dist/components/progress-checklist.js +1 -1
  140. package/dist/components/progress.d.ts +4 -2
  141. package/dist/components/progress.d.ts.map +1 -1
  142. package/dist/components/progress.js +4 -2
  143. package/dist/components/qr-code.d.ts +5 -2
  144. package/dist/components/qr-code.d.ts.map +1 -1
  145. package/dist/components/qr-code.js +5 -2
  146. package/dist/components/radio-group.d.ts +8 -5
  147. package/dist/components/radio-group.d.ts.map +1 -1
  148. package/dist/components/radio-group.js +8 -5
  149. package/dist/components/record-identity.d.ts +1 -1
  150. package/dist/components/record-identity.js +1 -1
  151. package/dist/components/record-list.d.ts +2 -2
  152. package/dist/components/record-list.js +2 -2
  153. package/dist/components/record-sheet.d.ts +2 -2
  154. package/dist/components/record-sheet.js +2 -2
  155. package/dist/components/record-time.d.ts +1 -1
  156. package/dist/components/record-time.js +1 -1
  157. package/dist/components/resizable.d.ts +2 -2
  158. package/dist/components/resizable.js +2 -2
  159. package/dist/components/row-edit-form.d.ts +1 -1
  160. package/dist/components/row-edit-form.js +1 -1
  161. package/dist/components/run-timeline.d.ts +2 -2
  162. package/dist/components/run-timeline.js +2 -2
  163. package/dist/components/scroll-area.d.ts +5 -3
  164. package/dist/components/scroll-area.d.ts.map +1 -1
  165. package/dist/components/scroll-area.js +5 -3
  166. package/dist/components/segmented-control.d.ts +1 -1
  167. package/dist/components/segmented-control.js +1 -1
  168. package/dist/components/select.d.ts +5 -3
  169. package/dist/components/select.d.ts.map +1 -1
  170. package/dist/components/select.js +5 -3
  171. package/dist/components/separator.d.ts +4 -2
  172. package/dist/components/separator.d.ts.map +1 -1
  173. package/dist/components/separator.js +4 -2
  174. package/dist/components/settings-facts.d.ts +3 -2
  175. package/dist/components/settings-facts.d.ts.map +1 -1
  176. package/dist/components/settings-facts.js +3 -2
  177. package/dist/components/settings-section.d.ts +1 -1
  178. package/dist/components/settings-section.js +1 -1
  179. package/dist/components/sheet.d.ts +6 -3
  180. package/dist/components/sheet.d.ts.map +1 -1
  181. package/dist/components/sheet.js +6 -3
  182. package/dist/components/skeleton.d.ts +1 -1
  183. package/dist/components/skeleton.js +1 -1
  184. package/dist/components/slider.d.ts +2 -1
  185. package/dist/components/slider.d.ts.map +1 -1
  186. package/dist/components/slider.js +2 -1
  187. package/dist/components/snippet.d.ts +3 -1
  188. package/dist/components/snippet.d.ts.map +1 -1
  189. package/dist/components/snippet.js +3 -1
  190. package/dist/components/sonner.d.ts +2 -2
  191. package/dist/components/sonner.js +2 -2
  192. package/dist/components/status-badge.d.ts +5 -2
  193. package/dist/components/status-badge.d.ts.map +1 -1
  194. package/dist/components/status-badge.js +5 -2
  195. package/dist/components/status-dot.d.ts +2 -1
  196. package/dist/components/status-dot.d.ts.map +1 -1
  197. package/dist/components/status-dot.js +2 -1
  198. package/dist/components/switch.d.ts +7 -6
  199. package/dist/components/switch.d.ts.map +1 -1
  200. package/dist/components/switch.js +7 -6
  201. package/dist/components/table.d.ts +18 -11
  202. package/dist/components/table.d.ts.map +1 -1
  203. package/dist/components/table.js +18 -11
  204. package/dist/components/tabs.d.ts +19 -13
  205. package/dist/components/tabs.d.ts.map +1 -1
  206. package/dist/components/tabs.js +19 -13
  207. package/dist/components/text-link.d.ts +9 -4
  208. package/dist/components/text-link.d.ts.map +1 -1
  209. package/dist/components/text-link.js +9 -4
  210. package/dist/components/text-with-copy-button.d.ts +2 -2
  211. package/dist/components/text-with-copy-button.js +2 -2
  212. package/dist/components/textarea.d.ts +4 -3
  213. package/dist/components/textarea.d.ts.map +1 -1
  214. package/dist/components/textarea.js +4 -3
  215. package/dist/components/tooltip.d.ts +5 -3
  216. package/dist/components/tooltip.d.ts.map +1 -1
  217. package/dist/components/tooltip.js +5 -3
  218. package/dist/components/usage-meter.d.ts +2 -2
  219. package/dist/components/usage-meter.js +2 -2
  220. package/dist/components/waiting-line.d.ts +1 -1
  221. package/dist/components/waiting-line.js +1 -1
  222. package/dist/showcase/usage.generated.d.ts.map +1 -1
  223. package/dist/showcase/usage.generated.js +147 -147
  224. package/dist/styles/shadcn.tailwind.css +8 -0
  225. package/package.json +3 -3
@@ -11,8 +11,8 @@ import { ChevronRightIcon, CheckIcon, LockIcon } from "lucide-react";
11
11
  *
12
12
  * @family Menus
13
13
  * @when "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: a menu no composition draws: a column chooser, a sort, a product's own choices in a submenu.
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: those are `ContextMenu` and `CommandDialog`; two related primary actions stand side by side as buttons. A record's or a page's commands are `ActionMenu` or `PageActions`' menu, from data. The account's rows are `AccountMenu`. A value to choose in a form is `Select`.
15
- * @behaviour "Dropdown menu opened via button. Supports typeahead and keyboard navigation." (https://vercel.com/geist/menu) "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`. A solid floating surface, 200 px wide at least, 10 px from its trigger. A labelled trigger may end in a chevron; an icon trigger has none. Safe commands come first, each with its icon, groups split by a divider, the destructive command last. Colour sits on that command alone: its text is the error colour at rest and its row takes the soft error fill when highlighted; the panel, the other rows, a section title and the divider stay neutral, and a suffix or lock is muted, 12 px after the label. A command that cannot run stays in place with muted text, never dimmed, and says why in a muted line under its label, which a tap on a phone reads as well as a pointer, since a tooltip opens for the mouse only; a destructive one is muted, not red. Every row is 36 px (44 on touch) with the pointer cursor, or the default one when it cannot be chosen, a row with a reason growing by its line, and a section title is a muted row of that height. The highlight is the row's fill alone: no text inside a row changes colour with it, and a row that cannot be chosen takes no highlight.
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: those are `ContextMenu` and `CommandDialog`; two related primary actions stand side by side as buttons. A record's or a page's commands are `ActionMenu` or `PageActions`' menu, from data. The account's rows are `AccountMenu`. These four draw their rows with `DropdownMenuCommand`; the `DropdownMenu` family is used directly only for a choice menu such as a sort, with `DropdownMenuLink` for a destination row. A value to choose in a form is `Select`.
15
+ * @behaviour "Dropdown menu opened via button. Supports typeahead and keyboard navigation." (https://vercel.com/geist/menu) "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`. A solid floating surface, 200 px wide at least, 10 px from its trigger. A labelled trigger may end in a chevron; an icon trigger has none. Safe commands come first, each with its icon, groups split by a divider, the destructive command last. Colour sits on that command alone: its text is the error colour at rest and its row takes the soft error fill when highlighted; the panel, the other rows, a section title and the divider stay neutral, and a suffix or lock is muted, 12 px after the label. A command that cannot run stays in place with muted text, never dimmed, and says why in a muted line under its label, which a tap on a phone reads as well as a pointer, since a tooltip opens for the mouse only; a destructive one is muted, not red. Every row, of any kind, is 36 px in the default comfortable density (44 on touch; the compact density, `density="compact"`, tightens the padding to about 28 px on a fine pointer, and no menu in the product uses it) with `{rounded.sm}` corners and the pointer cursor, or the default one when it cannot be chosen, a row with a reason growing by its line, and a section title is a muted row of that height. The highlight is the row's fill alone: no text inside a row changes colour with it, and a row that cannot be chosen takes no highlight. A submenu goes one level deep at most (`one-submenu-level`), and never holds a destructive 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) "Section headers (`MenuSection title`) are Title Case, 1–2 words (`Workspace`, `Recent Projects`)." (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, not Title Case: "Remove mailbox", never a bare "Delete"; a section title is sentence case too. Italian runs a third longer; rows wrap, never truncate.
17
17
  * @access "Up/Down arrows move focus through items, Home/End jump to first/last, Enter or Space activates." (https://vercel.com/geist/menu) "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: `role="menu"` named by its trigger, items `menuitem`. Unlike Geist, which skips disabled rows, arrows land on a command that cannot run so its reason is read; it is still never highlighted and never runs. A command's icon is hidden; the value it acts on and its reason are its description. `DropdownMenuCommand` requires its `icon`; a command that cannot run takes `disabledReason`, and one a person may not run is `locked` with its `reason`, so nothing is greyed without saying why.
18
18
  */
@@ -61,9 +61,9 @@ export type EmptyStateKind<K extends EmptyStateProps["kind"]> = Omit<Extract<Emp
61
61
  * @family Feedback
62
62
  * @when "Fill spaces when no content has been added yet, or is temporarily empty due to the nature of the feature and should be designed to prevent confusion." (https://vercel.com/geist/empty-state) "A card used to communicate an error state with a title and message." (https://vercel.com/geist/error-card) "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) "Render the permission and tier-denial variants full-page when the user lands on a route they can’t view. Use a `Note` only when one tile inside an otherwise-accessible page is gated." (https://vercel.com/geist/empty-state) "Use the Error component as a block surface when a section or page-level resource failed to load: a panel, a dashboard card, a route boundary." (https://vercel.com/geist/error) Ours: pick the `kind` by the cause. `firstUse` is the blank slate and the informational variant: no record was ever made. `nothingYet`: empty now and it fills by itself. `noResults`: the search or filter found nothing. `cleared`: the work is done. `denied`: this viewer's role or plan does not open it. `failed`: the read failed; it is the Error and the Error Card, a failure inside a card with `scope="card"` and one that stands alone as a block with `page` or `region`. There is no educational kind.
63
63
  * @instead "Don’t put critical persistent warnings here. Empty states vanish when the list populates; persistent warnings belong in `Note` or the page header." (https://vercel.com/geist/empty-state) "Pick `toasts.error()` for transient action failures (`Couldn’t save settings. Try again.`) and the `error` prop on `Input` for field-level validation. Don’t replace either with this block." (https://vercel.com/geist/error) Ours: `Note` is `MessageNotice` or `NoticeBanner`, `toasts.error()` is `showMessageToast` with the tone `error`, and the `error` prop on `Input` is `FieldError`. Rows still loading are skeleton rows. A failure of one record's action is that record's row message. One gated tile on an open page is a `MessageNotice`, so `denied` takes `page` or `region`, never `card`.
64
- * @behaviour "The CTA must be a real `Button` or `Link`, not an `onClick` div, so it joins the tab order and exposes a role." (https://vercel.com/geist/empty-state) "Cap at one primary CTA, plus one secondary when the first action could legitimately be one of two paths (`Import Repository` and `Deploy Template`). Three CTAs is a smell." (https://vercel.com/geist/empty-state) "Don’t auto-launch a tour from the educational variant; pair `Start Tour` with `Skip`." (https://vercel.com/geist/empty-state) "The recovery action must do something concrete: a `Try Again` button when the operation is retry-safe, a named verb (`Reconnect GitHub`, `Update Payment Method`) when it isn’t." (https://vercel.com/geist/error) "Don’t auto-retry in the background; the user came to this surface to decide." (https://vercel.com/geist/error) "For full-page route errors (`error.tsx`), return focus to the `Try Again` button on appearance so a keyboard user can retry without hunting for it." (https://vercel.com/geist/error) "Always pair platform or system errors with a stable identifier (request ID `x-vercel-id`, deployment ID `dpl_…`, run ID, trace ID). Validation and permission denials are user-state, not system, and don’t need an ID." (https://vercel.com/geist/error) "Render the stable ID on a monospace sub-line under a collapsed `<details>` so the user can copy-paste it into a support thread." (https://vercel.com/geist/error) Ours: `firstUse` has the one picture, one action and at most one docs link under it; there is no educational kind, so no tour. A failure shows at most two of its message's actions, Retry first, and moves focus to the first one when it fills a page (`scope="page"`); its `reference` is the collapsed Disclosure holding the monospace identifier and a copy button. A page or a region stands on a resting card, inside a card it takes none, and a collection always passes `card`; a card that lists a few items, as a collection's rail does, passes `line`, where `nothingYet` and `cleared` are one 44 px row like an item: the message at the left, after the cleared check at 16 px. Every kind that carries a title, `failed` excepted, draws it the same way: a mark or picture, a 16 px medium title, one or two muted 14 px lines, 24 px apart, centred, the lines no wider than 340 px. `cleared` and `denied` carry a bordered 54 px tile with a muted icon, never a hue; the picture is `firstUse`'s alone. The action is the filled primary button, as Vercel's Connect draws Create Connector in its empty card; the docs link is muted. A page or a region is padded 48 px above and below and 70 px at the sides (a first use narrows to 24 px under 640 px for its picture). `failed` is the one hued kind: on a page or a region its ground, line, mark and text are all in the error colour, with a 16 px regular title, 16 px padding and 8 px between its parts, and the buttons stay neutral; inside a card it takes the text and mark colour alone, because the card owns the edge and a second one would double it. Required: `firstUse` and `denied` take a title and a line, `firstUse` its picture, `failed` the catalogue message whose title is always drawn.
64
+ * @behaviour "The CTA must be a real `Button` or `Link`, not an `onClick` div, so it joins the tab order and exposes a role." (https://vercel.com/geist/empty-state) "Cap at one primary CTA, plus one secondary when the first action could legitimately be one of two paths (`Import Repository` and `Deploy Template`). Three CTAs is a smell." (https://vercel.com/geist/empty-state) "Don’t auto-launch a tour from the educational variant; pair `Start Tour` with `Skip`." (https://vercel.com/geist/empty-state) "The recovery action must do something concrete: a `Try Again` button when the operation is retry-safe, a named verb (`Reconnect GitHub`, `Update Payment Method`) when it isn’t." (https://vercel.com/geist/error) "Don’t auto-retry in the background; the user came to this surface to decide." (https://vercel.com/geist/error) "For full-page route errors (`error.tsx`), return focus to the `Try Again` button on appearance so a keyboard user can retry without hunting for it." (https://vercel.com/geist/error) "Always pair platform or system errors with a stable identifier (request ID `x-vercel-id`, deployment ID `dpl_…`, run ID, trace ID). Validation and permission denials are user-state, not system, and don’t need an ID." (https://vercel.com/geist/error) "Render the stable ID on a monospace sub-line under a collapsed `<details>` so the user can copy-paste it into a support thread." (https://vercel.com/geist/error) Ours: `firstUse` has the one picture, one action and at most one docs link under it; there is no educational kind, so no tour. A failure shows at most two of its message's actions, Retry first, and moves focus to the first one when it fills a page (`scope="page"`); its `reference` is the collapsed Disclosure holding the monospace identifier and a copy button. A page or a region stands on a resting card, inside a card it takes none, and a collection always passes `card`; a card that lists a few items, as a collection's rail does, passes `line`, where `nothingYet` and `cleared` are one 44 px row like an item: the message at the left, after the cleared check at 16 px. Every kind that carries a title, `failed` excepted, draws it the same way: a mark or picture, a 16 px medium title, one or two muted 14 px lines, 24 px apart, centred, the lines no wider than 340 px. `cleared` and `denied` carry a bordered 54 px tile with a muted icon, never a hue; the picture is `firstUse`'s alone. The action is the filled primary button, as Vercel's Connect draws Create Connector in its empty card; the docs link is muted. A page or a region is padded 48 px above and below and 70 px at the sides (a first use narrows to 24 px under 640 px for its picture). `failed` is the one hued kind: on a page or a region its ground, line, mark and text are all in the error colour, with a 16 px regular title, 16 px padding and 8 px between its parts, and the buttons stay neutral; inside a card it takes the text and mark colour alone, because the card owns the edge and a second one would double it. A first use's picture is 240 × 176 px on a page and 200 × 144 px in a region or a card. Required: `firstUse` and `denied` take a title and a line, `firstUse` its picture, `failed` the catalogue message whose title is always drawn.
65
65
  * @words "`title` is Title Case (`No Logs Match Your Filter`); `description` is sentence case and adds new information instead of restating the title." (https://vercel.com/geist/empty-state) Ours: a title is sentence case and names what is missing ("No mailboxes yet"), not Title Case; a quiet line is one sentence. "Quote a single typed query verbatim with curly quotes: `No logs match “${query}”. Clear the filter to see all logs.` For multi-facet filters use the plural template `No {Items} Match Your Filters` and suggest widening or clearing." (https://vercel.com/geist/empty-state) "Onboarding bodies name the next action that creates the first item: `Push to your Git repository to create your first one.` Tier-gated bodies follow `{Feature value} with the {Plan} plan.`" (https://vercel.com/geist/empty-state) "Error variant pairs the body with a copyable request ID and a `Try Again` button." (https://vercel.com/geist/empty-state) "CTA labels are Title Case `Verb + Noun`. Never `Get Started`, `Continue`, or `OK`." (https://vercel.com/geist/empty-state) Ours: an action label is sentence case, verb and noun ("Clear filters", "New Agent"), never "Get started" or "OK". "State what happened and what to do next, in that order. Cut apologetic preambles (`Unfortunately`, `Oops`, `We’re sorry`)." (https://vercel.com/geist/error) "Use `Couldn’t` or `Can’t` for user-state errors (`Couldn’t verify your passkey. Try again.`); use `Failed to` for system or infra errors that mirror CLI output (`Build failed. Bundle exceeds 50 MB.`). `Unable to` is banned." (https://vercel.com/geist/error) "Don’t fall back to `Something Went Wrong` as a title; name the resource that failed (`Couldn’t Load Page`, `Couldn’t Load Deployments`)." (https://vercel.com/geist/error) "Never humor an error. Users hitting an error are frustrated; insincere copy makes it worse." (https://vercel.com/geist/error) Ours: a failure is the catalogue's message, never a string of the component's own, and its title names what failed to load.
66
- * @access "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) "When the error appears asynchronously (after a failed fetch), wrap the region in `aria-live="polite"` so it’s announced. Reserve `aria-live="assertive"` for true blocking errors that interrupt input." (https://vercel.com/geist/error) Ours: a title, a failure's included, is a heading, level 2 or, inside a titled section, 3. The picture is decorative. A failure's message is a `role="status"` line, polite, never an assertive alert, because it arrives after a read, not in the middle of input. `nothingYet`, `noResults` and `cleared` are plain lines with no live role of their own: the wrapper that stays mounted while rows and absence swap (the `aria-live="polite"` region, such as `SkeletonRegion`) announces them, once.
66
+ * @access "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) "When the error appears asynchronously (after a failed fetch), wrap the region in `aria-live="polite"` so it’s announced. Reserve `aria-live="assertive"` for true blocking errors that interrupt input." (https://vercel.com/geist/error) Ours: a title, a failure's included, is a heading, level 2 or, inside a titled section, 3. The picture is decorative. A failure's message is a `role="status"` line, polite, never an assertive alert, because it arrives after a read, not in the middle of input. `nothingYet`, `noResults` and `cleared` are plain lines with no live role of their own: the wrapper that stays mounted while rows and absence swap (the `aria-live="polite"` region, such as `SkeletonRegion`) announces them, once. Beside a table, an absence stands outside the semantic table body, never as a row of it, in that same wrapper.
67
67
  */
68
68
  export declare function EmptyState(props: EmptyStateProps): import("react").JSX.Element;
69
69
  //# sourceMappingURL=empty-state.d.ts.map
@@ -14,9 +14,9 @@ import { bodyBeyondTitle } from "./product-message.js";
14
14
  * @family Feedback
15
15
  * @when "Fill spaces when no content has been added yet, or is temporarily empty due to the nature of the feature and should be designed to prevent confusion." (https://vercel.com/geist/empty-state) "A card used to communicate an error state with a title and message." (https://vercel.com/geist/error-card) "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) "Render the permission and tier-denial variants full-page when the user lands on a route they can’t view. Use a `Note` only when one tile inside an otherwise-accessible page is gated." (https://vercel.com/geist/empty-state) "Use the Error component as a block surface when a section or page-level resource failed to load: a panel, a dashboard card, a route boundary." (https://vercel.com/geist/error) Ours: pick the `kind` by the cause. `firstUse` is the blank slate and the informational variant: no record was ever made. `nothingYet`: empty now and it fills by itself. `noResults`: the search or filter found nothing. `cleared`: the work is done. `denied`: this viewer's role or plan does not open it. `failed`: the read failed; it is the Error and the Error Card, a failure inside a card with `scope="card"` and one that stands alone as a block with `page` or `region`. There is no educational kind.
16
16
  * @instead "Don’t put critical persistent warnings here. Empty states vanish when the list populates; persistent warnings belong in `Note` or the page header." (https://vercel.com/geist/empty-state) "Pick `toasts.error()` for transient action failures (`Couldn’t save settings. Try again.`) and the `error` prop on `Input` for field-level validation. Don’t replace either with this block." (https://vercel.com/geist/error) Ours: `Note` is `MessageNotice` or `NoticeBanner`, `toasts.error()` is `showMessageToast` with the tone `error`, and the `error` prop on `Input` is `FieldError`. Rows still loading are skeleton rows. A failure of one record's action is that record's row message. One gated tile on an open page is a `MessageNotice`, so `denied` takes `page` or `region`, never `card`.
17
- * @behaviour "The CTA must be a real `Button` or `Link`, not an `onClick` div, so it joins the tab order and exposes a role." (https://vercel.com/geist/empty-state) "Cap at one primary CTA, plus one secondary when the first action could legitimately be one of two paths (`Import Repository` and `Deploy Template`). Three CTAs is a smell." (https://vercel.com/geist/empty-state) "Don’t auto-launch a tour from the educational variant; pair `Start Tour` with `Skip`." (https://vercel.com/geist/empty-state) "The recovery action must do something concrete: a `Try Again` button when the operation is retry-safe, a named verb (`Reconnect GitHub`, `Update Payment Method`) when it isn’t." (https://vercel.com/geist/error) "Don’t auto-retry in the background; the user came to this surface to decide." (https://vercel.com/geist/error) "For full-page route errors (`error.tsx`), return focus to the `Try Again` button on appearance so a keyboard user can retry without hunting for it." (https://vercel.com/geist/error) "Always pair platform or system errors with a stable identifier (request ID `x-vercel-id`, deployment ID `dpl_…`, run ID, trace ID). Validation and permission denials are user-state, not system, and don’t need an ID." (https://vercel.com/geist/error) "Render the stable ID on a monospace sub-line under a collapsed `<details>` so the user can copy-paste it into a support thread." (https://vercel.com/geist/error) Ours: `firstUse` has the one picture, one action and at most one docs link under it; there is no educational kind, so no tour. A failure shows at most two of its message's actions, Retry first, and moves focus to the first one when it fills a page (`scope="page"`); its `reference` is the collapsed Disclosure holding the monospace identifier and a copy button. A page or a region stands on a resting card, inside a card it takes none, and a collection always passes `card`; a card that lists a few items, as a collection's rail does, passes `line`, where `nothingYet` and `cleared` are one 44 px row like an item: the message at the left, after the cleared check at 16 px. Every kind that carries a title, `failed` excepted, draws it the same way: a mark or picture, a 16 px medium title, one or two muted 14 px lines, 24 px apart, centred, the lines no wider than 340 px. `cleared` and `denied` carry a bordered 54 px tile with a muted icon, never a hue; the picture is `firstUse`'s alone. The action is the filled primary button, as Vercel's Connect draws Create Connector in its empty card; the docs link is muted. A page or a region is padded 48 px above and below and 70 px at the sides (a first use narrows to 24 px under 640 px for its picture). `failed` is the one hued kind: on a page or a region its ground, line, mark and text are all in the error colour, with a 16 px regular title, 16 px padding and 8 px between its parts, and the buttons stay neutral; inside a card it takes the text and mark colour alone, because the card owns the edge and a second one would double it. Required: `firstUse` and `denied` take a title and a line, `firstUse` its picture, `failed` the catalogue message whose title is always drawn.
17
+ * @behaviour "The CTA must be a real `Button` or `Link`, not an `onClick` div, so it joins the tab order and exposes a role." (https://vercel.com/geist/empty-state) "Cap at one primary CTA, plus one secondary when the first action could legitimately be one of two paths (`Import Repository` and `Deploy Template`). Three CTAs is a smell." (https://vercel.com/geist/empty-state) "Don’t auto-launch a tour from the educational variant; pair `Start Tour` with `Skip`." (https://vercel.com/geist/empty-state) "The recovery action must do something concrete: a `Try Again` button when the operation is retry-safe, a named verb (`Reconnect GitHub`, `Update Payment Method`) when it isn’t." (https://vercel.com/geist/error) "Don’t auto-retry in the background; the user came to this surface to decide." (https://vercel.com/geist/error) "For full-page route errors (`error.tsx`), return focus to the `Try Again` button on appearance so a keyboard user can retry without hunting for it." (https://vercel.com/geist/error) "Always pair platform or system errors with a stable identifier (request ID `x-vercel-id`, deployment ID `dpl_…`, run ID, trace ID). Validation and permission denials are user-state, not system, and don’t need an ID." (https://vercel.com/geist/error) "Render the stable ID on a monospace sub-line under a collapsed `<details>` so the user can copy-paste it into a support thread." (https://vercel.com/geist/error) Ours: `firstUse` has the one picture, one action and at most one docs link under it; there is no educational kind, so no tour. A failure shows at most two of its message's actions, Retry first, and moves focus to the first one when it fills a page (`scope="page"`); its `reference` is the collapsed Disclosure holding the monospace identifier and a copy button. A page or a region stands on a resting card, inside a card it takes none, and a collection always passes `card`; a card that lists a few items, as a collection's rail does, passes `line`, where `nothingYet` and `cleared` are one 44 px row like an item: the message at the left, after the cleared check at 16 px. Every kind that carries a title, `failed` excepted, draws it the same way: a mark or picture, a 16 px medium title, one or two muted 14 px lines, 24 px apart, centred, the lines no wider than 340 px. `cleared` and `denied` carry a bordered 54 px tile with a muted icon, never a hue; the picture is `firstUse`'s alone. The action is the filled primary button, as Vercel's Connect draws Create Connector in its empty card; the docs link is muted. A page or a region is padded 48 px above and below and 70 px at the sides (a first use narrows to 24 px under 640 px for its picture). `failed` is the one hued kind: on a page or a region its ground, line, mark and text are all in the error colour, with a 16 px regular title, 16 px padding and 8 px between its parts, and the buttons stay neutral; inside a card it takes the text and mark colour alone, because the card owns the edge and a second one would double it. A first use's picture is 240 × 176 px on a page and 200 × 144 px in a region or a card. Required: `firstUse` and `denied` take a title and a line, `firstUse` its picture, `failed` the catalogue message whose title is always drawn.
18
18
  * @words "`title` is Title Case (`No Logs Match Your Filter`); `description` is sentence case and adds new information instead of restating the title." (https://vercel.com/geist/empty-state) Ours: a title is sentence case and names what is missing ("No mailboxes yet"), not Title Case; a quiet line is one sentence. "Quote a single typed query verbatim with curly quotes: `No logs match “${query}”. Clear the filter to see all logs.` For multi-facet filters use the plural template `No {Items} Match Your Filters` and suggest widening or clearing." (https://vercel.com/geist/empty-state) "Onboarding bodies name the next action that creates the first item: `Push to your Git repository to create your first one.` Tier-gated bodies follow `{Feature value} with the {Plan} plan.`" (https://vercel.com/geist/empty-state) "Error variant pairs the body with a copyable request ID and a `Try Again` button." (https://vercel.com/geist/empty-state) "CTA labels are Title Case `Verb + Noun`. Never `Get Started`, `Continue`, or `OK`." (https://vercel.com/geist/empty-state) Ours: an action label is sentence case, verb and noun ("Clear filters", "New Agent"), never "Get started" or "OK". "State what happened and what to do next, in that order. Cut apologetic preambles (`Unfortunately`, `Oops`, `We’re sorry`)." (https://vercel.com/geist/error) "Use `Couldn’t` or `Can’t` for user-state errors (`Couldn’t verify your passkey. Try again.`); use `Failed to` for system or infra errors that mirror CLI output (`Build failed. Bundle exceeds 50 MB.`). `Unable to` is banned." (https://vercel.com/geist/error) "Don’t fall back to `Something Went Wrong` as a title; name the resource that failed (`Couldn’t Load Page`, `Couldn’t Load Deployments`)." (https://vercel.com/geist/error) "Never humor an error. Users hitting an error are frustrated; insincere copy makes it worse." (https://vercel.com/geist/error) Ours: a failure is the catalogue's message, never a string of the component's own, and its title names what failed to load.
19
- * @access "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) "When the error appears asynchronously (after a failed fetch), wrap the region in `aria-live="polite"` so it’s announced. Reserve `aria-live="assertive"` for true blocking errors that interrupt input." (https://vercel.com/geist/error) Ours: a title, a failure's included, is a heading, level 2 or, inside a titled section, 3. The picture is decorative. A failure's message is a `role="status"` line, polite, never an assertive alert, because it arrives after a read, not in the middle of input. `nothingYet`, `noResults` and `cleared` are plain lines with no live role of their own: the wrapper that stays mounted while rows and absence swap (the `aria-live="polite"` region, such as `SkeletonRegion`) announces them, once.
19
+ * @access "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) "When the error appears asynchronously (after a failed fetch), wrap the region in `aria-live="polite"` so it’s announced. Reserve `aria-live="assertive"` for true blocking errors that interrupt input." (https://vercel.com/geist/error) Ours: a title, a failure's included, is a heading, level 2 or, inside a titled section, 3. The picture is decorative. A failure's message is a `role="status"` line, polite, never an assertive alert, because it arrives after a read, not in the middle of input. `nothingYet`, `noResults` and `cleared` are plain lines with no live role of their own: the wrapper that stays mounted while rows and absence swap (the `aria-live="polite"` region, such as `SkeletonRegion`) announces them, once. Beside a table, an absence stands outside the semantic table body, never as a row of it, in that same wrapper.
20
20
  */
21
21
  export function EmptyState(props) {
22
22
  const scope = props.scope ?? "region";
@@ -42,6 +42,10 @@ declare const fieldVariants: (props?: ({
42
42
  * "The click target already extends to the label. Don’t override the `<label>`/`htmlFor` association with a custom wrapper that breaks the click region." (https://vercel.com/geist/checkbox)
43
43
  * "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox)
44
44
  * Ours: a disabled field says why in the card's footer, never in a tooltip around the control.
45
+ * `Field` only lays the parts out; the caller connects the real validation to the control, the help
46
+ * and the error, with the field owner that matches the product's form engine (`SettingsField`
47
+ * inside a settings section), and the values survive a recoverable failure. Visual styling never
48
+ * changes the form engine.
45
49
  * @words
46
50
  * "Labels are short Title Case nouns: `Project Name`, `Domain`, `Environment Variable Name`." (https://vercel.com/geist/input)
47
51
  * Ours: sentence case, a short noun (*Display name*); a field that may stay empty says so in its
@@ -1 +1 @@
1
- {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../src/components/field.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,+BAW1E;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAkB,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAAE,+BAYnE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWvE;AAED,QAAA,MAAM,aAAa;;8EAajB,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,+BAUlE;AAKD,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWzE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,KAAK,CAAC,+BAcvF;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWvE;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,+BAa3E;AAED,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,+BAsBA;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IACjD,+EAA+E;IAC/E,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,sCAiDA;AAED,OAAO,EACL,KAAK,EACL,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,UAAU,GACX,CAAC"}
1
+ {"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../src/components/field.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAG3C,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,+BAW1E;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAkB,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;CAAE,+BAYnE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWvE;AAED,QAAA,MAAM,aAAa;;8EAajB,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,WAAwB,EACxB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,+BAUlE;AAKD,iBAAS,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWzE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,KAAK,CAAC,+BAcvF;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAWvE;AAED,iBAAS,gBAAgB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,+BAa3E;AAED,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,+BAsBA;AAED,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IACjD,+EAA+E;IAC/E,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,sCAiDA;AAED,OAAO,EACL,KAAK,EACL,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,UAAU,GACX,CAAC"}
@@ -61,6 +61,10 @@ const fieldVariants = cva("group/field flex w-full gap-2", {
61
61
  * "The click target already extends to the label. Don’t override the `<label>`/`htmlFor` association with a custom wrapper that breaks the click region." (https://vercel.com/geist/checkbox)
62
62
  * "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox)
63
63
  * Ours: a disabled field says why in the card's footer, never in a tooltip around the control.
64
+ * `Field` only lays the parts out; the caller connects the real validation to the control, the help
65
+ * and the error, with the field owner that matches the product's form engine (`SettingsField`
66
+ * inside a settings section), and the values survive a recoverable failure. Visual styling never
67
+ * changes the form engine.
64
68
  * @words
65
69
  * "Labels are short Title Case nouns: `Project Name`, `Domain`, `Environment Variable Name`." (https://vercel.com/geist/input)
66
70
  * Ours: sentence case, a short noun (*Display name*); a field that may stay empty says so in its
@@ -12,9 +12,12 @@ interface FileDiffProps extends Omit<React.ComponentProps<"div">, "children"> {
12
12
  *
13
13
  * @family Data
14
14
  * @when Showing what changed in a file an Agent edited, or in a configuration before it is saved.
15
- * @instead A file as it stands is `CodeBlock`. A count of changed lines is `DiffCount`.
15
+ * @instead A file as it stands is `CodeBlock`. A count of changed lines is `DiffCount`. It is not a
16
+ * general code editor or a JSON viewer.
16
17
  * @behaviour Added lines on the success fill with a plus, removed on the destructive fill with a
17
- * true minus; unchanged lines beyond `context` fold into one marker.
18
+ * true minus; unchanged lines beyond `context` fold into one marker. The source is shown exactly as
19
+ * given, whitespace kept. It names no file: the conversation or tool that owns the change stays the
20
+ * owner and names it.
18
21
  * @words The added and removed labels and the folded-lines count come from the product's catalogue.
19
22
  * @access Each changed line carries its added or removed label in screen-reader text; the plus and
20
23
  * minus marks are hidden.
@@ -1 +1 @@
1
- {"version":3,"file":"file-diff.d.ts","sourceRoot":"","sources":["../../src/components/file-diff.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1C;AAYD;;;;;;;;;;;GAWG;AACH,iBAAS,QAAQ,CAAC,EAChB,UAAoB,EACpB,KAAK,EACL,MAAM,EACN,SAAS,EACT,OAAW,EACX,YAAwB,EACxB,YAAoD,EACpD,GAAG,KAAK,EACT,EAAE,aAAa,+BAkCf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"file-diff.d.ts","sourceRoot":"","sources":["../../src/components/file-diff.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAc,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1C;AAYD;;;;;;;;;;;;;;GAcG;AACH,iBAAS,QAAQ,CAAC,EAChB,UAAoB,EACpB,KAAK,EACL,MAAM,EACN,SAAS,EACT,OAAW,EACX,YAAwB,EACxB,YAAoD,EACpD,GAAG,KAAK,EACT,EAAE,aAAa,+BAkCf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -16,9 +16,12 @@ const MARK = {
16
16
  *
17
17
  * @family Data
18
18
  * @when Showing what changed in a file an Agent edited, or in a configuration before it is saved.
19
- * @instead A file as it stands is `CodeBlock`. A count of changed lines is `DiffCount`.
19
+ * @instead A file as it stands is `CodeBlock`. A count of changed lines is `DiffCount`. It is not a
20
+ * general code editor or a JSON viewer.
20
21
  * @behaviour Added lines on the success fill with a plus, removed on the destructive fill with a
21
- * true minus; unchanged lines beyond `context` fold into one marker.
22
+ * true minus; unchanged lines beyond `context` fold into one marker. The source is shown exactly as
23
+ * given, whitespace kept. It names no file: the conversation or tool that owns the change stays the
24
+ * owner and names it.
22
25
  * @words The added and removed labels and the folded-lines count come from the product's catalogue.
23
26
  * @access Each changed line carries its added or removed label in screen-reader text; the plus and
24
27
  * minus marks are hidden.
@@ -10,7 +10,7 @@ export type FormDialogProps = FormSurfaceProps & {
10
10
  * @family Compositions
11
11
  * @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
12
12
  * @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
13
- * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
13
+ * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
14
14
  * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
15
15
  * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
16
16
  */
@@ -11,7 +11,7 @@ import { guardUnsaved } from "../internal/unsaved-guard.js";
11
11
  * @family Compositions
12
12
  * @when "Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use `Sheet` on desktop or `Drawer` on mobile." (https://vercel.com/geist/modal) Ours: a person adds a record through a few fields, or changes one or two values a command asks for: new customer, add a mailbox, add an MCP server.
13
13
  * @instead "Skip Modal for routine create flows that have a dedicated page; route to the page instead." (https://vercel.com/geist/modal) "Confirm destructive actions in a Modal. `Drawer` and `Sheet` don’t fully dim the page, so they read as too soft for a delete or revoke." (https://vercel.com/geist/modal) Ours: a record already in a list edits in its row with `RowEditForm`; a choice from a catalogue is a `CatalogDrawer`; a setup in steps with a wait is a `FormDrawer` with `job="steps"`; a consequence is confirmed in a `ConfirmDialog`.
14
- * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
14
+ * @behaviour "Allow Escape and outside-click to dismiss non-destructive Modals; gate dismissal on destructive ones with unsaved input." (https://vercel.com/geist/modal) Ours: centred over a scrim without blur, 540 px wide, a bottom sheet on a phone: the title and its help, the fields in a 12 px column, then the footer, which stays at the bottom while a tall form scrolls, with Cancel at the leading edge and the primary at the trailing edge, in one row also on a phone. `FormDialogForm` puts the fields in the dialog's own scroll body and the actions in its fixed footer; no other overlay is nested inside. A refusal or a failed save sits above the footer and the fields keep what was typed. While its save runs it holds open, Cancel and the primary hold, and the waiting line runs under them. With `unsaved.dirty`, Escape and a press outside are held back and `unsaved.onDismissBlocked` runs so the caller can ask; Close and Cancel always close.
15
15
  * @words "`Modal.Title` is a Title Case statement, never a question. `Transfer Project` is correct; `Transfer Project?` is wrong." (https://vercel.com/geist/modal) "Primary button is `Verb + Noun` and matches the title verb (`Transfer Project` title pairs with `Transfer Project` button). Never `Confirm`, `OK`, or a bare verb on a destructive primary." (https://vercel.com/geist/modal) "Cancel literal stays `Cancel`. Acknowledgment-only Modals (after a key reveal, after a one-time-show) use `Done`, never `OK` or `Close`." (https://vercel.com/geist/modal) Ours: the title and the primary are sentence case, where Geist writes Title Case: the title names the job and its object, "New customer", "Add a mailbox"; the primary repeats it, "Create customer", "Add mailbox".
16
16
  * @access "Set `aria-labelledby` to the `Modal.Title` id so screen readers announce the title on open." (https://vercel.com/geist/modal) "Trap focus inside the Modal while it’s open and return focus to the trigger after close. Restore body scroll on the same tick the Modal unmounts." (https://vercel.com/geist/modal) "After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger." (https://vercel.com/geist/modal) Ours: a modal dialog with a Close named by `closeLabel`; focus starts in its first field or `initialFocus` and returns to the opener or `finalFocus`. Escape and Close close it unless the save runs.
17
17
  */
@@ -42,7 +42,7 @@ export type FormDrawerProps = FormSurfaceProps & ({
42
42
  * @family Compositions
43
43
  * @when Ours: choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
44
44
  * @instead "Don’t use Sheet to confirm destructive actions. The default `modal=false` keeps the page interactive, which weakens severity for a delete or revoke." (https://vercel.com/geist/sheet) Ours: a new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`; a phone's short job is a `Drawer`.
45
- * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
45
+ * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3", in mono) over the title, which stays the job's name, then the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
46
46
  * @words "Title is Title Case and names the entity (`Deployment Details`, `Member Profile`), not the page action." (https://vercel.com/geist/sheet) "Body is read-mostly: sentence case prose with Title Case sub-headings. Action buttons are optional; when present, follow `Verb + Noun`." (https://vercel.com/geist/sheet) Ours: the title is sentence case and names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
47
47
  * @access "Trap focus inside the sheet while it’s open and return focus to the trigger row on close so keyboard users keep their place in the list." (https://vercel.com/geist/sheet) "Provide a visible close button labeled `Close` (or an icon button with `aria-label="Close"`) since clicking outside doesn’t dismiss." (https://vercel.com/geist/sheet) "Announce the sheet with `aria-labelledby` pointing at the title; pair it with `aria-describedby` only when the body is short and load-bearing." (https://vercel.com/geist/sheet) Ours: a modal dialog named by its title; focus returns to the opener on close, or to `finalFocus` when the opener is gone. The step is read before the title.
48
48
  */
@@ -12,7 +12,7 @@ import { cn } from "../lib/utils.js";
12
12
  * @family Compositions
13
13
  * @when Ours: choosing from a catalogue too long for a dialog (through `CatalogDrawer`), or setting something up in several steps with a wait: connect a messaging channel, Telegram's code.
14
14
  * @instead "Don’t use Sheet to confirm destructive actions. The default `modal=false` keeps the page interactive, which weakens severity for a delete or revoke." (https://vercel.com/geist/sheet) Ours: a new record from a few fields is a `FormDialog`; a record already in a list edits in its row with `RowEditForm`; a fact on the record's own page changes in place in its section; a consequence is confirmed in a `ConfirmDialog`; a phone's short job is a `Drawer`.
15
- * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3") over the title, the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
15
+ * @behaviour "Sheet defaults to `modal=false` so toasts and other high-z elements stay reachable. Keep that default unless the sheet owns the screen." (https://vercel.com/geist/sheet) "Pick `side` from the trigger location: a row inspector slides from `right`, a global filter from `left`. Don’t change sides mid-session." (https://vercel.com/geist/sheet) "Outside-click does not auto-close, so always render an explicit close affordance and honor Escape." (https://vercel.com/geist/sheet) Ours: a modal `Sheet` from the right edge over the scrim, because the drawer owns the screen, at the Sheet's one width that no caller sets. The header holds the step ("Step 2 of 3", in mono) over the title, which stays the job's name, then the description and Close; the body scrolls between the header and a footer that stays, with no fill or rule of its own, Cancel then the primary at its trailing edge. A press outside does not close it; Escape does, unless `unsaved.dirty` holds it back. Cancel holds while a save runs.
16
16
  * @words "Title is Title Case and names the entity (`Deployment Details`, `Member Profile`), not the page action." (https://vercel.com/geist/sheet) "Body is read-mostly: sentence case prose with Title Case sub-headings. Action buttons are optional; when present, follow `Verb + Noun`." (https://vercel.com/geist/sheet) Ours: the title is sentence case and names the job and its object: "Connect Telegram", "Add a skill". The step reads "Step N of M". The primary says what it does: "Connect", "Continue", never "OK".
17
17
  * @access "Trap focus inside the sheet while it’s open and return focus to the trigger row on close so keyboard users keep their place in the list." (https://vercel.com/geist/sheet) "Provide a visible close button labeled `Close` (or an icon button with `aria-label="Close"`) since clicking outside doesn’t dismiss." (https://vercel.com/geist/sheet) "Announce the sheet with `aria-labelledby` pointing at the title; pair it with `aria-describedby` only when the body is short and load-bearing." (https://vercel.com/geist/sheet) Ours: a modal dialog named by its title; focus returns to the opener on close, or to `finalFocus` when the opener is gone. The step is read before the title.
18
18
  */
@@ -29,21 +29,23 @@ type GaugeProps = Omit<Meter.Root.Props, "value" | "min" | "max" | "children" |
29
29
  *
30
30
  * @family Data
31
31
  * @when "A 0–100 ratio against a fixed maximum where the comparison is the point, like quota usage, build cache hit rate, uptime, or billing-period consumption." (https://vercel.com/geist/gauge)
32
- * Ours: `size` follows the weight of the figure beside it.
32
+ * Ours: one ratio out of 100 on Base UI `Meter`. `size` follows the weight of the figure beside it:
33
+ * `xs` (20 px), `sm` (32), `md` (64) and `lg` (128). The centre holds the number or an icon.
33
34
  * @instead "For determinate task progress with a known total (uploads, multi-step setup), use `Progress`." (https://vercel.com/geist/gauge)
34
35
  * "For binary or enumerated state, use `Status Dot` for deployments or `Badge` for everything else." (https://vercel.com/geist/gauge)
35
36
  * Ours: those are `StatusDot` and `StatusBadge`. A single figure on its own is a `KpiCard`. A wait
36
37
  * of unknown length is the waiting line; the gauge has no indeterminate form. Two shares of one
37
- * whole are a chart.
38
+ * whole are a chart: the gauge is a control for one ratio, never a chart.
38
39
  * @behaviour "Use `arc="equal"` for true ratios so 50% reads as exactly half." (https://vercel.com/geist/gauge)
39
40
  * "Use the default `primary` arc for single-percentage usage where the filled portion is the story." (https://vercel.com/geist/gauge)
40
41
  * "When using the gauge to display a ratio, use the `equal` arc priority to make both arcs are equally sized." (https://vercel.com/geist/gauge)
41
- * Ours: there is no `arc` prop; the gauge always draws the primary arc, from the top, clockwise,
42
- * with round ends and a small gap before the neutral track; at 0 or 100 there is no gap. Colour
43
- * sits on the arc alone: the track stays the neutral line colour, and the number and icon stay
44
- * neutral.
42
+ * Ours: there is no `arc` prop and so no two-arc `equal` ratio; the gauge always draws the primary
43
+ * arc, from the top, clockwise, with round ends and a small gap before the neutral track; at 0 or
44
+ * 100 there is no gap. Colour sits on the arc alone: the track stays the neutral line colour, and
45
+ * the number and icon stay neutral.
45
46
  * "Threshold colors should match the same numeric breakpoints used elsewhere in the product (`>=80%` warning, `>=95%` error). Don’t invent gauge-only thresholds." (https://vercel.com/geist/gauge)
46
- * Ours: `tone` is that threshold, never derived from the value.
47
+ * Ours: `tone` is that threshold, never derived from the value, and takes `Progress`'s tones; there is
48
+ * no `colors` map.
47
49
  * "Pair `indeterminate` with explanatory copy nearby (`Calculating usage…`) so the user knows the value is loading, not zero." (https://vercel.com/geist/gauge)
48
50
  * Ours: there is no `indeterminate`; a value still loading is the waiting line. The smallest size
49
51
  * has room only for an icon. The arc moves on `open`, still under reduced motion.
@@ -1 +1 @@
1
- {"version":3,"file":"gauge.d.ts","sourceRoot":"","sources":["../../src/components/gauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,KAAK,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3C,KAAK,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAkC/C,KAAK,SAAS,GACV;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,KAAK,CAAA;CAAE,GACnD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAExD,KAAK,SAAS,GACV;IAAE,IAAI,CAAC,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5D;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC;AAErE,KAAK,UAAU,GAAG,IAAI,CACpB,KAAK,CAAC,IAAI,CAAC,KAAK,EAChB,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,iBAAiB,CACxE,GAAG;IACF,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,GAAG,SAAS,GACX,SAAS,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,KAAK,EACL,IAAgB,EAChB,IAAW,EACX,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,UAAU,+BAuEZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"gauge.d.ts","sourceRoot":"","sources":["../../src/components/gauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,KAAK,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3C,KAAK,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAkC/C,KAAK,SAAS,GACV;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,KAAK,CAAA;CAAE,GACnD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAExD,KAAK,SAAS,GACV;IAAE,IAAI,CAAC,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAC5D;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC;AAErE,KAAK,UAAU,GAAG,IAAI,CACpB,KAAK,CAAC,IAAI,CAAC,KAAK,EAChB,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,iBAAiB,CACxE,GAAG;IACF,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB,GAAG,SAAS,GACX,SAAS,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,KAAK,EACL,IAAgB,EAChB,IAAW,EACX,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,UAAU,+BAuEZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -33,21 +33,23 @@ const GAUGE_ARC_MOTION = "transition-[stroke-dasharray,stroke-dashoffset,stroke]
33
33
  *
34
34
  * @family Data
35
35
  * @when "A 0–100 ratio against a fixed maximum where the comparison is the point, like quota usage, build cache hit rate, uptime, or billing-period consumption." (https://vercel.com/geist/gauge)
36
- * Ours: `size` follows the weight of the figure beside it.
36
+ * Ours: one ratio out of 100 on Base UI `Meter`. `size` follows the weight of the figure beside it:
37
+ * `xs` (20 px), `sm` (32), `md` (64) and `lg` (128). The centre holds the number or an icon.
37
38
  * @instead "For determinate task progress with a known total (uploads, multi-step setup), use `Progress`." (https://vercel.com/geist/gauge)
38
39
  * "For binary or enumerated state, use `Status Dot` for deployments or `Badge` for everything else." (https://vercel.com/geist/gauge)
39
40
  * Ours: those are `StatusDot` and `StatusBadge`. A single figure on its own is a `KpiCard`. A wait
40
41
  * of unknown length is the waiting line; the gauge has no indeterminate form. Two shares of one
41
- * whole are a chart.
42
+ * whole are a chart: the gauge is a control for one ratio, never a chart.
42
43
  * @behaviour "Use `arc="equal"` for true ratios so 50% reads as exactly half." (https://vercel.com/geist/gauge)
43
44
  * "Use the default `primary` arc for single-percentage usage where the filled portion is the story." (https://vercel.com/geist/gauge)
44
45
  * "When using the gauge to display a ratio, use the `equal` arc priority to make both arcs are equally sized." (https://vercel.com/geist/gauge)
45
- * Ours: there is no `arc` prop; the gauge always draws the primary arc, from the top, clockwise,
46
- * with round ends and a small gap before the neutral track; at 0 or 100 there is no gap. Colour
47
- * sits on the arc alone: the track stays the neutral line colour, and the number and icon stay
48
- * neutral.
46
+ * Ours: there is no `arc` prop and so no two-arc `equal` ratio; the gauge always draws the primary
47
+ * arc, from the top, clockwise, with round ends and a small gap before the neutral track; at 0 or
48
+ * 100 there is no gap. Colour sits on the arc alone: the track stays the neutral line colour, and
49
+ * the number and icon stay neutral.
49
50
  * "Threshold colors should match the same numeric breakpoints used elsewhere in the product (`>=80%` warning, `>=95%` error). Don’t invent gauge-only thresholds." (https://vercel.com/geist/gauge)
50
- * Ours: `tone` is that threshold, never derived from the value.
51
+ * Ours: `tone` is that threshold, never derived from the value, and takes `Progress`'s tones; there is
52
+ * no `colors` map.
51
53
  * "Pair `indeterminate` with explanatory copy nearby (`Calculating usage…`) so the user knows the value is loading, not zero." (https://vercel.com/geist/gauge)
52
54
  * Ours: there is no `indeterminate`; a value still loading is the waiting line. The smallest size
53
55
  * has room only for an icon. The arc moves on `open`, still under reduced motion.
@@ -22,8 +22,11 @@ import type { PresentContent } from "../internal/present-content.js";
22
22
  * menu and belongs in `Menu`." "Use `align` to position the card at the start, center, or end of the
23
23
  * trigger." "Use `render` to set the trigger as a custom element, such as a link, button, or badge."
24
24
  * (https://vercel.com/geist/context-card)
25
- * Ours: the card stays open while the pointer is on it and opens above by default with a stem
26
- * pointing at the trigger. `HoverCardContent` requires its facts as children. Colour: one neutral
25
+ * Ours: the parts are `HoverCard`, `HoverCardTrigger`, `HoverCardContent` and `HoverCardSummary`.
26
+ * The card opens above by default, 150 ms after the pointer or focus arrives (`delay` on
27
+ * `HoverCardTrigger`), stays open while the pointer is on it. `HoverCardContent` requires its facts as children. A `HoverCardSummary` is the entity's
28
+ * name, one identifying line, two to four label and value facts, and at most one link, which takes
29
+ * the product's router link through `render`. Colour: one neutral
27
30
  * surface with no hue; the only accent a card carries is its link, in the outline button.
28
31
  * @words "Lead with the entity name as a Title Case heading and one identifying line in sentence
29
32
  * case underneath (team slug, owner, deployment URL)." "Follow with 2–4 metadata rows of `Label:
@@ -1 +1 @@
1
- {"version":3,"file":"hover-card.d.ts","sourceRoot":"","sources":["../../src/components/hover-card.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGlF,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAMjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,iBAAS,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,IAAI,CAAC,KAAK,+BAE/D;AAED,iBAAS,gBAAgB,CAAC,EACxB,KAAwB,EACxB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,+BAEpC;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,IAAY,EACZ,UAAe,EACf,KAAgB,EAChB,WAAe,EACf,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GACjC,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,GAAG;IAC7F,kEAAkE;IAClE,QAAQ,EAAE,cAAc,CAAC;CAC1B,+BAyBF;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,KAAK,cAAc,GACf,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,GACvC,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,GACtD,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAE1E,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAClF,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,KAAK,EAAE,cAAc,CAAC;IACtB,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CAC9E,CAAC;AAEF;;;GAGG;AACH,iBAAS,gBAAgB,CAAC,EACxB,IAAI,EACJ,MAAM,EACN,KAAK,EACL,YAAY,EACZ,MAAM,EACN,SAAS,EACT,GAAG,KAAK,EACT,EAAE,qBAAqB,+BA8BvB;AAED,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"hover-card.d.ts","sourceRoot":"","sources":["../../src/components/hover-card.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGlF,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAMjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,iBAAS,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,CAAC,IAAI,CAAC,KAAK,+BAE/D;AAED,iBAAS,gBAAgB,CAAC,EACxB,KAAwB,EACxB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,+BAEpC;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,IAAY,EACZ,UAAe,EACf,KAAgB,EAChB,WAAe,EACf,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GACjC,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,GAAG;IAC7F,kEAAkE;IAClE,QAAQ,EAAE,cAAc,CAAC;CAC1B,+BAyBF;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,iGAAiG;IACjG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,KAAK,cAAc,GACf,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,GACvC,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,GACtD,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAE1E,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,GAAG;IAClF,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,KAAK,EAAE,cAAc,CAAC;IACtB,4FAA4F;IAC5F,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAA;KAAE,CAAC;CAC9E,CAAC;AAEF;;;GAGG;AACH,iBAAS,gBAAgB,CAAC,EACxB,IAAI,EACJ,MAAM,EACN,KAAK,EACL,YAAY,EACZ,MAAM,EACN,SAAS,EACT,GAAG,KAAK,EACT,EAAE,qBAAqB,+BA8BvB;AAED,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
@@ -28,8 +28,11 @@ const HOVER_CARD_DELAY = 150;
28
28
  * menu and belongs in `Menu`." "Use `align` to position the card at the start, center, or end of the
29
29
  * trigger." "Use `render` to set the trigger as a custom element, such as a link, button, or badge."
30
30
  * (https://vercel.com/geist/context-card)
31
- * Ours: the card stays open while the pointer is on it and opens above by default with a stem
32
- * pointing at the trigger. `HoverCardContent` requires its facts as children. Colour: one neutral
31
+ * Ours: the parts are `HoverCard`, `HoverCardTrigger`, `HoverCardContent` and `HoverCardSummary`.
32
+ * The card opens above by default, 150 ms after the pointer or focus arrives (`delay` on
33
+ * `HoverCardTrigger`), stays open while the pointer is on it. `HoverCardContent` requires its facts as children. A `HoverCardSummary` is the entity's
34
+ * name, one identifying line, two to four label and value facts, and at most one link, which takes
35
+ * the product's router link through `render`. Colour: one neutral
33
36
  * surface with no hue; the only accent a card carries is its link, in the outline button.
34
37
  * @words "Lead with the entity name as a Title Case heading and one identifying line in sentence
35
38
  * case underneath (team slug, owner, deployment URL)." "Follow with 2–4 metadata rows of `Label:
@@ -52,10 +52,10 @@ export type IdentityMarkProps = {
52
52
  * company's initials, a person's picture, or a record kind's icon on its tile.
53
53
  *
54
54
  * @family Status
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): wherever it tells a person which thing they are looking at.
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.
56
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`.
57
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her orb from the orb engine, 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 on the white tile; a company is its logo: the one white ink Sofia kept from its site on a black tile in both themes, as the company's card stamps it, or a square SVG icon in its own colours filling the tile, as Vercel shows a project's favicon; its two initials on the ringed card tile until a logo is found, or when the stored logo does not load; a person is their picture, then their initials; 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 navigation icon, on the purple ground for a skill and the blue one for a plugin.
58
- * @words None of its own: the record's name stands beside it. Initials are the first letters of the name's first two words.
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 company is its logo: the one white ink Sofia kept from its site on a black tile (`{colors.identity-ink}`) in both themes, as the company's card stamps it, or a square SVG icon in its own colours filling the tile, as Vercel shows a project's favicon; its two initials on the ringed card tile until a logo is found, or when the stored logo does not load; 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 or 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, and no other kind takes letters.
59
59
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
60
60
  */
61
61
  export declare function IdentityMark(props: IdentityMarkProps): ReactNode;
@@ -64,10 +64,10 @@ function Tile({ kind, label, size, tone, children, }) {
64
64
  * company's initials, a person's picture, or a record kind's icon on its tile.
65
65
  *
66
66
  * @family Status
67
- * @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): wherever it tells a person which thing they are looking at.
67
+ * @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.
68
68
  * @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`.
69
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her orb from the orb engine, 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 on the white tile; a company is its logo: the one white ink Sofia kept from its site on a black tile in both themes, as the company's card stamps it, or a square SVG icon in its own colours filling the tile, as Vercel shows a project's favicon; its two initials on the ringed card tile until a logo is found, or when the stored logo does not load; a person is their picture, then their initials; 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 navigation icon, on the purple ground for a skill and the blue one for a plugin.
70
- * @words None of its own: the record's name stands beside it. Initials are the first letters of the name's first two words.
69
+ * @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 logo: the one white ink Sofia kept from its site on a black tile (`{colors.identity-ink}`) in both themes, as the company's card stamps it, or a square SVG icon in its own colours filling the tile, as Vercel shows a project's favicon; its two initials on the ringed card tile until a logo is found, or when the stored logo does not load; 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 or 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.
70
+ * @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.
71
71
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
72
72
  */
73
73
  export function IdentityMark(props) {
@@ -18,6 +18,7 @@ import { InputBox, type FieldSize } from "../internal/input-box.js";
18
18
  * a `segment` (a filled cell with a divider, the look of `Input`'s prefix and suffix) or `plain`
19
19
  * (a mark on the box's own fill, flush against the text). An icon button in an addon fills the
20
20
  * row, sits flush against the edge, is muted until hovered and never fills on hover or press.
21
+ * A text button in an addon is `InputGroupButton` at `xs`, 24 px high.
21
22
  * A disabled input steps the whole group down in fill and text, never in opacity, an icon button
22
23
  * included; a button in an addon that is held, such as a send button waiting for text, leaves the
23
24
  * box as it is.
@@ -1 +1 @@
1
- {"version":3,"file":"input-group.d.ts","sourceRoot":"","sources":["../../src/components/input-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAU,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EAA+B,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA2B7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,IAAgB,EAChB,OAAe,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,qBAaA;AAED,QAAA,MAAM,uBAAuB;;;8EA6B5B,CAAC;AAEF,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,KAAsB,EACtB,IAAc,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,qBAmB5E;AAkBD,KAAK,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,cAAc,CAAC,GAAG;IAChG,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC,CAAC;AAEF,KAAK,qBAAqB,GACtB,CAAC,oBAAoB,GAAG;IAAE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC,GAC/C,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1F,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,IAAe,EACf,OAAiB,EACjB,IAAW,EACX,GAAG,KAAK,EACT,EAAE,qBAAqB,qBAUvB;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAU5E;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,EAAE,MAAM,CAAC,qBAarD;AAED,iBAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,GAAG,cAAc,qBAE9F;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,qBAWnD;AAED,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,CAAC"}
1
+ {"version":3,"file":"input-group.d.ts","sourceRoot":"","sources":["../../src/components/input-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAU,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EAA+B,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA2B7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,iBAAS,UAAU,CAAC,EAClB,SAAS,EACT,IAAgB,EAChB,OAAe,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,qBAaA;AAED,QAAA,MAAM,uBAAuB;;;8EA6B5B,CAAC;AAEF,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,KAAsB,EACtB,IAAc,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,uBAAuB,CAAC,qBAmB5E;AAkBD,KAAK,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,cAAc,CAAC,GAAG;IAChG,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC,CAAC;AAEF,KAAK,qBAAqB,GACtB,CAAC,oBAAoB,GAAG;IAAE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC,GAC/C,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1F,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,IAAe,EACf,OAAiB,EACjB,IAAW,EACX,GAAG,KAAK,EACT,EAAE,qBAAqB,qBAUvB;AAED,iBAAS,cAAc,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,qBAU5E;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,EAAE,MAAM,CAAC,qBAarD;AAED,iBAAS,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,iBAAiB,CAAC,GAAG,cAAc,qBAE9F;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,cAAc,qBAWnD;AAED,OAAO,EACL,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,CAAC"}
@@ -42,6 +42,7 @@ const inputGroupVariants = cva([
42
42
  * a `segment` (a filled cell with a divider, the look of `Input`'s prefix and suffix) or `plain`
43
43
  * (a mark on the box's own fill, flush against the text). An icon button in an addon fills the
44
44
  * row, sits flush against the edge, is muted until hovered and never fills on hover or press.
45
+ * A text button in an addon is `InputGroupButton` at `xs`, 24 px high.
45
46
  * A disabled input steps the whole group down in fill and text, never in opacity, an icon button
46
47
  * included; a button in an addon that is held, such as a send button waiting for text, leaves the
47
48
  * box as it is.
@@ -9,11 +9,13 @@ import { OTPInput } from "input-otp";
9
9
  * `Input` with a copy or paste action.
10
10
  * @behaviour One real input behind the slots: paste fills them all, Backspace walks back. The
11
11
  * active slot carries the focus outline and a still caret. A wrong code turns the group red and
12
- * keeps the digits so the person can correct them. Resend follows the product's real policy.
13
- * @words The label says where the code comes from. The error says what to do: *That code didn't
12
+ * keeps the digits so the person can correct them. Resend follows the product's real policy. The
13
+ * component owns none of the length (`maxLength`), expiry or submission: the product sets and
14
+ * handles them.
15
+ * @words A visible label says where the code comes from. The error says what to do: *That code didn't
14
16
  * match. Check the newest code in your app.*
15
17
  * @access One labelled input with `autocomplete="one-time-code"` and `inputMode="numeric"`. The
16
- * separator is decorative to the reader.
18
+ * separator has `role="separator"`.
17
19
  */
18
20
  declare function InputOTP({ className, containerClassName, ...props }: React.ComponentProps<typeof OTPInput> & {
19
21
  containerClassName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"input-otp.d.ts","sourceRoot":"","sources":["../../src/components/input-otp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AAKtD;;;;;;;;;;;;;;GAcG;AACH,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,GAAG;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,qBAoBA;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW1E;AAED,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,qBAsBA;AAED,iBAAS,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWnE;AAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"input-otp.d.ts","sourceRoot":"","sources":["../../src/components/input-otp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AAKtD;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,GAAG;IACzC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,qBAoBA;AAED,iBAAS,aAAa,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW1E;AAED,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,qBAsBA;AAED,iBAAS,iBAAiB,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWnE;AAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -13,11 +13,13 @@ import { MinusIcon } from "lucide-react";
13
13
  * `Input` with a copy or paste action.
14
14
  * @behaviour One real input behind the slots: paste fills them all, Backspace walks back. The
15
15
  * active slot carries the focus outline and a still caret. A wrong code turns the group red and
16
- * keeps the digits so the person can correct them. Resend follows the product's real policy.
17
- * @words The label says where the code comes from. The error says what to do: *That code didn't
16
+ * keeps the digits so the person can correct them. Resend follows the product's real policy. The
17
+ * component owns none of the length (`maxLength`), expiry or submission: the product sets and
18
+ * handles them.
19
+ * @words A visible label says where the code comes from. The error says what to do: *That code didn't
18
20
  * match. Check the newest code in your app.*
19
21
  * @access One labelled input with `autocomplete="one-time-code"` and `inputMode="numeric"`. The
20
- * separator is decorative to the reader.
22
+ * separator has `role="separator"`.
21
23
  */
22
24
  function InputOTP({ className, containerClassName, ...props }) {
23
25
  return (_jsx(OTPInput, { "data-slot": "input-otp", containerClassName: cn("cn-input-otp flex items-center has-disabled:opacity-50", containerClassName), spellCheck: false,
@@ -29,8 +29,10 @@ type InputProps = Omit<React.ComponentProps<"input">, "size" | "prefix"> & {
29
29
  * variant with a scoped placeholder like `Search projects`; don’t embed a `<SearchInput>` inside an
30
30
  * unrelated form." (https://vercel.com/geist/input) Ours: there is no `search` variant. A
31
31
  * collection's search is `CollectionSearch`, and a value people empty often is `ClearableInput`. A
32
- * short known set is radios or a select. A button inside the box, or a server-given value with its
33
- * copy button, is an `InputGroup`.
32
+ * short known set is radios or a select. A button inside the box, a block addon, a textarea
33
+ * toolbar, or a server-given value with its copy button, is an `InputGroup`; Geist's
34
+ * `prefixContainer` and `suffixContainer` are compositions of `InputGroup`. The card around a field
35
+ * is a `SettingsField` or a `Field`.
34
36
  * @behaviour Sizes `sm` (32 px), default (36 px) and `lg` (40 px, larger type) are shared by every
35
37
  * field, so fields in a row line up. The edge is a 1 px ring outside the box that darkens on hover;
36
38
  * focus makes it full strength with a soft 4 px halo around it. Colour sits in one place: an error
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGhE,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,KAAK,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,GAAG;IACzE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,gEAAgE;IAChE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,qHAAqH;IACrH,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,WAAW,EACX,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAgB,EAChB,OAAe,EACf,IAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,UAAU,qBAyBZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGhE,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,KAAK,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,GAAG;IACzE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,gEAAgE;IAChE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,qHAAqH;IACrH,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC3B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,iBAAS,KAAK,CAAC,EACb,KAAK,EACL,WAAW,EACX,KAAK,EACL,MAAM,EACN,MAAM,EACN,IAAgB,EAChB,OAAe,EACf,IAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,UAAU,qBAyBZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -15,8 +15,10 @@ import { InputGroup, InputGroupAddon, InputGroupControl } from "./input-group.js
15
15
  * variant with a scoped placeholder like `Search projects`; don’t embed a `<SearchInput>` inside an
16
16
  * unrelated form." (https://vercel.com/geist/input) Ours: there is no `search` variant. A
17
17
  * collection's search is `CollectionSearch`, and a value people empty often is `ClearableInput`. A
18
- * short known set is radios or a select. A button inside the box, or a server-given value with its
19
- * copy button, is an `InputGroup`.
18
+ * short known set is radios or a select. A button inside the box, a block addon, a textarea
19
+ * toolbar, or a server-given value with its copy button, is an `InputGroup`; Geist's
20
+ * `prefixContainer` and `suffixContainer` are compositions of `InputGroup`. The card around a field
21
+ * is a `SettingsField` or a `Field`.
20
22
  * @behaviour Sizes `sm` (32 px), default (36 px) and `lg` (40 px, larger type) are shared by every
21
23
  * field, so fields in a row line up. The edge is a 1 px ring outside the box that darkens on hover;
22
24
  * focus makes it full strength with a soft 4 px halo around it. Colour sits in one place: an error
@@ -27,7 +27,7 @@ declare const itemVariants: (props?: ({
27
27
  * @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
28
28
  * “For a static key/value metadata block on a detail page, use `Description`.” (https://vercel.com/geist/entity)
29
29
  * Ours: Geist's `Table` is a `DataTable` and its `Description` is `ObjectFacts`. An object a person opens, with a mark, facts and a status, is a `RecordList` row; the same row edited in place is a `RecordList` with an `editor`. A page whose job is one collection is `CollectionPage`. Agents in a gallery are `AgentListRow`; Library entries `CatalogEntry`.
30
- * @behaviour Every row has a title over its one muted description line; only a message row read whole, or a second content beside the first, may be description only. Media, content and actions stand 16 px apart, centred on one another, in a 72 px row of 16 px padding; the title and the description each hold one line and end in an ellipsis (`whole` lets a message wrap). Inside a card the group is `divided`: no gaps, one hairline between items. An item that is an `a`, a `button` or a `label` takes the `accent` hover and is one hit target; a plain item never reacts to hover; nested controls stay independent. A button in the row is `size="sm"`. A row a person picks starts with `ItemSelect` and is drawn `render={<label />}`, so the whole row ticks its box and has no other control. A second content beside the first takes only the room its words need. Colour is neutral: the title in ink, the description and any trailing words muted, no hue.
30
+ * @behaviour A list of descriptive rows is an `ItemGroup` of `Item`s, never table semantics. Every row has a title over its one muted description line; only a message row read whole, or a second content beside the first, may be description only. Media, content and actions stand 16 px apart, centred on one another, in a 72 px row of 16 px padding; a 600 title stands over one 20 px description with no gap, and each holds one line and ends in an ellipsis (`whole` lets a message wrap). Inside a card the group is `divided`: no gaps, one hairline between items. An item that is an `a`, a `button` or a `label` takes the `accent` hover and is one hit target; a plain item never reacts to hover; nested controls stay independent. A button in the row is `size="sm"` (32 px). A row a person picks starts with `ItemSelect` and is drawn `render={<label />}`, so the whole row ticks its box and has no other control. A second content beside the first takes only the room its words need. Colour is neutral: the title in ink, the description and any trailing words muted, no hue.
31
31
  * “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)
32
32
  * Ours: the third control goes in the row's three dots.
33
33
  * “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)
@@ -48,7 +48,7 @@ const itemVariants = cva("nc-transition-paint group/item flex w-full flex-wrap i
48
48
  * @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
49
49
  * “For a static key/value metadata block on a detail page, use `Description`.” (https://vercel.com/geist/entity)
50
50
  * Ours: Geist's `Table` is a `DataTable` and its `Description` is `ObjectFacts`. An object a person opens, with a mark, facts and a status, is a `RecordList` row; the same row edited in place is a `RecordList` with an `editor`. A page whose job is one collection is `CollectionPage`. Agents in a gallery are `AgentListRow`; Library entries `CatalogEntry`.
51
- * @behaviour Every row has a title over its one muted description line; only a message row read whole, or a second content beside the first, may be description only. Media, content and actions stand 16 px apart, centred on one another, in a 72 px row of 16 px padding; the title and the description each hold one line and end in an ellipsis (`whole` lets a message wrap). Inside a card the group is `divided`: no gaps, one hairline between items. An item that is an `a`, a `button` or a `label` takes the `accent` hover and is one hit target; a plain item never reacts to hover; nested controls stay independent. A button in the row is `size="sm"`. A row a person picks starts with `ItemSelect` and is drawn `render={<label />}`, so the whole row ticks its box and has no other control. A second content beside the first takes only the room its words need. Colour is neutral: the title in ink, the description and any trailing words muted, no hue.
51
+ * @behaviour A list of descriptive rows is an `ItemGroup` of `Item`s, never table semantics. Every row has a title over its one muted description line; only a message row read whole, or a second content beside the first, may be description only. Media, content and actions stand 16 px apart, centred on one another, in a 72 px row of 16 px padding; a 600 title stands over one 20 px description with no gap, and each holds one line and ends in an ellipsis (`whole` lets a message wrap). Inside a card the group is `divided`: no gaps, one hairline between items. An item that is an `a`, a `button` or a `label` takes the `accent` hover and is one hit target; a plain item never reacts to hover; nested controls stay independent. A button in the row is `size="sm"` (32 px). A row a person picks starts with `ItemSelect` and is drawn `render={<label />}`, so the whole row ticks its box and has no other control. A second content beside the first takes only the room its words need. Colour is neutral: the title in ink, the description and any trailing words muted, no hue.
52
52
  * “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)
53
53
  * Ours: the third control goes in the row's three dots.
54
54
  * “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)