@nadicodeai/ui 12.1.164 → 12.1.166

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 (364) hide show
  1. package/AGENTS.md +8 -9
  2. package/README.md +2 -17
  3. package/dist/components/accordion.d.ts.map +1 -1
  4. package/dist/components/accordion.js +2 -1
  5. package/dist/components/account-menu.d.ts.map +1 -1
  6. package/dist/components/account-menu.js +5 -3
  7. package/dist/components/activity-calendar.d.ts.map +1 -1
  8. package/dist/components/activity-calendar.js +3 -2
  9. package/dist/components/agent-card.js +1 -1
  10. package/dist/components/agent-orb.d.ts.map +1 -1
  11. package/dist/components/agent-orb.js +1 -0
  12. package/dist/components/agent-profile.d.ts.map +1 -1
  13. package/dist/components/agent-profile.js +7 -4
  14. package/dist/components/alert-dialog.d.ts +1 -1
  15. package/dist/components/alert-dialog.d.ts.map +1 -1
  16. package/dist/components/alert-dialog.js +3 -3
  17. package/dist/components/app-mark.js +1 -1
  18. package/dist/components/avatar.js +8 -8
  19. package/dist/components/badge.d.ts +11 -16
  20. package/dist/components/badge.d.ts.map +1 -1
  21. package/dist/components/badge.js +7 -43
  22. package/dist/components/breadcrumb.d.ts.map +1 -1
  23. package/dist/components/breadcrumb.js +3 -2
  24. package/dist/components/button.d.ts +5 -21
  25. package/dist/components/button.d.ts.map +1 -1
  26. package/dist/components/button.js +6 -76
  27. package/dist/components/calendar.d.ts +1 -1
  28. package/dist/components/calendar.d.ts.map +1 -1
  29. package/dist/components/calendar.js +3 -3
  30. package/dist/components/card-row.js +1 -1
  31. package/dist/components/card.d.ts +4 -1
  32. package/dist/components/card.d.ts.map +1 -1
  33. package/dist/components/card.js +3 -2
  34. package/dist/components/catalog-drawer.d.ts.map +1 -1
  35. package/dist/components/catalog-drawer.js +3 -2
  36. package/dist/components/chart-axis.d.ts.map +1 -1
  37. package/dist/components/chart-axis.js +0 -2
  38. package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
  39. package/dist/components/chart-bar-horizontal.js +16 -14
  40. package/dist/components/chart-card.d.ts.map +1 -1
  41. package/dist/components/chart-card.js +0 -1
  42. package/dist/components/chart.d.ts.map +1 -1
  43. package/dist/components/chart.js +18 -32
  44. package/dist/components/checkbox.d.ts +3 -2
  45. package/dist/components/checkbox.d.ts.map +1 -1
  46. package/dist/components/checkbox.js +4 -3
  47. package/dist/components/choicebox.d.ts +5 -5
  48. package/dist/components/choicebox.d.ts.map +1 -1
  49. package/dist/components/choicebox.js +6 -5
  50. package/dist/components/clearable-input.d.ts.map +1 -1
  51. package/dist/components/clearable-input.js +2 -2
  52. package/dist/components/code-block.d.ts.map +1 -1
  53. package/dist/components/code-block.js +4 -2
  54. package/dist/components/collapsible.js +1 -1
  55. package/dist/components/collection-filters.d.ts.map +1 -1
  56. package/dist/components/collection-filters.js +1 -0
  57. package/dist/components/collection-page.js +1 -1
  58. package/dist/components/collection-sort.d.ts.map +1 -1
  59. package/dist/components/collection-sort.js +1 -4
  60. package/dist/components/collection-toolbar.js +1 -1
  61. package/dist/components/combobox.js +4 -4
  62. package/dist/components/command.d.ts.map +1 -1
  63. package/dist/components/command.js +1 -1
  64. package/dist/components/confirm-dialog.js +2 -2
  65. package/dist/components/context-menu.d.ts +1 -1
  66. package/dist/components/context-menu.d.ts.map +1 -1
  67. package/dist/components/copy-button.js +1 -1
  68. package/dist/components/data-table.d.ts +11 -3
  69. package/dist/components/data-table.d.ts.map +1 -1
  70. package/dist/components/data-table.js +12 -4
  71. package/dist/components/dialog.d.ts +1 -1
  72. package/dist/components/dialog.d.ts.map +1 -1
  73. package/dist/components/dialog.js +2 -2
  74. package/dist/components/drawer.d.ts +4 -4
  75. package/dist/components/drawer.d.ts.map +1 -1
  76. package/dist/components/drawer.js +14 -15
  77. package/dist/components/dropdown-menu.d.ts +1 -1
  78. package/dist/components/dropdown-menu.d.ts.map +1 -1
  79. package/dist/components/dropdown-menu.js +9 -5
  80. package/dist/components/empty-art.js +1 -1
  81. package/dist/components/empty-state.js +2 -2
  82. package/dist/components/entry-scene.d.ts.map +1 -1
  83. package/dist/components/entry-scene.js +2 -3
  84. package/dist/components/field.js +3 -3
  85. package/dist/components/file-diff.d.ts.map +1 -1
  86. package/dist/components/file-diff.js +5 -2
  87. package/dist/components/footer.d.ts +1 -1
  88. package/dist/components/footer.d.ts.map +1 -1
  89. package/dist/components/footer.js +3 -3
  90. package/dist/components/form-dialog.d.ts.map +1 -1
  91. package/dist/components/form-dialog.js +2 -1
  92. package/dist/components/form-drawer.d.ts +7 -9
  93. package/dist/components/form-drawer.d.ts.map +1 -1
  94. package/dist/components/form-drawer.js +5 -5
  95. package/dist/components/form.d.ts +26 -0
  96. package/dist/components/form.d.ts.map +1 -0
  97. package/dist/components/form.js +29 -0
  98. package/dist/components/gauge.js +2 -2
  99. package/dist/components/heatmap/calendar-heatmap.d.ts.map +1 -1
  100. package/dist/components/heatmap/calendar-heatmap.js +15 -13
  101. package/dist/components/hive-scene.d.ts +3 -3
  102. package/dist/components/hive-scene.d.ts.map +1 -1
  103. package/dist/components/hive-scene.js +4 -2
  104. package/dist/components/hover-card.d.ts +1 -1
  105. package/dist/components/hover-card.d.ts.map +1 -1
  106. package/dist/components/hover-card.js +1 -1
  107. package/dist/components/input-group.d.ts +5 -6
  108. package/dist/components/input-group.d.ts.map +1 -1
  109. package/dist/components/input-group.js +8 -11
  110. package/dist/components/input-otp.d.ts.map +1 -1
  111. package/dist/components/input-otp.js +2 -2
  112. package/dist/components/item.d.ts +1 -1
  113. package/dist/components/item.js +2 -2
  114. package/dist/components/kbd.d.ts +6 -9
  115. package/dist/components/kbd.d.ts.map +1 -1
  116. package/dist/components/kbd.js +7 -3
  117. package/dist/components/message-notice.js +1 -1
  118. package/dist/components/middle-truncate.d.ts.map +1 -1
  119. package/dist/components/middle-truncate.js +1 -0
  120. package/dist/components/model-identity.d.ts +4 -4
  121. package/dist/components/model-identity.d.ts.map +1 -1
  122. package/dist/components/model-identity.js +2 -2
  123. package/dist/components/model-mark.d.ts.map +1 -1
  124. package/dist/components/model-mark.js +4 -2
  125. package/dist/components/multi-select.js +2 -2
  126. package/dist/components/native-select.d.ts.map +1 -1
  127. package/dist/components/native-select.js +2 -6
  128. package/dist/components/notice-banner.js +1 -1
  129. package/dist/components/object-page.js +2 -2
  130. package/dist/components/object-workspace.d.ts.map +1 -1
  131. package/dist/components/object-workspace.js +1 -3
  132. package/dist/components/overview-page.d.ts +1 -1
  133. package/dist/components/overview-page.d.ts.map +1 -1
  134. package/dist/components/overview-page.js +2 -1
  135. package/dist/components/page-actions.d.ts.map +1 -1
  136. package/dist/components/page-actions.js +9 -4
  137. package/dist/components/pairing-code.js +1 -1
  138. package/dist/components/pending-label.d.ts.map +1 -1
  139. package/dist/components/pending-label.js +0 -1
  140. package/dist/components/popover.d.ts +1 -1
  141. package/dist/components/popover.d.ts.map +1 -1
  142. package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
  143. package/dist/components/portal-sidebar-frame.js +1 -1
  144. package/dist/components/product-message.d.ts.map +1 -1
  145. package/dist/components/product-message.js +1 -0
  146. package/dist/components/progress-checklist.d.ts.map +1 -1
  147. package/dist/components/progress-checklist.js +2 -2
  148. package/dist/components/progress.d.ts.map +1 -1
  149. package/dist/components/progress.js +5 -4
  150. package/dist/components/radio-group.js +2 -2
  151. package/dist/components/reading-column.js +1 -1
  152. package/dist/components/record-identity.d.ts.map +1 -1
  153. package/dist/components/record-identity.js +2 -5
  154. package/dist/components/record-list.d.ts.map +1 -1
  155. package/dist/components/record-list.js +4 -3
  156. package/dist/components/record-sheet.js +1 -1
  157. package/dist/components/record-time.d.ts.map +1 -1
  158. package/dist/components/record-time.js +2 -1
  159. package/dist/components/resizable.d.ts.map +1 -1
  160. package/dist/components/resizable.js +1 -1
  161. package/dist/components/row-edit-form.d.ts +2 -1
  162. package/dist/components/row-edit-form.d.ts.map +1 -1
  163. package/dist/components/row-edit-form.js +2 -1
  164. package/dist/components/run-timeline.js +1 -1
  165. package/dist/components/scope-switcher.js +1 -1
  166. package/dist/components/segmented-control.js +1 -1
  167. package/dist/components/select.js +1 -1
  168. package/dist/components/settings-facts.js +1 -1
  169. package/dist/components/settings-section.js +1 -1
  170. package/dist/components/sheet.d.ts +1 -1
  171. package/dist/components/sheet.d.ts.map +1 -1
  172. package/dist/components/sheet.js +1 -1
  173. package/dist/components/sidebar.d.ts +2 -2
  174. package/dist/components/sidebar.d.ts.map +1 -1
  175. package/dist/components/sidebar.js +16 -18
  176. package/dist/components/site-menu.d.ts +28 -0
  177. package/dist/components/site-menu.d.ts.map +1 -0
  178. package/dist/components/site-menu.js +23 -0
  179. package/dist/components/slider.d.ts.map +1 -1
  180. package/dist/components/slider.js +2 -1
  181. package/dist/components/snippet.d.ts +2 -0
  182. package/dist/components/snippet.d.ts.map +1 -1
  183. package/dist/components/snippet.js +13 -6
  184. package/dist/components/sonner.d.ts.map +1 -1
  185. package/dist/components/sonner.js +3 -4
  186. package/dist/components/status-badge.d.ts +1 -1
  187. package/dist/components/status-badge.d.ts.map +1 -1
  188. package/dist/components/switch.js +1 -1
  189. package/dist/components/table-card.js +1 -1
  190. package/dist/components/table.js +4 -4
  191. package/dist/components/tabs-nav.d.ts +52 -0
  192. package/dist/components/tabs-nav.d.ts.map +1 -0
  193. package/dist/components/tabs-nav.js +95 -0
  194. package/dist/components/tabs.d.ts +2 -56
  195. package/dist/components/tabs.d.ts.map +1 -1
  196. package/dist/components/tabs.js +2 -91
  197. package/dist/components/text-link.d.ts +1 -2
  198. package/dist/components/text-link.d.ts.map +1 -1
  199. package/dist/components/text-link.js +1 -2
  200. package/dist/components/textarea.d.ts +5 -2
  201. package/dist/components/textarea.d.ts.map +1 -1
  202. package/dist/components/textarea.js +12 -4
  203. package/dist/components/toast.d.ts +2 -0
  204. package/dist/components/toast.d.ts.map +1 -1
  205. package/dist/components/toast.js +4 -0
  206. package/dist/components/toggle-group.d.ts +3 -1
  207. package/dist/components/toggle-group.d.ts.map +1 -1
  208. package/dist/components/toggle-group.js +3 -6
  209. package/dist/components/toggle.js +1 -1
  210. package/dist/components/tooltip.d.ts +12 -12
  211. package/dist/components/tooltip.d.ts.map +1 -1
  212. package/dist/components/tooltip.js +9 -9
  213. package/dist/components/trend-badge.js +2 -2
  214. package/dist/components/update-card.js +1 -1
  215. package/dist/components/usage-meter.d.ts +1 -1
  216. package/dist/components/usage-meter.d.ts.map +1 -1
  217. package/dist/components/usage-meter.js +9 -7
  218. package/dist/components/waiting-line.js +1 -1
  219. package/dist/index.d.ts +3 -7
  220. package/dist/index.d.ts.map +1 -1
  221. package/dist/index.js +3 -7
  222. package/dist/internal/agent-orb-motion.d.ts +4 -1
  223. package/dist/internal/agent-orb-motion.d.ts.map +1 -1
  224. package/dist/internal/agent-orb-motion.js +9 -7
  225. package/dist/internal/agent-orb.d.ts +4 -1
  226. package/dist/internal/agent-orb.d.ts.map +1 -1
  227. package/dist/internal/agent-orb.js +7 -1
  228. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  229. package/dist/internal/assistant-ui/attachment.js +15 -15
  230. package/dist/internal/assistant-ui/follow-up-suggestions.js +1 -1
  231. package/dist/internal/assistant-ui/markdown-text.js +26 -25
  232. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  233. package/dist/internal/assistant-ui/reasoning.js +13 -16
  234. package/dist/internal/assistant-ui/thread.d.ts.map +1 -1
  235. package/dist/internal/assistant-ui/thread.js +22 -16
  236. package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -1
  237. package/dist/internal/assistant-ui/tool-fallback.js +29 -21
  238. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  239. package/dist/internal/assistant-ui/tool-group.js +6 -7
  240. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  241. package/dist/internal/badge-frame.d.ts +15 -0
  242. package/dist/internal/badge-frame.d.ts.map +1 -0
  243. package/dist/internal/badge-frame.js +44 -0
  244. package/dist/internal/button-classes.d.ts +20 -0
  245. package/dist/internal/button-classes.d.ts.map +1 -0
  246. package/dist/internal/button-classes.js +74 -0
  247. package/dist/internal/catalog-list.d.ts.map +1 -1
  248. package/dist/internal/catalog-list.js +8 -4
  249. package/dist/internal/collection-rail.js +3 -3
  250. package/dist/internal/form-drawer-frame.d.ts +10 -0
  251. package/dist/internal/form-drawer-frame.d.ts.map +1 -0
  252. package/dist/internal/form-drawer-frame.js +9 -0
  253. package/dist/internal/form-submit.d.ts +2 -1
  254. package/dist/internal/form-submit.d.ts.map +1 -1
  255. package/dist/internal/settings-save.d.ts.map +1 -1
  256. package/dist/internal/settings-save.js +4 -2
  257. package/dist/internal/status-mark.d.ts.map +1 -1
  258. package/dist/internal/status-mark.js +4 -1
  259. package/dist/internal/tab-row.d.ts +10 -0
  260. package/dist/internal/tab-row.d.ts.map +1 -0
  261. package/dist/internal/tab-row.js +2 -0
  262. package/dist/internal/table-compact-line.d.ts +1 -1
  263. package/dist/internal/table-compact-line.d.ts.map +1 -1
  264. package/dist/internal/table-compact-line.js +1 -1
  265. package/dist/internal/tooltip-content-frame.d.ts +14 -0
  266. package/dist/internal/tooltip-content-frame.d.ts.map +1 -0
  267. package/dist/internal/tooltip-content-frame.js +11 -0
  268. package/dist/lib/css-variables.d.ts +8 -0
  269. package/dist/lib/css-variables.d.ts.map +1 -0
  270. package/dist/lib/css-variables.js +4 -0
  271. package/dist/lib/merge-tokens.generated.js +1 -1
  272. package/dist/lib/use-copy-to-clipboard.d.ts.map +1 -1
  273. package/dist/lib/use-copy-to-clipboard.js +1 -2
  274. package/dist/showcase/samples.js +1 -1
  275. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  276. package/dist/showcase/specimens/choices.js +3 -2
  277. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  278. package/dist/showcase/specimens/compositions.js +7 -5
  279. package/dist/showcase/specimens/data.d.ts.map +1 -1
  280. package/dist/showcase/specimens/data.js +1 -1
  281. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  282. package/dist/showcase/specimens/feedback.js +1 -2
  283. package/dist/showcase/specimens/index.d.ts +2 -0
  284. package/dist/showcase/specimens/index.d.ts.map +1 -1
  285. package/dist/showcase/specimens/inputs.d.ts +1 -0
  286. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  287. package/dist/showcase/specimens/inputs.js +5 -2
  288. package/dist/showcase/specimens/menus.d.ts +1 -0
  289. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  290. package/dist/showcase/specimens/menus.js +7 -2
  291. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  292. package/dist/showcase/specimens/navigation.js +6 -5
  293. package/dist/showcase/specimens/status.d.ts.map +1 -1
  294. package/dist/showcase/specimens/status.js +4 -4
  295. package/dist/showcase/usage.generated.d.ts +1 -1
  296. package/dist/showcase/usage.generated.d.ts.map +1 -1
  297. package/dist/showcase/usage.generated.js +39 -17
  298. package/dist/standalone/index.js +1 -1
  299. package/dist/standalone/orb-page.js +10 -8
  300. package/dist/styles/components.css +14 -19
  301. package/package.json +32 -33
  302. package/dist/eslint/index.js +0 -224
  303. package/dist/eslint/rules/badge-is-static-label.js +0 -93
  304. package/dist/eslint/rules/button-icon-slot.js +0 -102
  305. package/dist/eslint/rules/button-link-for-navigation.js +0 -146
  306. package/dist/eslint/rules/button-no-aria-label-with-text.js +0 -75
  307. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +0 -83
  308. package/dist/eslint/rules/choice-control-has-a-name.js +0 -98
  309. package/dist/eslint/rules/choice-group-in-fieldset.js +0 -86
  310. package/dist/eslint/rules/command-shortcut-single-owner.js +0 -118
  311. package/dist/eslint/rules/confirm-dialog-words.js +0 -63
  312. package/dist/eslint/rules/data-table-one-unsized-column.js +0 -96
  313. package/dist/eslint/rules/destructive-action-placement.js +0 -69
  314. package/dist/eslint/rules/disabled-choice-says-why.js +0 -71
  315. package/dist/eslint/rules/disabled-control-appearance.js +0 -75
  316. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +0 -110
  317. package/dist/eslint/rules/empty-state-owner.js +0 -145
  318. package/dist/eslint/rules/input-group-owners.js +0 -155
  319. package/dist/eslint/rules/jsx-class-utility.js +0 -200
  320. package/dist/eslint/rules/kbd-children-no-modifier-text.js +0 -128
  321. package/dist/eslint/rules/literal-text.js +0 -41
  322. package/dist/eslint/rules/menu-owner.js +0 -75
  323. package/dist/eslint/rules/middle-truncate-placement.js +0 -69
  324. package/dist/eslint/rules/no-app-feature-component.js +0 -100
  325. package/dist/eslint/rules/no-bare-button-label.js +0 -55
  326. package/dist/eslint/rules/no-choice-control-wrapper.js +0 -97
  327. package/dist/eslint/rules/no-comment.js +0 -77
  328. package/dist/eslint/rules/no-control-in-read-only-surface.js +0 -106
  329. package/dist/eslint/rules/no-decorative-icon.js +0 -164
  330. package/dist/eslint/rules/no-deprecated-zod-api.js +0 -215
  331. package/dist/eslint/rules/no-global-patch.js +0 -115
  332. package/dist/eslint/rules/no-hand-built-busy.js +0 -104
  333. package/dist/eslint/rules/no-hand-built-theme-picker.js +0 -144
  334. package/dist/eslint/rules/no-hand-built-tile.js +0 -41
  335. package/dist/eslint/rules/no-hand-formatted-date.js +0 -87
  336. package/dist/eslint/rules/no-hand-stacked-avatars.js +0 -67
  337. package/dist/eslint/rules/no-nested-collapse.js +0 -60
  338. package/dist/eslint/rules/no-package-component-redefinition.js +0 -175
  339. package/dist/eslint/rules/no-search-in-form.js +0 -47
  340. package/dist/eslint/rules/no-shadcn-appearance-override.js +0 -305
  341. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +0 -74
  342. package/dist/eslint/rules/no-stock-error-words.js +0 -56
  343. package/dist/eslint/rules/no-subject-derived-expectation.js +0 -183
  344. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +0 -72
  345. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +0 -57
  346. package/dist/eslint/rules/no-write-in-subscription.js +0 -140
  347. package/dist/eslint/rules/one-submenu-level.js +0 -43
  348. package/dist/eslint/rules/one-toast-per-flow.js +0 -91
  349. package/dist/eslint/rules/option-count.js +0 -167
  350. package/dist/eslint/rules/page-command-link-not-render.js +0 -43
  351. package/dist/eslint/rules/page-composition.js +0 -232
  352. package/dist/eslint/rules/progress-needs-name.js +0 -57
  353. package/dist/eslint/rules/rendered-import.js +0 -121
  354. package/dist/eslint/rules/server-action-discipline.js +0 -233
  355. package/dist/eslint/rules/settings-limit-in-footer.js +0 -94
  356. package/dist/eslint/rules/skeleton-in-region.js +0 -80
  357. package/dist/eslint/rules/sortable-heading-uses-sort.js +0 -79
  358. package/dist/eslint/rules/table-cell-inset-owner.js +0 -107
  359. package/dist/eslint/rules/tabs-selection-is-controlled.js +0 -47
  360. package/dist/eslint/rules/test-files-from-one-definition.js +0 -67
  361. package/dist/eslint/rules/tooltip-only-arrow.js +0 -38
  362. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +0 -114
  363. package/dist/eslint/rules/workspace-declares-imports.js +0 -163
  364. package/dist/eslint/strict-design-system.js +0 -250
@@ -0,0 +1,95 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { mergeProps } from "@base-ui/react/merge-props";
5
+ import { useRender } from "@base-ui/react/use-render";
6
+ import { tabShape } from "../internal/tab-row.js";
7
+ import { cn } from "../lib/utils.js";
8
+ /** Which ends of a scrolled row hide links, so the row fades there to say more stand beyond. */
9
+ function hiddenTabs(element) {
10
+ const start = element.scrollLeft > 1;
11
+ const end = element.scrollLeft + element.clientWidth < element.scrollWidth - 1;
12
+ return start && end ? "both" : start ? "start" : end ? "end" : "none";
13
+ }
14
+ const HIDDEN_FADE = {
15
+ none: undefined,
16
+ start: "[mask-image:linear-gradient(to_right,transparent,black_2rem)]",
17
+ end: "[mask-image:linear-gradient(to_left,transparent,black_2rem)]",
18
+ both: "[mask-image:linear-gradient(to_right,transparent,black_2rem,black_calc(100%_-_2rem),transparent)]",
19
+ };
20
+ /**
21
+ * Sibling views of one object, each with its own URL, under the top bar.
22
+ *
23
+ * @family Navigation
24
+ * @when Sibling views of one object under the top bar, when each view has its own URL (an object's
25
+ * sections), with `TabsLink` for each.
26
+ * @instead Panels that switch in place are `Tabs`. A stable destination belongs in the `Sidebar`.
27
+ * An object's ancestry is the `Breadcrumb`.
28
+ * @behaviour "Reflect the active tab in the URL (query param or path) so deep-links and refresh restore state." (https://vercel.com/geist/tabs)
29
+ * Ours: each view is its own URL, so a link carries it. Overflow scrolls sideways and brings the
30
+ * current link into view, and the row fades out over 32 px at each end where links stand beyond it.
31
+ * The current link takes the selection fill, or in `line` a 2 px ink underline over the row's 1 px
32
+ * rule; the other links are muted until hover, with no hue. Sizes and spacing follow `Tabs`. The
33
+ * row holds at most 7 links; in a `band`, which a phone scrolls sideways instead of holding
34
+ * fewer, that is 7 at every width, as an Agent's six views do, and a `line` row follows the 7 and 4 cap of `Tabs`. The sub-pages of one object stand as the filled-pill row in a
35
+ * `band` under the top bar, as Vercel draws a deployment's tabs: the band is this component's, with `above` for the
36
+ * object's identity, so no page draws the border, the fill or the gutters around the row. The band
37
+ * keeps the page's own column and gutter, and the first link's words start at the page title's edge,
38
+ * its fill reaching into the gutter as Vercel's tabs do. The
39
+ * `line` row has its own rule and takes no band.
40
+ * @words "`tabs[].title` is Title Case, 1–2 words, and names the destination noun (`Overview`, `Logs`, `Settings`). Verbs belong on buttons; `View Logs` is wrong on a tab." (https://vercel.com/geist/tabs)
41
+ * "Don’t append a count to the title (`Logs (12)`); use a badge slot instead and drop the badge at zero." (https://vercel.com/geist/tabs)
42
+ * Ours: the title is sentence case (*Overview*, *Installations*), not Title Case. There is no badge
43
+ * slot: a count belongs to the list's footer. A link has no icon. Italian scrolls, never wraps or
44
+ * truncates.
45
+ * @access "Label the tablist with `aria-label` when no visible heading sits above it (`aria-label="Sections"`)." (https://vercel.com/geist/tabs)
46
+ * "Maintain a visible focus ring on the active tab; don’t suppress focus styles for visual polish." (https://vercel.com/geist/tabs)
47
+ * Ours: a `nav` of links named by `aria-label` or `aria-labelledby`, which the type requires, with
48
+ * `aria-current="page"` on the current one.
49
+ */
50
+ function TabsNav({ className, children, variant = "default", band = false, above, ...props }) {
51
+ const navigation = React.useRef(null);
52
+ const current = React.useRef(null);
53
+ const [hidden, setHidden] = React.useState("none");
54
+ React.useEffect(() => {
55
+ const element = navigation.current;
56
+ if (!element || typeof ResizeObserver === "undefined")
57
+ return;
58
+ const measure = () => setHidden(hiddenTabs(element));
59
+ measure();
60
+ const observer = new ResizeObserver(measure);
61
+ observer.observe(element);
62
+ element.addEventListener("scroll", measure, { passive: true });
63
+ return () => {
64
+ observer.disconnect();
65
+ element.removeEventListener("scroll", measure);
66
+ };
67
+ }, []);
68
+ React.useEffect(() => {
69
+ const element = navigation.current;
70
+ const link = element?.querySelector('[aria-current="page"]') ?? null;
71
+ if (!element || link === current.current)
72
+ return;
73
+ current.current = link;
74
+ if (link && element.scrollWidth > element.clientWidth) {
75
+ link.scrollIntoView({ block: "nearest", inline: "nearest" });
76
+ }
77
+ });
78
+ const row = (_jsx("nav", { ref: navigation, "data-slot": "tabs-nav", "data-variant": variant, className: cn("group/tabs-nav group/tabs-list min-w-0 overflow-x-auto", HIDDEN_FADE[hidden], variant === "line" && "pb-px shadow-[inset_0_-1px_0_0_var(--border)]", className), ...props, children: _jsx("ul", { className: "flex w-max min-w-full items-center gap-0 group-data-[variant=line]/tabs-nav:gap-6", children: children }) }));
79
+ if (!band)
80
+ return row;
81
+ return (_jsx("div", { "data-slot": "tabs-nav-band", className: "border-b bg-background", children: _jsxs("div", { className: "mx-auto w-full max-w-7xl px-6", children: [above, _jsx("div", { className: "-mx-3 py-2", children: row })] }) }));
82
+ }
83
+ function TabsLink({ current = false, className, render, ...props }) {
84
+ const link = useRender({
85
+ defaultTagName: "a",
86
+ render,
87
+ props: mergeProps({
88
+ "aria-current": current ? "page" : undefined,
89
+ className: cn(tabShape, "group-data-[variant=line]/tabs-nav:-mb-px group-data-[variant=line]/tabs-nav:h-12.5 group-data-[variant=line]/tabs-nav:px-0.5", "group-data-[variant=default]/tabs-nav:aria-[current=page]:bg-selection group-data-[variant=default]/tabs-nav:aria-[current=page]:text-selection-foreground", "group-data-[variant=line]/tabs-nav:aria-[current=page]:text-foreground", "after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:bg-foreground after:opacity-0 group-data-[variant=line]/tabs-nav:aria-[current=page]:after:opacity-100", className),
90
+ }, props),
91
+ state: { slot: "tabs-link", current },
92
+ });
93
+ return _jsx("li", { className: "flex", children: link });
94
+ }
95
+ export { TabsNav, TabsLink };
@@ -1,14 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
3
- import { useRender } from "@base-ui/react/use-render";
4
3
  import { type VariantProps } from "class-variance-authority";
5
- type TabGroupName = {
6
- "aria-label": string;
7
- "aria-labelledby"?: string | undefined;
8
- } | {
9
- "aria-labelledby": string;
10
- "aria-label"?: string | undefined;
11
- };
4
+ import { type TabGroupName } from "../internal/tab-row.js";
12
5
  type TabDisabling = {
13
6
  disabled?: false | undefined;
14
7
  disabledReason?: undefined;
@@ -67,53 +60,6 @@ declare const tabsListVariants: (props?: ({
67
60
  declare function TabsList({ className, variant, ...props }: Omit<TabsPrimitive.List.Props, "aria-label" | "aria-labelledby"> & VariantProps<typeof tabsListVariants> & TabGroupName): React.JSX.Element;
68
61
  declare function TabsTrigger({ className, disabled, disabledReason, "aria-describedby": describedBy, ...props }: TabsTriggerProps): React.JSX.Element;
69
62
  declare function TabsContent({ className, ...props }: TabsPrimitive.Panel.Props): React.JSX.Element;
70
- /**
71
- * Sibling views of one object, each with its own URL, under the top bar.
72
- *
73
- * @family Navigation
74
- * @when Sibling views of one object under the top bar, when each view has its own URL (an object's
75
- * sections), with `TabsLink` for each.
76
- * @instead Panels that switch in place are `Tabs`. A stable destination belongs in the `Sidebar`.
77
- * An object's ancestry is the `Breadcrumb`.
78
- * @behaviour "Reflect the active tab in the URL (query param or path) so deep-links and refresh restore state." (https://vercel.com/geist/tabs)
79
- * Ours: each view is its own URL, so a link carries it. Overflow scrolls sideways and brings the
80
- * current link into view, and the row fades out over 32 px at each end where links stand beyond it.
81
- * The current link takes the selection fill, or in `line` a 2 px ink underline over the row's 1 px
82
- * rule; the other links are muted until hover, with no hue. Sizes and spacing follow `Tabs`. The
83
- * row holds at most 7 links; in a `band`, which a phone scrolls sideways instead of holding
84
- * fewer, that is 7 at every width, as an Agent's six views do, and a `line` row follows the 7 and 4 cap of `Tabs`. The sub-pages of one object stand as the filled-pill row in a
85
- * `band` under the top bar, as Vercel draws a deployment's tabs: the band is this component's, with `above` for the
86
- * object's identity, so no page draws the border, the fill or the gutters around the row. The band
87
- * keeps the page's own column and gutter, and the first link's words start at the page title's edge,
88
- * its fill reaching into the gutter as Vercel's tabs do. The
89
- * `line` row has its own rule and takes no band.
90
- * @words "`tabs[].title` is Title Case, 1–2 words, and names the destination noun (`Overview`, `Logs`, `Settings`). Verbs belong on buttons; `View Logs` is wrong on a tab." (https://vercel.com/geist/tabs)
91
- * "Don’t append a count to the title (`Logs (12)`); use a badge slot instead and drop the badge at zero." (https://vercel.com/geist/tabs)
92
- * Ours: the title is sentence case (*Overview*, *Installations*), not Title Case. There is no badge
93
- * slot: a count belongs to the list's footer. A link has no icon. Italian scrolls, never wraps or
94
- * truncates.
95
- * @access "Label the tablist with `aria-label` when no visible heading sits above it (`aria-label="Sections"`)." (https://vercel.com/geist/tabs)
96
- * "Maintain a visible focus ring on the active tab; don’t suppress focus styles for visual polish." (https://vercel.com/geist/tabs)
97
- * Ours: a `nav` of links named by `aria-label` or `aria-labelledby`, which the type requires, with
98
- * `aria-current="page"` on the current one.
99
- */
100
- declare function TabsNav({ className, children, variant, band, above, ...props }: Omit<React.ComponentProps<"nav">, "aria-label" | "aria-labelledby"> & TabGroupName & ({
101
- variant?: "default" | "line" | null;
102
- band?: false;
103
- above?: never;
104
- } | {
105
- variant?: "default" | null;
106
- /**
107
- * The row stands in a full-width band under the top bar: a 1 px rule below, the page's
108
- * background, the page's gutters, and the reading column centred inside.
109
- */
110
- band: true;
111
- /** The object's identity, in the band's column above the row. */
112
- above?: React.ReactNode;
113
- })): React.JSX.Element;
114
- declare function TabsLink({ current, className, render, ...props }: useRender.ComponentProps<"a"> & {
115
- current?: boolean;
116
- }): React.JSX.Element;
117
- export { Tabs, TabsList, TabsTrigger, TabsContent, TabsNav, TabsLink, tabsListVariants };
63
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
118
64
  export type { TabsProps };
119
65
  //# sourceMappingURL=tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/components/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,KAAK,YAAY,GACb;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAChE;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAErE,KAAK,YAAY,GACb;IAAE,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GAC5D;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,KAAK,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC;AAEjF,KAAK,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,eAAe,CAAC,GAAG;IAC5F,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC,IAAI,CAAC,kBAAkB,KAAK,IAAI,CAAC;CAC7F,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,iBAAS,IAAI,CAAC,EAAE,SAAS,EAAE,WAA0B,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,qBAU3E;AAED,QAAA,MAAM,gBAAgB;;8EAarB,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,OAAmB,EACnB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACjE,YAAY,CAAC,OAAO,gBAAgB,CAAC,GACrC,YAAY,qBAUb;AAKD,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,kBAAkB,EAAE,WAAW,EAC/B,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAmClB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,qBAQtE;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,iBAAS,OAAO,CAAC,EACf,SAAS,EACT,QAAQ,EACR,OAAmB,EACnB,IAAY,EACZ,KAAK,EACL,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACpE,YAAY,GACZ,CACI;IACE,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,GACD;IACE,OAAO,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B;;;OAGG;IACH,IAAI,EAAE,IAAI,CAAC;IACX,iEAAiE;IACjE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB,CACJ,qBAqDF;AAED,iBAAS,QAAQ,CAAC,EAChB,OAAe,EACf,SAAS,EACT,MAAM,EACN,GAAG,KAAK,EACT,EAAE,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,qBAqBvD;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;AACzF,YAAY,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/components/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGjE,KAAK,YAAY,GACb;IAAE,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IAAC,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GAC5D;IACE,QAAQ,EAAE,IAAI,CAAC;IACf,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,KAAK,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC;AAEjF,KAAK,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,eAAe,CAAC,GAAG;IAC5F,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,CAAC,IAAI,CAAC,kBAAkB,KAAK,IAAI,CAAC;CAC7F,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,iBAAS,IAAI,CAAC,EAAE,SAAS,EAAE,WAA0B,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,qBAU3E;AAED,QAAA,MAAM,gBAAgB;;8EAarB,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,OAAmB,EACnB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACjE,YAAY,CAAC,OAAO,gBAAgB,CAAC,GACrC,YAAY,qBAUb;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,kBAAkB,EAAE,WAAW,EAC/B,GAAG,KAAK,EACT,EAAE,gBAAgB,qBAmClB;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,qBAQtE;AAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,CAAC"}
@@ -2,10 +2,9 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Tabs as TabsPrimitive } from "@base-ui/react/tabs";
5
- import { mergeProps } from "@base-ui/react/merge-props";
6
- import { useRender } from "@base-ui/react/use-render";
7
5
  import { cva } from "class-variance-authority";
8
6
  import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip.js";
7
+ import { tabShape } from "../internal/tab-row.js";
9
8
  import { cn } from "../lib/utils.js";
10
9
  /**
11
10
  * Panels of one surface that switch in place.
@@ -61,7 +60,6 @@ const tabsListVariants = cva("group/tabs-list inline-flex max-w-full w-fit items
61
60
  function TabsList({ className, variant = "default", ...props }) {
62
61
  return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", "data-nc-ui": "", "data-variant": variant, className: cn(tabsListVariants({ variant }), className), ...props }));
63
62
  }
64
- const tabShape = "nc-transition-paint relative inline-flex shrink-0 h-nadicode-control-height-sm min-h-touch-target min-w-touch-target items-center justify-center gap-1.5 rounded-sm px-3 text-label-sm font-normal whitespace-nowrap text-muted-foreground not-aria-disabled:hover:text-foreground aria-disabled:cursor-not-allowed focus-visible:-outline-offset-2 [@media(hover:hover)_and_(pointer:fine)]:min-h-0 [@media(hover:hover)_and_(pointer:fine)]:min-w-0 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 group-data-[variant=line]/tabs-list:rounded-none group-data-[variant=line]/tabs-list:text-body-sm";
65
63
  function TabsTrigger({ className, disabled, disabledReason, "aria-describedby": describedBy, ...props }) {
66
64
  const reasonId = React.useId();
67
65
  const description = [describedBy, disabledReason === undefined ? undefined : reasonId].filter(Boolean).join(" ") ||
@@ -74,91 +72,4 @@ function TabsTrigger({ className, disabled, disabledReason, "aria-describedby":
74
72
  function TabsContent({ className, ...props }) {
75
73
  return (_jsx(TabsPrimitive.Panel, { "data-slot": "tabs-content", className: cn("min-w-0 flex-1 text-sm outline-none", className), ...props }));
76
74
  }
77
- /** Which ends of a scrolled row hide links, so the row fades there to say more stand beyond. */
78
- function hiddenTabs(element) {
79
- const start = element.scrollLeft > 1;
80
- const end = element.scrollLeft + element.clientWidth < element.scrollWidth - 1;
81
- return start && end ? "both" : start ? "start" : end ? "end" : "none";
82
- }
83
- const HIDDEN_FADE = {
84
- none: undefined,
85
- start: "[mask-image:linear-gradient(to_right,transparent,black_2rem)]",
86
- end: "[mask-image:linear-gradient(to_left,transparent,black_2rem)]",
87
- both: "[mask-image:linear-gradient(to_right,transparent,black_2rem,black_calc(100%_-_2rem),transparent)]",
88
- };
89
- /**
90
- * Sibling views of one object, each with its own URL, under the top bar.
91
- *
92
- * @family Navigation
93
- * @when Sibling views of one object under the top bar, when each view has its own URL (an object's
94
- * sections), with `TabsLink` for each.
95
- * @instead Panels that switch in place are `Tabs`. A stable destination belongs in the `Sidebar`.
96
- * An object's ancestry is the `Breadcrumb`.
97
- * @behaviour "Reflect the active tab in the URL (query param or path) so deep-links and refresh restore state." (https://vercel.com/geist/tabs)
98
- * Ours: each view is its own URL, so a link carries it. Overflow scrolls sideways and brings the
99
- * current link into view, and the row fades out over 32 px at each end where links stand beyond it.
100
- * The current link takes the selection fill, or in `line` a 2 px ink underline over the row's 1 px
101
- * rule; the other links are muted until hover, with no hue. Sizes and spacing follow `Tabs`. The
102
- * row holds at most 7 links; in a `band`, which a phone scrolls sideways instead of holding
103
- * fewer, that is 7 at every width, as an Agent's six views do, and a `line` row follows the 7 and 4 cap of `Tabs`. The sub-pages of one object stand as the filled-pill row in a
104
- * `band` under the top bar, as Vercel draws a deployment's tabs: the band is this component's, with `above` for the
105
- * object's identity, so no page draws the border, the fill or the gutters around the row. The band
106
- * keeps the page's own column and gutter, and the first link's words start at the page title's edge,
107
- * its fill reaching into the gutter as Vercel's tabs do. The
108
- * `line` row has its own rule and takes no band.
109
- * @words "`tabs[].title` is Title Case, 1–2 words, and names the destination noun (`Overview`, `Logs`, `Settings`). Verbs belong on buttons; `View Logs` is wrong on a tab." (https://vercel.com/geist/tabs)
110
- * "Don’t append a count to the title (`Logs (12)`); use a badge slot instead and drop the badge at zero." (https://vercel.com/geist/tabs)
111
- * Ours: the title is sentence case (*Overview*, *Installations*), not Title Case. There is no badge
112
- * slot: a count belongs to the list's footer. A link has no icon. Italian scrolls, never wraps or
113
- * truncates.
114
- * @access "Label the tablist with `aria-label` when no visible heading sits above it (`aria-label="Sections"`)." (https://vercel.com/geist/tabs)
115
- * "Maintain a visible focus ring on the active tab; don’t suppress focus styles for visual polish." (https://vercel.com/geist/tabs)
116
- * Ours: a `nav` of links named by `aria-label` or `aria-labelledby`, which the type requires, with
117
- * `aria-current="page"` on the current one.
118
- */
119
- function TabsNav({ className, children, variant = "default", band = false, above, ...props }) {
120
- const navigation = React.useRef(null);
121
- const current = React.useRef(null);
122
- const [hidden, setHidden] = React.useState("none");
123
- React.useEffect(() => {
124
- const element = navigation.current;
125
- if (!element || typeof ResizeObserver === "undefined")
126
- return;
127
- const measure = () => setHidden(hiddenTabs(element));
128
- measure();
129
- const observer = new ResizeObserver(measure);
130
- observer.observe(element);
131
- element.addEventListener("scroll", measure, { passive: true });
132
- return () => {
133
- observer.disconnect();
134
- element.removeEventListener("scroll", measure);
135
- };
136
- }, []);
137
- React.useEffect(() => {
138
- const element = navigation.current;
139
- const link = element?.querySelector('[aria-current="page"]') ?? null;
140
- if (!element || link === current.current)
141
- return;
142
- current.current = link;
143
- if (link && element.scrollWidth > element.clientWidth) {
144
- link.scrollIntoView({ block: "nearest", inline: "nearest" });
145
- }
146
- });
147
- const row = (_jsx("nav", { ref: navigation, "data-slot": "tabs-nav", "data-variant": variant, className: cn("group/tabs-nav group/tabs-list min-w-0 overflow-x-auto", HIDDEN_FADE[hidden], variant === "line" && "pb-px shadow-[inset_0_-1px_0_0_var(--border)]", className), ...props, children: _jsx("ul", { className: "flex w-max min-w-full items-center gap-0 group-data-[variant=line]/tabs-nav:gap-6", children: children }) }));
148
- if (!band)
149
- return row;
150
- return (_jsx("div", { "data-slot": "tabs-nav-band", className: "border-b bg-background", children: _jsxs("div", { className: "mx-auto w-full max-w-7xl px-6", children: [above, _jsx("div", { className: "-mx-3 py-2", children: row })] }) }));
151
- }
152
- function TabsLink({ current = false, className, render, ...props }) {
153
- const link = useRender({
154
- defaultTagName: "a",
155
- render,
156
- props: mergeProps({
157
- "aria-current": current ? "page" : undefined,
158
- className: cn(tabShape, "group-data-[variant=line]/tabs-nav:-mb-px group-data-[variant=line]/tabs-nav:h-12.5 group-data-[variant=line]/tabs-nav:px-0.5", "group-data-[variant=default]/tabs-nav:aria-[current=page]:bg-selection group-data-[variant=default]/tabs-nav:aria-[current=page]:text-selection-foreground", "group-data-[variant=line]/tabs-nav:aria-[current=page]:text-foreground", "after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:bg-foreground after:opacity-0 group-data-[variant=line]/tabs-nav:aria-[current=page]:after:opacity-100", className),
159
- }, props),
160
- state: { slot: "tabs-link", current },
161
- });
162
- return _jsx("li", { className: "flex", children: link });
163
- }
164
- export { Tabs, TabsList, TabsTrigger, TabsContent, TabsNav, TabsLink, tabsListVariants };
75
+ export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
@@ -9,8 +9,7 @@ import { type VariantProps } from "class-variance-authority";
9
9
  * a secondary way out beside the content, such as a card header's *See everything*, which takes the
10
10
  * same blue treatment as `inline`; or a muted way to somewhere such as a footer's *Learn more*
11
11
  * (`quiet`).
12
- * @instead A command is a `Button`; a destination drawn as a button is a link with
13
- * `buttonVariants`. Going to a record from its row is the record's name in `RecordIdentity`.
12
+ * @instead A command is a `Button`; a destination drawn as a button is a `ButtonLink`. Going to a record from its row is the record's name in `RecordIdentity`.
14
13
  * Breadcrumb and back navigation are not text links: they keep their own quieter navigation
15
14
  * treatment.
16
15
  * @behaviour Classes only: the caller renders the real anchor or router link. `inline` thickens its
@@ -1 +1 @@
1
- {"version":3,"file":"text-link.d.ts","sourceRoot":"","sources":["../../src/components/text-link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,QAAA,MAAM,gBAAgB;;8EAYpB,CAAC;AAEH,KAAK,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"text-link.d.ts","sourceRoot":"","sources":["../../src/components/text-link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,QAAA,MAAM,gBAAgB;;8EAYpB,CAAC;AAEH,KAAK,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,CAAC"}
@@ -9,8 +9,7 @@ import { cva } from "class-variance-authority";
9
9
  * a secondary way out beside the content, such as a card header's *See everything*, which takes the
10
10
  * same blue treatment as `inline`; or a muted way to somewhere such as a footer's *Learn more*
11
11
  * (`quiet`).
12
- * @instead A command is a `Button`; a destination drawn as a button is a link with
13
- * `buttonVariants`. Going to a record from its row is the record's name in `RecordIdentity`.
12
+ * @instead A command is a `Button`; a destination drawn as a button is a `ButtonLink`. Going to a record from its row is the record's name in `RecordIdentity`.
14
13
  * Breadcrumb and back navigation are not text links: they keep their own quieter navigation
15
14
  * treatment.
16
15
  * @behaviour Classes only: the caller renders the real anchor or router link. `inline` thickens its
@@ -7,6 +7,8 @@ type TextareaProps = Omit<React.ComponentProps<"textarea">, "size"> & {
7
7
  description?: string;
8
8
  /** The message under the box, in the product's words; it also marks the box invalid. */
9
9
  error?: string;
10
+ /** One control in the box's bottom-end corner, inside its ring: a prompt's Ask. */
11
+ action?: React.ReactNode;
10
12
  } & FieldName;
11
13
  /**
12
14
  * Several lines of free text that grow with their content.
@@ -32,7 +34,8 @@ type TextareaProps = Omit<React.ComponentProps<"textarea">, "size"> & {
32
34
  * newlines don’t pass a `required` check." (https://vercel.com/geist/textarea) Ours: typing keeps
33
35
  * every space and newline; the save of `FormDialog`, `FormDrawer`, `RowEditForm` and
34
36
  * `SettingsSection` trims the ends (see `Field`). A character count shows only when a real limit
35
- * exists.
37
+ * exists. `action` puts one control in the bottom-end corner inside the box's ring, as a prompt's
38
+ * Ask sits under what was typed.
36
39
  * @words "Labels are short Title Case nouns (`Description`, `Release Notes`); placeholders show an
37
40
  * example value, not instructions like `Enter a description`." (https://vercel.com/geist/textarea)
38
41
  * "Validation names the field and constraint, ends in a period, and skips `please` (`Description is
@@ -44,6 +47,6 @@ type TextareaProps = Omit<React.ComponentProps<"textarea">, "size"> & {
44
47
  * @access A visible label tied by `id`, or `aria-label`; the error through `aria-describedby`. In a
45
48
  * dialog, the footer's Save stays reachable while the box grows.
46
49
  */
47
- declare function Textarea({ label, description, error, size, className, ...props }: TextareaProps): React.JSX.Element;
50
+ declare function Textarea({ label, description, error, size, action, className, ...props }: TextareaProps): React.JSX.Element;
48
51
  export { Textarea };
49
52
  //# sourceMappingURL=textarea.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAqB7F,KAAK,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,GAAG;IACpE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,SAAS,CAAC;AAEd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,WAAW,EACX,KAAK,EACL,IAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,aAAa,qBAgBf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"textarea.d.ts","sourceRoot":"","sources":["../../src/components/textarea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAyC,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAqB7F,KAAK,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,GAAG;IACpE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,GAAG,SAAS,CAAC;AAKd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,WAAW,EACX,KAAK,EACL,IAAgB,EAChB,MAAM,EACN,SAAS,EACT,GAAG,KAAK,EACT,EAAE,aAAa,qBA2Bf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1,6 +1,7 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cva } from "class-variance-authority";
3
3
  import { cn } from "../lib/utils.js";
4
+ import { InputGroup, InputGroupAddon } from "./input-group.js";
4
5
  import { FieldFrame } from "../internal/field-frame.js";
5
6
  import { fieldDisabled, fieldRing, fieldStates } from "../internal/input-box.js";
6
7
  const textareaVariants = cva([
@@ -18,6 +19,7 @@ const textareaVariants = cva([
18
19
  },
19
20
  defaultVariants: { size: "default" },
20
21
  });
22
+ const inGroup = "flex-1 resize-none rounded-none bg-transparent shadow-none focus-visible:outline-none disabled:bg-transparent aria-invalid:outline-none";
21
23
  /**
22
24
  * Several lines of free text that grow with their content.
23
25
  *
@@ -42,7 +44,8 @@ const textareaVariants = cva([
42
44
  * newlines don’t pass a `required` check." (https://vercel.com/geist/textarea) Ours: typing keeps
43
45
  * every space and newline; the save of `FormDialog`, `FormDrawer`, `RowEditForm` and
44
46
  * `SettingsSection` trims the ends (see `Field`). A character count shows only when a real limit
45
- * exists.
47
+ * exists. `action` puts one control in the bottom-end corner inside the box's ring, as a prompt's
48
+ * Ask sits under what was typed.
46
49
  * @words "Labels are short Title Case nouns (`Description`, `Release Notes`); placeholders show an
47
50
  * example value, not instructions like `Enter a description`." (https://vercel.com/geist/textarea)
48
51
  * "Validation names the field and constraint, ends in a period, and skips `please` (`Description is
@@ -54,7 +57,12 @@ const textareaVariants = cva([
54
57
  * @access A visible label tied by `id`, or `aria-label`; the error through `aria-describedby`. In a
55
58
  * dialog, the footer's Save stays reachable while the box grows.
56
59
  */
57
- function Textarea({ label, description, error, size = "default", className, ...props }) {
58
- return (_jsx(FieldFrame, { label: label, description: description, error: error, size: size, control: props, children: (aria) => (_jsx("textarea", { "data-slot": "textarea", "data-nc-ui": "", "data-size": size, "data-field-frame": "", className: cn(textareaVariants({ size }), className), ...props, ...aria })) }));
60
+ function Textarea({ label, description, error, size = "default", action, className, ...props }) {
61
+ return (_jsx(FieldFrame, { label: label, description: description, error: error, size: size, control: props, children: (aria) => {
62
+ const box = (_jsx("textarea", { "data-slot": action === undefined ? "textarea" : "input-group-control", "data-nc-ui": "", "data-size": size, "data-field-frame": "", className: cn(textareaVariants({ size }), action !== undefined && inGroup, className), ...props, ...aria }));
63
+ if (action === undefined)
64
+ return box;
65
+ return (_jsxs(InputGroup, { size: size, children: [box, _jsx(InputGroupAddon, { align: "block-end", className: "justify-end", children: action })] }));
66
+ } }));
59
67
  }
60
68
  export { Textarea };
@@ -1,5 +1,7 @@
1
1
  import { type ResolvedMessage } from "./product-message.js";
2
2
  export type MessageToastTone = "success" | "info" | "warning" | "error";
3
+ /** Takes down every toast on screen, such as between two tests that share the toaster. */
4
+ export declare function dismissToasts(): void;
3
5
  export declare function showMessageToast(message: ResolvedMessage, options: {
4
6
  tone: MessageToastTone;
5
7
  id?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../src/components/toast.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAExE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,IAAI,CAON"}
1
+ {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../src/components/toast.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAExE,0FAA0F;AAC1F,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,IAAI,CAON"}
@@ -2,6 +2,10 @@
2
2
  // a string, so sonner is imported here and nowhere else.
3
3
  import { toast } from "sonner";
4
4
  import { bodyBeyondTitle } from "./product-message.js";
5
+ /** Takes down every toast on screen, such as between two tests that share the toaster. */
6
+ export function dismissToasts() {
7
+ toast.dismiss();
8
+ }
5
9
  export function showMessageToast(message, options) {
6
10
  const action = message.actions.find((command) => command.onClick !== undefined);
7
11
  toast[options.tone](message.title, {
@@ -36,7 +36,9 @@ type ToggleGroupMemberName = {
36
36
  * *Reasoning*.
37
37
  * @access `role="group"` with a name; each member a button with `aria-pressed`.
38
38
  */
39
- declare function ToggleGroup({ className, variant, size, spacing, orientation, style, children, ...props }: Omit<ToggleGroupPrimitive.Props, "aria-label" | "aria-labelledby"> & ToggleGroupName & VariantProps<typeof toggleVariants> & {
39
+ declare function ToggleGroup({ className, variant, size, spacing, orientation, style, children, ...props }: Omit<ToggleGroupPrimitive.Props, "aria-label" | "aria-labelledby" | "style"> & {
40
+ style?: React.CSSProperties;
41
+ } & ToggleGroupName & VariantProps<typeof toggleVariants> & {
40
42
  spacing?: number;
41
43
  orientation?: "horizontal" | "vertical";
42
44
  }): React.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"toggle-group.d.ts","sourceRoot":"","sources":["../../src/components/toggle-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAcrD,KAAK,eAAe,GAChB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5D,KAAK,qBAAqB,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAW,EACX,WAA0B,EAC1B,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAAC,GACnE,eAAe,GACf,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC,qBA4BF;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,QAAQ,EACR,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,GACxC,qBAAqB,GACrB,YAAY,CAAC,OAAO,cAAc,CAAC,qBAuBpC;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"toggle-group.d.ts","sourceRoot":"","sources":["../../src/components/toggle-group.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAI7D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAcrD,KAAK,eAAe,GAChB;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,iBAAiB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE5D,KAAK,qBAAqB,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC;AAEzD;;;;;;;;;;;;;;;;;;GAkBG;AACH,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAW,EACX,WAA0B,EAC1B,KAAK,EACL,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC,GAAG;IAChF,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,GAAG,eAAe,GACjB,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC,qBAyBF;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,QAAQ,EACR,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,GACxC,qBAAqB,GACrB,YAAY,CAAC,OAAO,cAAc,CAAC,qBAuBpC;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC"}
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
5
5
  import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group";
6
6
  import { cn } from "../lib/utils.js";
7
+ import { cssVariables } from "../lib/css-variables.js";
7
8
  import { toggleVariants } from "./toggle.js";
8
9
  const ToggleGroupContext = React.createContext({
9
10
  size: "default",
@@ -31,12 +32,8 @@ const ToggleGroupContext = React.createContext({
31
32
  * @access `role="group"` with a name; each member a button with `aria-pressed`.
32
33
  */
33
34
  function ToggleGroup({ className, variant, size, spacing = 2, orientation = "horizontal", style, children, ...props }) {
34
- return (_jsx(ToggleGroupPrimitive, { "data-slot": "toggle-group", "data-nc-ui": "", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation, orientation: orientation,
35
- // SAFETY: CSSProperties lists only standard properties; React sets each `--` custom property key here through style.setProperty.
36
- style: {
37
- ...style,
38
- "--gap": spacing,
39
- }, className: cn("group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-sm data-vertical:flex-col data-vertical:items-stretch", className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: { variant, size, spacing, orientation }, children: children }) }));
35
+ const groupContext = React.useMemo(() => ({ variant, size, spacing, orientation }), [variant, size, spacing, orientation]);
36
+ return (_jsx(ToggleGroupPrimitive, { "data-slot": "toggle-group", "data-nc-ui": "", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation, orientation: orientation, style: cssVariables({ ...style, "--gap": spacing }), className: cn("group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-sm data-vertical:flex-col data-vertical:items-stretch", className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: groupContext, children: children }) }));
40
37
  }
41
38
  function ToggleGroupItem({ className, children, variant = "default", size = "default", ...props }) {
42
39
  const context = React.useContext(ToggleGroupContext);
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Toggle as TogglePrimitive } from "@base-ui/react/toggle";
4
4
  import { cva } from "class-variance-authority";
5
5
  import { cn } from "../lib/utils.js";
6
- const toggleVariants = cva("group/toggle inline-flex has-[>svg:only-child]:aspect-square has-[>svg:only-child]:px-0 min-h-touch-target min-w-touch-target items-center justify-center gap-1 rounded-sm border border-transparent text-button font-medium whitespace-nowrap transition-[background-color,border-color,color,opacity] duration-[var(--nc-duration-confirm)] ease-[var(--nc-ease-out-strong)] hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-pressed:bg-accent aria-pressed:font-semibold aria-pressed:text-accent-foreground data-pressed:bg-accent data-pressed:font-semibold data-pressed:text-accent-foreground [@media(hover:hover)_and_(pointer:fine)]:min-h-0 [@media(hover:hover)_and_(pointer:fine)]:min-w-0 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
6
+ const toggleVariants = cva("group/toggle inline-flex has-[>svg:only-child]:aspect-square has-[>svg:only-child]:px-0 min-h-touch-target min-w-touch-target items-center justify-center gap-1 rounded-sm border border-transparent text-button font-medium whitespace-nowrap nc-transition-paint hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-pressed:bg-accent aria-pressed:font-semibold aria-pressed:text-accent-foreground data-pressed:bg-accent data-pressed:font-semibold data-pressed:text-accent-foreground [@media(hover:hover)_and_(pointer:fine)]:min-h-0 [@media(hover:hover)_and_(pointer:fine)]:min-w-0 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
7
7
  variants: {
8
8
  variant: {
9
9
  default: "bg-transparent",
@@ -1,5 +1,6 @@
1
1
  import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
2
- import type { PresentContent } from "../internal/present-content.js";
2
+ import { type KbdProps } from "./kbd.js";
3
+ import { type TooltipContentFrameProps } from "../internal/tooltip-content-frame.js";
3
4
  declare function TooltipProvider({ delay, ...props }: TooltipPrimitive.Provider.Props): import("react").JSX.Element;
4
5
  /**
5
6
  * A short, optional fact about its trigger.
@@ -28,9 +29,10 @@ declare function TooltipProvider({ delay, ...props }: TooltipPrimitive.Provider.
28
29
  * wide, 13 px text balanced over its lines. Never interactive. `arrow={false}` drops the stem (Geist's
29
30
  * `tip={false}`); `centerText={false}` left-aligns a tooltip that wraps (Geist's `center={false}`).
30
31
  * Geist's coloured `type` is not provided. `TooltipContent` requires its text as
31
- * children. Colour: one inverted neutral, the page's ink as the fill and its surface as the
32
- * text, with a stem of the same fill and no hue, in both themes; a shortcut is a `Kbd` after the
33
- * text, drawn 20 px high.
32
+ * children, one string, so no control, link or second overlay fits inside it. Colour: one
33
+ * inverted neutral, the page's ink as the fill and its surface as the text, with a stem of the
34
+ * same fill and no hue, in both themes; a shortcut is `shortcut`, the `Kbd`'s props, drawn as a
35
+ * `Kbd` after the text, 20 px high.
34
36
  * @words "One sentence or fragment in `text`." "Sentence case, no period for a single fragment."
35
37
  * "Skip tooltips that repeat the visible label (`text="Rate Limit"` on a `Rate Limit` button) or
36
38
  * describe the interaction (`text="Click to override"`)." "Lifecycle Tooltips follow `{Label}:
@@ -41,15 +43,13 @@ declare function TooltipProvider({ delay, ...props }: TooltipPrimitive.Provider.
41
43
  * context, it doesn’t replace the label." "Escape closes the tooltip and returns focus to the
42
44
  * trigger." (https://vercel.com/geist/tooltip)
43
45
  */
44
- declare function Tooltip({ ...props }: TooltipPrimitive.Root.Props): import("react").JSX.Element;
46
+ declare function Tooltip({ ...props }: Omit<TooltipPrimitive.Root.Props, "defaultOpen">): import("react").JSX.Element;
45
47
  declare function TooltipTrigger({ delay, ...props }: TooltipPrimitive.Trigger.Props): import("react").JSX.Element;
46
- declare function TooltipContent({ className, side, sideOffset, align, alignOffset, arrow, centerText, children, ...props }: TooltipPrimitive.Popup.Props & Pick<TooltipPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset"> & {
47
- /** The text of the tooltip; a tooltip without one does not compile. */
48
- children: PresentContent;
49
- /** The stem pointing at the trigger; `false` for a tooltip that sits against it. */
50
- arrow?: boolean;
51
- /** Centres the text of a tooltip that wraps; `false` left-aligns it. */
52
- centerText?: boolean;
48
+ declare function TooltipContent({ children, shortcut, ...props }: Omit<TooltipContentFrameProps, "children"> & {
49
+ /** The text of the tooltip: words only, so no control or second overlay fits inside it. */
50
+ children: string;
51
+ /** The key that runs the trigger's command, drawn as a `Kbd` after the text. */
52
+ shortcut?: KbdProps;
53
53
  }): import("react").JSX.Element;
54
54
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
55
55
  //# sourceMappingURL=tooltip.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/components/tooltip.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAIrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAQjE,iBAAS,eAAe,CAAC,EAAE,KAAqB,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAAK,+BAM5F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,iBAAS,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,CAAC,IAAI,CAAC,KAAK,+BAEzD;AAED,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,+BAS1E;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,IAAY,EACZ,UAAe,EACf,KAAgB,EAChB,WAAe,EACf,KAAY,EACZ,UAAiB,EACjB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,GAC7B,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,GAAG;IACzF,uEAAuE;IACvE,QAAQ,EAAE,cAAc,CAAC;IACzB,oFAAoF;IACpF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,+BA+BF;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/components/tooltip.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAGrE,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,kCAAkC,CAAC;AAM1C,iBAAS,eAAe,CAAC,EAAE,KAAqB,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,KAAK,+BAM5F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,iBAAS,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,+BAE9E;AAED,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,+BAS1E;AAED,iBAAS,cAAc,CAAC,EACtB,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,CAAC,GAAG;IAC9C,2FAA2F;IAC3F,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,+BAYA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC"}
@@ -1,10 +1,9 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
4
4
  import { createContext, useContext } from "react";
5
- import { overlayStem, OverlayStemShape } from "../internal/overlay-stem.js";
6
- import { cn } from "../lib/utils.js";
7
- import { anchoredOverlayMotion } from "../lib/motion.js";
5
+ import { Kbd } from "./kbd.js";
6
+ import { TooltipContentFrame, } from "../internal/tooltip-content-frame.js";
8
7
  const TOOLTIP_DELAY = 150;
9
8
  const TooltipDelay = createContext(TOOLTIP_DELAY);
10
9
  function TooltipProvider({ delay = TOOLTIP_DELAY, ...props }) {
@@ -37,9 +36,10 @@ function TooltipProvider({ delay = TOOLTIP_DELAY, ...props }) {
37
36
  * wide, 13 px text balanced over its lines. Never interactive. `arrow={false}` drops the stem (Geist's
38
37
  * `tip={false}`); `centerText={false}` left-aligns a tooltip that wraps (Geist's `center={false}`).
39
38
  * Geist's coloured `type` is not provided. `TooltipContent` requires its text as
40
- * children. Colour: one inverted neutral, the page's ink as the fill and its surface as the
41
- * text, with a stem of the same fill and no hue, in both themes; a shortcut is a `Kbd` after the
42
- * text, drawn 20 px high.
39
+ * children, one string, so no control, link or second overlay fits inside it. Colour: one
40
+ * inverted neutral, the page's ink as the fill and its surface as the text, with a stem of the
41
+ * same fill and no hue, in both themes; a shortcut is `shortcut`, the `Kbd`'s props, drawn as a
42
+ * `Kbd` after the text, 20 px high.
43
43
  * @words "One sentence or fragment in `text`." "Sentence case, no period for a single fragment."
44
44
  * "Skip tooltips that repeat the visible label (`text="Rate Limit"` on a `Rate Limit` button) or
45
45
  * describe the interaction (`text="Click to override"`)." "Lifecycle Tooltips follow `{Label}:
@@ -57,7 +57,7 @@ function TooltipTrigger({ delay, ...props }) {
57
57
  const inheritedDelay = useContext(TooltipDelay);
58
58
  return (_jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", delay: delay ?? inheritedDelay, ...props }));
59
59
  }
60
- function TooltipContent({ className, side = "top", sideOffset = 10, align = "center", alignOffset = 0, arrow = true, centerText = true, children, ...props }) {
61
- return (_jsx(TooltipPrimitive.Portal, { children: _jsx(TooltipPrimitive.Positioner, { align: align, alignOffset: alignOffset, side: side, sideOffset: sideOffset, className: "isolate z-50", children: _jsxs(TooltipPrimitive.Popup, { "data-slot": "tooltip-content", "data-nc-ui": "", className: cn("z-50 w-fit max-w-62.5 rounded-md border-0 bg-foreground px-nadicode-xs py-1.5 text-body-compact text-balance text-background nc-elevation-floating has-data-[slot=kbd]:inline-flex has-data-[slot=kbd]:items-center has-data-[slot=kbd]:gap-1 has-data-[slot=kbd]:pr-1.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:h-5 **:data-[slot=kbd]:min-w-5 **:data-[slot=kbd]:text-caption **:data-[slot=kbd]:leading-5", centerText ? "text-center" : "text-left", anchoredOverlayMotion, className), ...props, children: [children, arrow ? (_jsx(TooltipPrimitive.Arrow, { className: cn(overlayStem, "[&_path]:fill-foreground"), children: _jsx(OverlayStemShape, {}) })) : null] }) }) }));
60
+ function TooltipContent({ children, shortcut, ...props }) {
61
+ return (_jsxs(TooltipContentFrame, { ...props, children: [children, shortcut ? (_jsxs(_Fragment, { children: [" ", _jsx(Kbd, { ...shortcut })] })) : null] }));
62
62
  }
63
63
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MinusIcon, TrendingDownIcon, TrendingUpIcon } from "lucide-react";
3
- import { Badge } from "./badge.js";
3
+ import { BadgeFrame } from "../internal/badge-frame.js";
4
4
  const TREND_ICONS = {
5
5
  up: TrendingUpIcon,
6
6
  down: TrendingDownIcon,
@@ -34,6 +34,6 @@ function trendTone(direction, upIsGood = true, neutral = false) {
34
34
  */
35
35
  function TrendBadge({ value, direction, tone, directionLabel, }) {
36
36
  const Icon = TREND_ICONS[direction];
37
- return (_jsxs(Badge, { "data-slot": "trend-badge", "data-direction": direction, "data-tone": tone, variant: "outline", className: "tabular-nums", icon: _jsx(Icon, { "aria-hidden": "true", className: TREND_TONE_CLASS[tone] }), children: [_jsx("span", { className: "sr-only", children: directionLabel }), value] }));
37
+ return (_jsxs(BadgeFrame, { "data-slot": "trend-badge", "data-direction": direction, "data-tone": tone, variant: "outline", className: "tabular-nums", icon: _jsx(Icon, { "aria-hidden": "true", className: TREND_TONE_CLASS[tone] }), children: [_jsx("span", { className: "sr-only", children: directionLabel }), value] }));
38
38
  }
39
39
  export { TrendBadge, trendTone };