@godxjp/ui 31.31.7 → 32.0.0

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 (728) hide show
  1. package/README.md +102 -121
  2. package/agent/START-HERE.md +10 -10
  3. package/agent/components/Accordion.json +2 -2
  4. package/agent/components/AccountChip.json +1 -1
  5. package/agent/components/Actions.json +1 -1
  6. package/agent/components/Activity.json +2 -2
  7. package/agent/components/Affix.json +1 -1
  8. package/agent/components/Alert.json +22 -6
  9. package/agent/components/AlertDialog.json +8 -1
  10. package/agent/components/Anchor.json +4 -3
  11. package/agent/components/AppLauncher.json +2 -2
  12. package/agent/components/AppProvider.json +19 -11
  13. package/agent/components/AppSettingPicker.json +18 -2
  14. package/agent/components/AppShell.json +4 -5
  15. package/agent/components/AreaChart.json +0 -1
  16. package/agent/components/AspectRatio.json +2 -2
  17. package/agent/components/Attachments.json +3 -3
  18. package/agent/components/AuthAccountSummary.json +1 -1
  19. package/agent/components/AuthDivider.json +1 -1
  20. package/agent/components/AuthExpiryProvider.json +0 -1
  21. package/agent/components/AuthFooter.json +2 -2
  22. package/agent/components/AuthIdentity.json +3 -3
  23. package/agent/components/AuthStack.json +1 -1
  24. package/agent/components/Avatar.json +2 -12
  25. package/agent/components/Badge.json +1 -1
  26. package/agent/components/BarChart.json +0 -1
  27. package/agent/components/BranchScopePicker.json +1 -1
  28. package/agent/components/Breadcrumb.json +1 -1
  29. package/agent/components/Button.json +3 -3
  30. package/agent/components/Calendar.json +1 -1
  31. package/agent/components/Card.json +2 -2
  32. package/agent/components/CardBar.json +0 -1
  33. package/agent/components/CardContent.json +0 -1
  34. package/agent/components/Carousel.json +4 -3
  35. package/agent/components/Cascader.json +1 -1
  36. package/agent/components/CenteredShell.json +78 -17
  37. package/agent/components/ChatBubble.json +3 -3
  38. package/agent/components/ChatBubbleList.json +3 -3
  39. package/agent/components/ChatComposer.json +3 -3
  40. package/agent/components/ChatSuggestion.json +3 -3
  41. package/agent/components/Checkbox.json +1 -1
  42. package/agent/components/CheckboxGroup.json +0 -1
  43. package/agent/components/CodeBlock.json +1 -1
  44. package/agent/components/Collapsible.json +4 -4
  45. package/agent/components/ColorPicker.json +1 -1
  46. package/agent/components/Command.json +5 -5
  47. package/agent/components/CommandPalette.json +1 -1
  48. package/agent/components/CompactBarTrend.json +1 -1
  49. package/agent/components/Conversations.json +3 -3
  50. package/agent/components/CredentialReveal.json +1 -1
  51. package/agent/components/DataState.json +2 -2
  52. package/agent/components/DataTable.json +1 -1
  53. package/agent/components/DatePicker.json +1 -1
  54. package/agent/components/Descriptions.json +1 -1
  55. package/agent/components/Dialog.json +2 -2
  56. package/agent/components/DraggablePanel.json +5 -4
  57. package/agent/components/DropdownMenu.json +1 -1
  58. package/agent/components/EmojiPicker.json +3 -2
  59. package/agent/components/EmptyState.json +1 -1
  60. package/agent/components/ErrorSurface.json +3 -3
  61. package/agent/components/FeatureList.json +1 -1
  62. package/agent/components/Field.json +0 -1
  63. package/agent/components/Flex.json +34 -4
  64. package/agent/components/FloatButton.json +6 -5
  65. package/agent/components/Form.json +1 -1
  66. package/agent/components/FormErrors.json +0 -1
  67. package/agent/components/FormField.json +6 -6
  68. package/agent/components/FormFieldArray.json +0 -1
  69. package/agent/components/FormFieldControl.json +0 -1
  70. package/agent/components/FormRoot.json +1 -1
  71. package/agent/components/Heading.json +3 -0
  72. package/agent/components/Icon.json +1 -1
  73. package/agent/components/Image.json +7 -4
  74. package/agent/components/InfiniteQueryState.json +1 -1
  75. package/agent/components/Input.json +1 -1
  76. package/agent/components/InputOTP.json +2 -2
  77. package/agent/components/Label.json +3 -3
  78. package/agent/components/LegalDocumentShell.json +5 -4
  79. package/agent/components/Legend.json +1 -1
  80. package/agent/components/LineChart.json +0 -1
  81. package/agent/components/Link.json +0 -1
  82. package/agent/components/ListRow.json +1 -1
  83. package/agent/components/Logo.json +5 -4
  84. package/agent/components/Marquee.json +4 -3
  85. package/agent/components/Masonry.json +4 -3
  86. package/agent/components/MasterDetail.json +1 -1
  87. package/agent/components/MegaMenu.json +4 -3
  88. package/agent/components/MobileShell.json +4 -4
  89. package/agent/components/NavList.json +1 -1
  90. package/agent/components/NumberInput.json +1 -1
  91. package/agent/components/OrgChart.json +4 -3
  92. package/agent/components/OrgSwitcher.json +1 -1
  93. package/agent/components/OverlayPortalProvider.json +0 -1
  94. package/agent/components/PageContainer.json +3 -3
  95. package/agent/components/PageCover.json +3 -2
  96. package/agent/components/Pagination.json +1 -1
  97. package/agent/components/PasswordInput.json +1 -1
  98. package/agent/components/PasswordStrength.json +1 -1
  99. package/agent/components/PermissionMatrix.json +1 -1
  100. package/agent/components/PieChart.json +0 -1
  101. package/agent/components/Popover.json +31 -6
  102. package/agent/components/PrefetchLink.json +1 -1
  103. package/agent/components/Progress.json +1 -1
  104. package/agent/components/Prose.json +1 -1
  105. package/agent/components/QrCode.json +1 -1
  106. package/agent/components/Radio.json +0 -1
  107. package/agent/components/RadioGroup.json +2 -2
  108. package/agent/components/RangeTimeline.json +2 -1
  109. package/agent/components/Rating.json +1 -1
  110. package/agent/components/RecordPicker.json +1 -1
  111. package/agent/components/ResizablePanel.json +1 -1
  112. package/agent/components/ResponsiveGrid.json +2 -2
  113. package/agent/components/Reveal.json +3 -3
  114. package/agent/components/ScrollArea.json +2 -2
  115. package/agent/components/SearchInput.json +1 -1
  116. package/agent/components/Segmented.json +1 -1
  117. package/agent/components/Select.json +7 -5
  118. package/agent/components/Separator.json +1 -1
  119. package/agent/components/ServiceCatalogCta.json +0 -1
  120. package/agent/components/ServiceLauncherCard.json +1 -1
  121. package/agent/components/ServiceRolePanel.json +1 -1
  122. package/agent/components/Sheet.json +5 -5
  123. package/agent/components/Sidebar.json +1 -1
  124. package/agent/components/Skeleton.json +26 -12
  125. package/agent/components/Slider.json +2 -2
  126. package/agent/components/SortableList.json +3 -2
  127. package/agent/components/SplitPane.json +1 -1
  128. package/agent/components/StatCard.json +1 -1
  129. package/agent/components/Steps.json +1 -1
  130. package/agent/components/Swatch.json +1 -1
  131. package/agent/components/Switch.json +1 -1
  132. package/agent/components/Table.json +1 -1
  133. package/agent/components/Tabs.json +3 -3
  134. package/agent/components/Text.json +5 -1
  135. package/agent/components/TextDiff.json +5 -4
  136. package/agent/components/Textarea.json +1 -1
  137. package/agent/components/ThemeScope.json +1 -1
  138. package/agent/components/ThoughtChain.json +3 -3
  139. package/agent/components/TimePicker.json +1 -1
  140. package/agent/components/Timeline.json +1 -1
  141. package/agent/components/TimelineGrid.json +5 -4
  142. package/agent/components/Toaster.json +0 -1
  143. package/agent/components/Toggle.json +3 -3
  144. package/agent/components/ToggleGroup.json +1 -1
  145. package/agent/components/Toolbar.json +10 -3
  146. package/agent/components/Tooltip.json +9 -9
  147. package/agent/components/Topbar.json +1 -1
  148. package/agent/components/TopbarItem.json +1 -1
  149. package/agent/components/Transfer.json +2 -2
  150. package/agent/components/Tree.json +1 -1
  151. package/agent/components/TreeSelect.json +1 -1
  152. package/agent/components/TwoFactorSetup.json +1 -1
  153. package/agent/components/Upload.json +1 -1
  154. package/agent/components/UploadCropDialog.json +1 -1
  155. package/agent/components/Welcome.json +3 -3
  156. package/agent/components/formatDate.json +2 -2
  157. package/agent/components/inertiaUpload.json +0 -1
  158. package/agent/components/useZodForm.json +0 -1
  159. package/agent/components-index.json +80 -154
  160. package/agent/components.json +541 -1737
  161. package/agent/index.json +10 -10
  162. package/agent/llms.txt +9 -9
  163. package/agent/patterns/account-recovery-settings.json +1 -1
  164. package/agent/patterns/auth-recovery-panels.json +2 -2
  165. package/agent/patterns/error-pages.json +1 -1
  166. package/agent/patterns/pricing-plans.json +17 -0
  167. package/agent/patterns-index.json +17 -1
  168. package/agent/patterns.json +21 -4
  169. package/agent/rules.json +30 -65
  170. package/agent/tokens.json +27 -57
  171. package/agent/vocabulary.json +3 -3
  172. package/dist/app/app-provider.d.ts +5 -3
  173. package/dist/app/app-provider.js +47 -12
  174. package/dist/app/date-format-labels.d.ts +3 -1
  175. package/dist/app/date-format-labels.js +2 -4
  176. package/dist/app/date-formats.d.ts +21 -2
  177. package/dist/app/date-formats.js +51 -2
  178. package/dist/app/index.d.ts +3 -1
  179. package/dist/app/index.js +5 -0
  180. package/dist/app/locales.d.ts +58 -3
  181. package/dist/app/locales.js +134 -8
  182. package/dist/app/preset.d.ts +25 -0
  183. package/dist/app/preset.js +10 -0
  184. package/dist/app/request-headers.d.ts +3 -3
  185. package/dist/app/request-headers.js +19 -10
  186. package/dist/app/settings-scope.d.ts +54 -0
  187. package/dist/app/settings-scope.js +46 -0
  188. package/dist/app/tenant-theme.js +8 -3
  189. package/dist/app/time-format-labels.d.ts +4 -1
  190. package/dist/app/time-format-labels.js +7 -1
  191. package/dist/app/types.d.ts +10 -2
  192. package/dist/app/use-formatting.d.ts +1 -1
  193. package/dist/components/admin/index.d.ts +1 -1
  194. package/dist/components/admin/index.js +1 -1
  195. package/dist/components/data-display/accordion.d.ts +51 -1
  196. package/dist/components/data-display/accordion.js +247 -1
  197. package/dist/components/data-display/avatar.d.ts +16 -1
  198. package/dist/components/data-display/avatar.js +109 -1
  199. package/dist/components/data-display/credential-reveal.d.ts +9 -2
  200. package/dist/components/data-display/credential-reveal.js +156 -1
  201. package/dist/components/data-display/image.js +5 -3
  202. package/dist/components/data-display/index.d.ts +0 -21
  203. package/dist/components/data-display/index.js +1 -43
  204. package/dist/components/data-display/popover.d.ts +15 -3
  205. package/dist/components/data-display/popover.js +168 -2
  206. package/dist/components/data-entry/branch-scope-picker.d.ts +1 -1
  207. package/dist/components/data-entry/index.d.ts +5 -12
  208. package/dist/components/data-entry/index.js +11 -12
  209. package/dist/components/data-entry/input-otp.d.ts +48 -2
  210. package/dist/components/data-entry/input-otp.js +94 -1
  211. package/dist/components/data-entry/number-input.d.ts +1 -1
  212. package/dist/components/data-entry/password-input.d.ts +38 -2
  213. package/dist/components/data-entry/password-input.js +56 -1
  214. package/dist/components/data-entry/rating.d.ts +38 -2
  215. package/dist/components/data-entry/rating.js +127 -1
  216. package/dist/components/data-entry/segmented.d.ts +94 -2
  217. package/dist/components/data-entry/segmented.js +104 -1
  218. package/dist/components/{ui/tag-input.d.ts → data-entry/select-tags-inline.d.ts} +7 -4
  219. package/dist/components/{ui/tag-input.js → data-entry/select-tags-inline.js} +4 -4
  220. package/dist/components/data-entry/select.js +4 -0
  221. package/dist/components/data-entry/toggle-group.d.ts +108 -2
  222. package/dist/components/data-entry/toggle-group.js +189 -1
  223. package/dist/components/data-entry/toggle.d.ts +86 -2
  224. package/dist/components/data-entry/toggle.js +153 -2
  225. package/dist/components/feedback/alert.d.ts +5 -3
  226. package/dist/components/feedback/alert.js +14 -2
  227. package/dist/components/feedback/index.d.ts +2 -6
  228. package/dist/components/feedback/index.js +1 -13
  229. package/dist/components/feedback/skeleton.d.ts +4 -17
  230. package/dist/components/feedback/skeleton.js +3 -40
  231. package/dist/components/general/index.d.ts +2 -4
  232. package/dist/components/general/index.js +1 -6
  233. package/dist/components/general/typography.d.ts +4 -58
  234. package/dist/components/general/typography.js +7 -141
  235. package/dist/components/layout/aspect-ratio.d.ts +24 -1
  236. package/dist/components/layout/aspect-ratio.js +18 -1
  237. package/dist/components/layout/auth-divider.js +1 -1
  238. package/dist/components/layout/auth-identity.js +6 -2
  239. package/dist/components/layout/centered-shell.d.ts +13 -8
  240. package/dist/components/layout/centered-shell.js +43 -1
  241. package/dist/components/layout/flex.d.ts +1 -1
  242. package/dist/components/layout/flex.js +73 -1
  243. package/dist/components/layout/index.d.ts +1 -13
  244. package/dist/components/layout/index.js +0 -12
  245. package/dist/components/layout/separator.d.ts +25 -2
  246. package/dist/components/layout/separator.js +71 -1
  247. package/dist/components/navigation/{app-setting-toggle.d.ts → app-setting-cycle.d.ts} +3 -4
  248. package/dist/components/navigation/{app-setting-toggle.js → app-setting-cycle.js} +3 -3
  249. package/dist/components/navigation/app-setting-picker.d.ts +6 -2
  250. package/dist/components/navigation/app-setting-picker.js +20 -2
  251. package/dist/components/navigation/index.d.ts +3 -11
  252. package/dist/components/navigation/index.js +1 -9
  253. package/dist/components/navigation/tabs.js +1 -1
  254. package/dist/components/ui/carousel.d.ts +1 -1
  255. package/dist/components/ui/carousel.js +1 -1
  256. package/dist/components/ui/index.d.ts +11 -5
  257. package/dist/components/ui/index.js +5 -5
  258. package/dist/contracts/measurement.json +2 -2
  259. package/dist/email/brand-mark.d.ts +3 -2
  260. package/dist/email/brand-mark.js +1 -1
  261. package/dist/email/tokens.generated.d.ts +6 -6
  262. package/dist/email/tokens.generated.js +6 -6
  263. package/dist/i18n/locale-tags.d.ts +25 -0
  264. package/dist/i18n/locale-tags.js +59 -0
  265. package/dist/i18n/translate.d.ts +20 -3
  266. package/dist/i18n/translate.js +25 -14
  267. package/dist/i18n/use-translation.d.ts +3 -3
  268. package/dist/i18n/use-translation.js +4 -2
  269. package/dist/{components/navigation → lab}/anchor.d.ts +2 -2
  270. package/dist/{components/navigation → lab}/anchor.js +5 -5
  271. package/dist/{components/data-display → lab}/carousel.js +2 -2
  272. package/dist/{components/layout → lab}/draggable-panel.d.ts +8 -8
  273. package/dist/{components/layout → lab}/draggable-panel.js +2 -2
  274. package/dist/{components/data-entry → lab}/emoji-picker.d.ts +2 -2
  275. package/dist/{components/data-entry → lab}/emoji-picker.js +6 -6
  276. package/dist/{components/general → lab}/float-button.d.ts +8 -8
  277. package/dist/{components/general → lab}/float-button.js +7 -7
  278. package/dist/lab/index.d.ts +39 -0
  279. package/dist/lab/index.js +48 -0
  280. package/dist/{components/layout → lab}/legal-document-shell.d.ts +2 -2
  281. package/dist/{components/layout → lab}/legal-document-shell.js +4 -4
  282. package/dist/{components/data-display → lab}/marquee.d.ts +5 -5
  283. package/dist/{components/data-display → lab}/marquee.js +5 -5
  284. package/dist/{components/layout → lab}/masonry.d.ts +2 -2
  285. package/dist/{components/layout → lab}/masonry.js +3 -3
  286. package/dist/{components/navigation → lab}/mega-menu.d.ts +4 -4
  287. package/dist/{components/navigation → lab}/mega-menu.js +2 -2
  288. package/dist/{components/data-display → lab}/org-chart.d.ts +2 -2
  289. package/dist/{components/data-display → lab}/org-chart.js +4 -4
  290. package/dist/{components/layout → lab}/page-cover.d.ts +2 -2
  291. package/dist/{components/layout → lab}/page-cover.js +2 -2
  292. package/dist/{components/data-display → lab}/range-timeline.d.ts +1 -1
  293. package/dist/{components/data-display → lab}/range-timeline.js +6 -6
  294. package/dist/{components/data-entry → lab}/sortable-list.d.ts +2 -2
  295. package/dist/{components/data-entry → lab}/sortable-list.js +3 -3
  296. package/dist/{components/data-display → lab}/text-diff.d.ts +3 -3
  297. package/dist/{components/data-display → lab}/text-diff.js +4 -4
  298. package/dist/{components/data-display → lab}/timeline-grid.d.ts +2 -2
  299. package/dist/{components/data-display → lab}/timeline-grid.js +1 -1
  300. package/dist/lib/control-styles.js +1 -1
  301. package/dist/lib/datetime/format.js +20 -6
  302. package/dist/lib/datetime/sync.d.ts +6 -2
  303. package/dist/lib/datetime/sync.js +14 -18
  304. package/dist/lib/platform.d.ts +1 -1
  305. package/dist/props/components/app.prop.d.ts +28 -13
  306. package/dist/props/components/data-display.prop.d.ts +19 -29
  307. package/dist/props/components/feedback.prop.d.ts +15 -44
  308. package/dist/props/components/general.prop.d.ts +2 -64
  309. package/dist/props/components/index.d.ts +9 -1
  310. package/dist/props/components/layout.prop.d.ts +41 -57
  311. package/dist/props/registry.d.ts +48 -101
  312. package/dist/props/registry.js +45 -129
  313. package/dist/props/vocabulary/index.d.ts +1 -1
  314. package/dist/props/vocabulary/interaction.prop.d.ts +3 -12
  315. package/dist/styles/alert-layout.css +0 -29
  316. package/dist/styles/data-display-layout.css +14 -22
  317. package/dist/styles/dialog-layout.css +4 -0
  318. package/dist/styles/fonts/OFL.txt +93 -0
  319. package/dist/styles/form-layout.css +4 -0
  320. package/dist/styles/index.css +0 -2
  321. package/dist/styles/layers.json +44 -179
  322. package/dist/styles/text-layout.css +0 -15
  323. package/dist/styles.css +2 -0
  324. package/dist/themes/godx.css +43 -0
  325. package/dist/themes/godx.d.ts +13 -0
  326. package/dist/themes/godx.js +12 -0
  327. package/dist/tokens/components/feedback.css +0 -6
  328. package/dist/tokens/derived.css +23 -22
  329. package/dist/tokens/foundation.css +4 -6
  330. package/docs/COMPOSITION-VS-COMPONENT.md +58 -33
  331. package/docs/CONSUMER-RULES.md +1 -1
  332. package/docs/CUSTOMER-THEMING.md +17 -53
  333. package/docs/migrations/v32.md +98 -0
  334. package/package.json +58 -19
  335. package/scripts/_agent-setup.mjs +54 -3
  336. package/scripts/brand-accent.generated.mjs +15 -2
  337. package/scripts/cli.mjs +36 -11
  338. package/scripts/codemod.mjs +522 -0
  339. package/scripts/consumer-rule.md +21 -43
  340. package/scripts/postinstall.mjs +10 -47
  341. package/scripts/prune-css.mjs +1 -1
  342. package/scripts/ui-audit.mjs +5 -2
  343. package/dist/components/data-display/chat-bubble.d.ts +0 -30
  344. package/dist/components/data-display/chat-bubble.js +0 -229
  345. package/dist/components/data-display/hover-card.d.ts +0 -1
  346. package/dist/components/data-display/hover-card.js +0 -7
  347. package/dist/components/data-display/thought-chain.d.ts +0 -42
  348. package/dist/components/data-display/thought-chain.js +0 -177
  349. package/dist/components/data-display/thumbnail.d.ts +0 -37
  350. package/dist/components/data-display/thumbnail.js +0 -20
  351. package/dist/components/data-display/welcome.d.ts +0 -26
  352. package/dist/components/data-display/welcome.js +0 -37
  353. package/dist/components/data-entry/attachments.d.ts +0 -19
  354. package/dist/components/data-entry/attachments.js +0 -366
  355. package/dist/components/data-entry/chat-composer.d.ts +0 -51
  356. package/dist/components/data-entry/chat-composer.js +0 -200
  357. package/dist/components/data-entry/chat-suggestion.d.ts +0 -28
  358. package/dist/components/data-entry/chat-suggestion.js +0 -309
  359. package/dist/components/data-entry/tag-input.d.ts +0 -2
  360. package/dist/components/data-entry/tag-input.js +0 -5
  361. package/dist/components/feedback/banner.d.ts +0 -21
  362. package/dist/components/feedback/banner.js +0 -19
  363. package/dist/components/feedback/callout.d.ts +0 -23
  364. package/dist/components/feedback/callout.js +0 -42
  365. package/dist/components/layout/auth-shell.d.ts +0 -10
  366. package/dist/components/layout/auth-shell.js +0 -42
  367. package/dist/components/layout/space-compact.d.ts +0 -65
  368. package/dist/components/layout/space-compact.js +0 -52
  369. package/dist/components/navigation/conversations.d.ts +0 -39
  370. package/dist/components/navigation/conversations.js +0 -371
  371. package/dist/components/ui/accordion.d.ts +0 -51
  372. package/dist/components/ui/accordion.js +0 -254
  373. package/dist/components/ui/aspect-ratio.d.ts +0 -24
  374. package/dist/components/ui/aspect-ratio.js +0 -21
  375. package/dist/components/ui/avatar.d.ts +0 -16
  376. package/dist/components/ui/avatar.js +0 -115
  377. package/dist/components/ui/credential-reveal.d.ts +0 -9
  378. package/dist/components/ui/credential-reveal.js +0 -160
  379. package/dist/components/ui/hover-card.d.ts +0 -47
  380. package/dist/components/ui/hover-card.js +0 -205
  381. package/dist/components/ui/input-otp.d.ts +0 -48
  382. package/dist/components/ui/input-otp.js +0 -101
  383. package/dist/components/ui/password-input.d.ts +0 -38
  384. package/dist/components/ui/password-input.js +0 -60
  385. package/dist/components/ui/rating.d.ts +0 -38
  386. package/dist/components/ui/rating.js +0 -131
  387. package/dist/components/ui/segmented.d.ts +0 -94
  388. package/dist/components/ui/segmented.js +0 -108
  389. package/dist/components/ui/separator.d.ts +0 -25
  390. package/dist/components/ui/separator.js +0 -74
  391. package/dist/components/ui/toggle-group.d.ts +0 -108
  392. package/dist/components/ui/toggle-group.js +0 -194
  393. package/dist/components/ui/toggle.d.ts +0 -86
  394. package/dist/components/ui/toggle.js +0 -156
  395. package/docs/CANONICAL-CONTRACTS.md +0 -206
  396. package/docs/COMPONENTS.md +0 -163
  397. package/docs/DATETIME.md +0 -78
  398. package/docs/DEVELOPMENT.md +0 -269
  399. package/docs/FRAME-A11Y-CI.md +0 -287
  400. package/docs/FRAME-COVERAGE-LEDGER.md +0 -123
  401. package/docs/FRAME-COVERAGE-REPORT.md +0 -228
  402. package/docs/FRAME-COVERAGE-STANDARD.md +0 -65
  403. package/docs/FRAME-COVERAGE.md +0 -29
  404. package/docs/MEASUREMENT-CONTRACT.md +0 -109
  405. package/docs/PROPS-REGISTRY.md +0 -61
  406. package/docs/PROPS-VOCABULARY.md +0 -100
  407. package/docs/REGISTRY.md +0 -70
  408. package/docs/TESTING.md +0 -107
  409. package/docs/THEME-API-COVERAGE.md +0 -538
  410. package/docs/WHAT-BELONGS-HERE.md +0 -179
  411. package/docs/asset-modules.d.ts +0 -53
  412. package/docs/assets/cover-terrain.svg +0 -6
  413. package/docs/assets/portrait-amber.svg +0 -5
  414. package/docs/assets/portrait-clay.svg +0 -5
  415. package/docs/assets/portrait-indigo.svg +0 -5
  416. package/docs/assets/portrait-iris.svg +0 -5
  417. package/docs/assets/portrait-moss.svg +0 -5
  418. package/docs/assets/portrait-plum.svg +0 -5
  419. package/docs/assets/portrait-slate.svg +0 -5
  420. package/docs/assets/service-mark-rose.svg +0 -6
  421. package/docs/assets/service-mark-teal.svg +0 -5
  422. package/docs/assets/shot-landscape.svg +0 -12
  423. package/docs/assets/shot-portrait.svg +0 -10
  424. package/docs/assets/tcgm/card-1.svg +0 -1
  425. package/docs/assets/tcgm/card-2.svg +0 -1
  426. package/docs/assets/tcgm/card-3.svg +0 -1
  427. package/docs/assets/tcgm/card-4.svg +0 -1
  428. package/docs/assets/tcgm/card-5.svg +0 -1
  429. package/docs/assets/tcgm/card-6.svg +0 -1
  430. package/docs/assets/tcgm/hero-prism.svg +0 -1
  431. package/docs/assets/tcgm/scene-1.svg +0 -1
  432. package/docs/assets/tcgm/scene-2.svg +0 -1
  433. package/docs/assets/tcgm/scene-3.svg +0 -1
  434. package/docs/assets/tcgm/scene-4.svg +0 -1
  435. package/docs/assets/tcgm/scene-5.svg +0 -1
  436. package/docs/assets/tcgm/tcgm-lockup-color.svg +0 -1
  437. package/docs/assets/tcgm/tcgm-symbol-color.svg +0 -1
  438. package/docs/charts/cjk-category-axis.tsx +0 -81
  439. package/docs/charts/compact-bar-trend.tsx +0 -327
  440. package/docs/charts/size-tiers.tsx +0 -192
  441. package/docs/data-display/accordion.tsx +0 -99
  442. package/docs/data-display/avatar.tsx +0 -502
  443. package/docs/data-display/badge.tsx +0 -335
  444. package/docs/data-display/card/examples/detail-panel.tsx +0 -106
  445. package/docs/data-display/card/examples/tab-list.tsx +0 -97
  446. package/docs/data-display/card/index.md +0 -3
  447. package/docs/data-display/card/index.tsx +0 -390
  448. package/docs/data-display/carousel.tsx +0 -160
  449. package/docs/data-display/charts.tsx +0 -278
  450. package/docs/data-display/chat-bubble.tsx +0 -397
  451. package/docs/data-display/code-block.tsx +0 -188
  452. package/docs/data-display/collapsible.tsx +0 -162
  453. package/docs/data-display/credential-reveal.tsx +0 -148
  454. package/docs/data-display/data-table/examples/antd-parity.tsx +0 -257
  455. package/docs/data-display/data-table/examples/approval-queue.tsx +0 -212
  456. package/docs/data-display/data-table/examples/grid-features.tsx +0 -158
  457. package/docs/data-display/data-table/examples/list-page.tsx +0 -175
  458. package/docs/data-display/data-table/examples/selectable-inbox.tsx +0 -113
  459. package/docs/data-display/data-table/examples/server-paged.tsx +0 -179
  460. package/docs/data-display/data-table/examples/striped-list.tsx +0 -173
  461. package/docs/data-display/data-table/index.md +0 -9
  462. package/docs/data-display/data-table/index.tsx +0 -407
  463. package/docs/data-display/descriptions.tsx +0 -263
  464. package/docs/data-display/empty-state.tsx +0 -164
  465. package/docs/data-display/feature-list.tsx +0 -159
  466. package/docs/data-display/hover-card.tsx +0 -181
  467. package/docs/data-display/image.tsx +0 -170
  468. package/docs/data-display/legend.tsx +0 -158
  469. package/docs/data-display/list-row.tsx +0 -441
  470. package/docs/data-display/markdown.tsx +0 -86
  471. package/docs/data-display/marquee.tsx +0 -254
  472. package/docs/data-display/org-chart.tsx +0 -165
  473. package/docs/data-display/permission-matrix.tsx +0 -188
  474. package/docs/data-display/popover-touch.tsx +0 -27
  475. package/docs/data-display/popover.tsx +0 -331
  476. package/docs/data-display/progress.tsx +0 -162
  477. package/docs/data-display/prose.tsx +0 -169
  478. package/docs/data-display/qr-code.tsx +0 -68
  479. package/docs/data-display/scroll-area.tsx +0 -420
  480. package/docs/data-display/service-launcher-card.tsx +0 -445
  481. package/docs/data-display/stat-card.tsx +0 -354
  482. package/docs/data-display/swatch.tsx +0 -107
  483. package/docs/data-display/table.tsx +0 -362
  484. package/docs/data-display/text-diff.tsx +0 -89
  485. package/docs/data-display/thought-chain.tsx +0 -176
  486. package/docs/data-display/thumbnail.tsx +0 -128
  487. package/docs/data-display/timeline-grid.tsx +0 -119
  488. package/docs/data-display/timeline.tsx +0 -671
  489. package/docs/data-display/touch-actions.tsx +0 -36
  490. package/docs/data-display/tree.tsx +0 -724
  491. package/docs/data-display/welcome.tsx +0 -115
  492. package/docs/data-entry/attachments.tsx +0 -160
  493. package/docs/data-entry/block-editor.tsx +0 -105
  494. package/docs/data-entry/branch-scope-picker.tsx +0 -128
  495. package/docs/data-entry/calendar.tsx +0 -226
  496. package/docs/data-entry/cascader.tsx +0 -380
  497. package/docs/data-entry/chat-composer.tsx +0 -619
  498. package/docs/data-entry/chat-suggestion.tsx +0 -301
  499. package/docs/data-entry/checkbox.tsx +0 -256
  500. package/docs/data-entry/color-picker.tsx +0 -189
  501. package/docs/data-entry/command-palette.tsx +0 -179
  502. package/docs/data-entry/command.tsx +0 -341
  503. package/docs/data-entry/country-picker-recipe.tsx +0 -175
  504. package/docs/data-entry/date-picker.tsx +0 -452
  505. package/docs/data-entry/emoji-picker.tsx +0 -35
  506. package/docs/data-entry/form/examples/employee-settings.tsx +0 -267
  507. package/docs/data-entry/form/examples/invoice-form.tsx +0 -387
  508. package/docs/data-entry/form-dynamic-fields.tsx +0 -199
  509. package/docs/data-entry/form-field/examples/a11y-contract.tsx +0 -242
  510. package/docs/data-entry/form-field/examples/create-form.tsx +0 -107
  511. package/docs/data-entry/form-field/index.md +0 -8
  512. package/docs/data-entry/form-field/index.tsx +0 -337
  513. package/docs/data-entry/form-inertia.tsx +0 -80
  514. package/docs/data-entry/form-root.tsx +0 -112
  515. package/docs/data-entry/form.tsx +0 -1498
  516. package/docs/data-entry/input-otp.tsx +0 -258
  517. package/docs/data-entry/input.tsx +0 -796
  518. package/docs/data-entry/label.tsx +0 -102
  519. package/docs/data-entry/markdown-editor.tsx +0 -69
  520. package/docs/data-entry/number-input.tsx +0 -279
  521. package/docs/data-entry/password-input.tsx +0 -102
  522. package/docs/data-entry/password-strength.tsx +0 -99
  523. package/docs/data-entry/radio-group.tsx +0 -316
  524. package/docs/data-entry/rating.tsx +0 -91
  525. package/docs/data-entry/record-picker.tsx +0 -209
  526. package/docs/data-entry/search-input.tsx +0 -121
  527. package/docs/data-entry/segmented-in-filter-row.tsx +0 -60
  528. package/docs/data-entry/segmented.tsx +0 -300
  529. package/docs/data-entry/select-async-contracts.tsx +0 -108
  530. package/docs/data-entry/select-matrix.tsx +0 -209
  531. package/docs/data-entry/select.tsx +0 -547
  532. package/docs/data-entry/slider.tsx +0 -212
  533. package/docs/data-entry/sortable-list.tsx +0 -76
  534. package/docs/data-entry/switch.tsx +0 -314
  535. package/docs/data-entry/tag-input.tsx +0 -145
  536. package/docs/data-entry/textarea.tsx +0 -249
  537. package/docs/data-entry/time-picker.tsx +0 -187
  538. package/docs/data-entry/time-range-picker.tsx +0 -55
  539. package/docs/data-entry/toggle-count.tsx +0 -348
  540. package/docs/data-entry/toggle-group.tsx +0 -438
  541. package/docs/data-entry/toggle.tsx +0 -217
  542. package/docs/data-entry/transfer.tsx +0 -115
  543. package/docs/data-entry/tree-select.tsx +0 -204
  544. package/docs/data-entry/upload-crop-dialog.tsx +0 -109
  545. package/docs/data-entry/upload.tsx +0 -310
  546. package/docs/feedback/alert-dialog.tsx +0 -270
  547. package/docs/feedback/alert.tsx +0 -248
  548. package/docs/feedback/auth-expiry.tsx +0 -104
  549. package/docs/feedback/banner.tsx +0 -183
  550. package/docs/feedback/callout.tsx +0 -220
  551. package/docs/feedback/danger-confirm.tsx +0 -91
  552. package/docs/feedback/dialog-touch.tsx +0 -24
  553. package/docs/feedback/dialog.tsx +0 -373
  554. package/docs/feedback/sheet.tsx +0 -510
  555. package/docs/feedback/skeleton.tsx +0 -168
  556. package/docs/feedback/toast.tsx +0 -135
  557. package/docs/feedback/tooltip.tsx +0 -171
  558. package/docs/feedback/two-factor-setup.tsx +0 -68
  559. package/docs/foundation/_email-specimen.ts +0 -274
  560. package/docs/foundation/_theme-editor-scope.ts +0 -222
  561. package/docs/foundation/colors.tsx +0 -207
  562. package/docs/foundation/density.tsx +0 -242
  563. package/docs/foundation/email-tokens.tsx +0 -323
  564. package/docs/foundation/radius-shadow.tsx +0 -154
  565. package/docs/foundation/spacing.tsx +0 -216
  566. package/docs/foundation/theme-editor.tsx +0 -654
  567. package/docs/foundation/typography.tsx +0 -147
  568. package/docs/general/actions.tsx +0 -175
  569. package/docs/general/activity.tsx +0 -289
  570. package/docs/general/button/examples/destructive-confirm.tsx +0 -90
  571. package/docs/general/button/examples/form-actions.tsx +0 -87
  572. package/docs/general/button/examples/toolbar.tsx +0 -160
  573. package/docs/general/button/index.md +0 -16
  574. package/docs/general/button/index.tsx +0 -236
  575. package/docs/general/float-button.tsx +0 -133
  576. package/docs/general/icon.tsx +0 -217
  577. package/docs/general/logo.tsx +0 -194
  578. package/docs/general/reveal.tsx +0 -309
  579. package/docs/general/typography.tsx +0 -542
  580. package/docs/i18n/messages/en.json +0 -1715
  581. package/docs/i18n/messages/ja.json +0 -1708
  582. package/docs/i18n/messages/vi.json +0 -1708
  583. package/docs/layout/account-chip.tsx +0 -72
  584. package/docs/layout/admin-collection.tsx +0 -122
  585. package/docs/layout/affix.tsx +0 -209
  586. package/docs/layout/app-launcher.tsx +0 -211
  587. package/docs/layout/app-shell-arrangements.tsx +0 -225
  588. package/docs/layout/app-shell-narrow-bar.tsx +0 -205
  589. package/docs/layout/app-shell-states.tsx +0 -171
  590. package/docs/layout/app-shell.tsx +0 -395
  591. package/docs/layout/aspect-ratio.tsx +0 -135
  592. package/docs/layout/auth-account-summary.tsx +0 -103
  593. package/docs/layout/auth-divider.tsx +0 -28
  594. package/docs/layout/auth-footer.tsx +0 -37
  595. package/docs/layout/auth-identity.tsx +0 -70
  596. package/docs/layout/auth-recovery/examples/mfa-challenge.md +0 -41
  597. package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +0 -254
  598. package/docs/layout/auth-recovery/examples/mobile-390.md +0 -25
  599. package/docs/layout/auth-recovery/examples/mobile-390.tsx +0 -82
  600. package/docs/layout/auth-recovery/examples/password-recovery.md +0 -24
  601. package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -197
  602. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +0 -27
  603. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +0 -156
  604. package/docs/layout/auth-recovery/index.md +0 -140
  605. package/docs/layout/auth-recovery/index.tsx +0 -96
  606. package/docs/layout/auth-shell-context.tsx +0 -103
  607. package/docs/layout/auth-shell-device.tsx +0 -112
  608. package/docs/layout/auth-shell-registration.tsx +0 -338
  609. package/docs/layout/auth-shell-variants.tsx +0 -143
  610. package/docs/layout/auth-shell.tsx +0 -59
  611. package/docs/layout/auth-stack.tsx +0 -40
  612. package/docs/layout/centered-shell.tsx +0 -102
  613. package/docs/layout/draggable-panel.tsx +0 -127
  614. package/docs/layout/error-surface/examples/application-403.tsx +0 -84
  615. package/docs/layout/error-surface/examples/application-404.tsx +0 -77
  616. package/docs/layout/error-surface/examples/system-500.tsx +0 -47
  617. package/docs/layout/error-surface/examples/system-503.tsx +0 -48
  618. package/docs/layout/error-surface/index.md +0 -153
  619. package/docs/layout/error-surface/index.tsx +0 -239
  620. package/docs/layout/flex.tsx +0 -444
  621. package/docs/layout/legal-document-shell/_data.ts +0 -110
  622. package/docs/layout/legal-document-shell/examples/desktop-1440.md +0 -12
  623. package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +0 -83
  624. package/docs/layout/legal-document-shell/examples/mobile-390.md +0 -22
  625. package/docs/layout/legal-document-shell/examples/mobile-390.tsx +0 -70
  626. package/docs/layout/legal-document-shell/examples/tablet-1024.md +0 -3
  627. package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +0 -84
  628. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +0 -18
  629. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +0 -61
  630. package/docs/layout/legal-document-shell/index.md +0 -51
  631. package/docs/layout/legal-document-shell/index.tsx +0 -101
  632. package/docs/layout/masonry.tsx +0 -291
  633. package/docs/layout/master-detail.tsx +0 -390
  634. package/docs/layout/mobile-shell.tsx +0 -106
  635. package/docs/layout/nav-list.tsx +0 -584
  636. package/docs/layout/org-switcher.tsx +0 -131
  637. package/docs/layout/page-container.tsx +0 -1020
  638. package/docs/layout/page-cover.tsx +0 -56
  639. package/docs/layout/resizable-panel.tsx +0 -419
  640. package/docs/layout/responsive-grid.tsx +0 -403
  641. package/docs/layout/separator.tsx +0 -327
  642. package/docs/layout/service-role-panel.tsx +0 -144
  643. package/docs/layout/sidebar.tsx +0 -689
  644. package/docs/layout/space-compact.tsx +0 -202
  645. package/docs/layout/split-pane.tsx +0 -532
  646. package/docs/layout/topbar-item.tsx +0 -233
  647. package/docs/layout/topbar.tsx +0 -360
  648. package/docs/navigation/anchor.tsx +0 -295
  649. package/docs/navigation/app-setting-picker.tsx +0 -178
  650. package/docs/navigation/app-setting-toggle.tsx +0 -111
  651. package/docs/navigation/breadcrumb.tsx +0 -207
  652. package/docs/navigation/card-tabs.tsx +0 -344
  653. package/docs/navigation/conversations.tsx +0 -176
  654. package/docs/navigation/dropdown-menu.tsx +0 -345
  655. package/docs/navigation/filter-bar.tsx +0 -247
  656. package/docs/navigation/mega-menu-panel.tsx +0 -86
  657. package/docs/navigation/mega-menu.tsx +0 -254
  658. package/docs/navigation/pagination.tsx +0 -293
  659. package/docs/navigation/steps.tsx +0 -315
  660. package/docs/navigation/tabs-rtl.tsx +0 -28
  661. package/docs/navigation/tabs.tsx +0 -755
  662. package/docs/navigation/toolbar.tsx +0 -347
  663. package/docs/providers/app-provider.tsx +0 -191
  664. package/docs/providers/format-date.tsx +0 -230
  665. package/docs/providers/theme-scope.tsx +0 -186
  666. package/docs/query/button-refetch.tsx +0 -161
  667. package/docs/query/data-state.tsx +0 -262
  668. package/docs/query/infinite-query-state.tsx +0 -97
  669. package/docs/query/mutation-feedback.tsx +0 -128
  670. package/docs/query/touch-actions.tsx +0 -68
  671. package/docs/react-router/prefetch-link.tsx +0 -262
  672. package/docs/roadmap/ai-chat-components.md +0 -206
  673. package/docs/roadmap/antd-parity.md +0 -155
  674. package/docs/roadmap/badge-tag-chip-count.md +0 -172
  675. package/docs/roadmap/list-masonry.md +0 -159
  676. package/docs/roadmap/parity-audit-data-display-feedback.md +0 -567
  677. package/docs/roadmap/parity-audit-data-entry.md +0 -368
  678. package/docs/roadmap/parity-audit-layout-navigation-general.md +0 -459
  679. package/docs/roadmap/parity-backlog.md +0 -77
  680. package/docs/roadmap/tree-components.md +0 -151
  681. package/docs/roadmap/website-components.md +0 -813
  682. package/docs/showcase/acme-portal.tsx +0 -461
  683. package/docs/showcase/acme-website.tsx +0 -499
  684. package/docs/showcase/caimono-price-comparison.tsx +0 -919
  685. package/docs/showcase/case1-warehouse-dashboard.tsx +0 -358
  686. package/docs/showcase/case2-employee-me.tsx +0 -438
  687. package/docs/showcase/case3-approval-workflow.tsx +0 -531
  688. package/docs/showcase/case4-login.tsx +0 -312
  689. package/docs/showcase/case5-shift-calendar.tsx +0 -702
  690. package/docs/showcase/case6-agency-handy.tsx +0 -1120
  691. package/docs/showcase/futurelastic-web.tsx +0 -441
  692. package/docs/showcase/marketing-page.tsx +0 -895
  693. package/docs/showcase/org-switcher.tsx +0 -320
  694. package/docs/showcase/permission-matrix.tsx +0 -354
  695. package/docs/showcase/public-landing.tsx +0 -210
  696. package/docs/showcase/settings-account-sections.tsx +0 -559
  697. package/docs/showcase/settings-security-mfa.tsx +0 -145
  698. package/docs/showcase/table-approval-queue.tsx +0 -199
  699. package/docs/showcase/table-bulk-actions.tsx +0 -468
  700. package/docs/showcase/table-compact-kintone.tsx +0 -438
  701. package/docs/showcase/table-conditional-format.tsx +0 -367
  702. package/docs/showcase/table-crud-list.tsx +0 -544
  703. package/docs/showcase/table-density.tsx +0 -349
  704. package/docs/showcase/table-expandable-rows.tsx +0 -496
  705. package/docs/showcase/table-filter-chips.tsx +0 -468
  706. package/docs/showcase/table-footer-totals.tsx +0 -328
  707. package/docs/showcase/table-grouped-subtotals.tsx +0 -398
  708. package/docs/showcase/table-master-detail.tsx +0 -482
  709. package/docs/showcase/table-pagination.tsx +0 -409
  710. package/docs/showcase/table-states.tsx +0 -371
  711. package/docs/showcase/table-sticky-columns.tsx +0 -377
  712. package/docs/showcase/table-tree-rows.tsx +0 -451
  713. package/docs/showcase/table-view-tabs.tsx +0 -488
  714. package/docs/showcase/tcgm-website.tsx +0 -1047
  715. package/docs/showcase/tenant-brand-color.tsx +0 -338
  716. package/docs/showcase/theme-customization.tsx +0 -1292
  717. package/docs/showcase/theme-lab.tsx +0 -2125
  718. package/docs/themes/flat.css +0 -466
  719. package/docs/themes/glassmorphism.css +0 -960
  720. package/docs/themes/index.ts +0 -219
  721. package/docs/themes/neubrutalism.css +0 -481
  722. /package/dist/components/navigation/{filter-bar.d.ts → toolbar.d.ts} +0 -0
  723. /package/dist/components/navigation/{filter-bar.js → toolbar.js} +0 -0
  724. /package/dist/{components/data-display → lab}/carousel.d.ts +0 -0
  725. /package/dist/{components/data-entry → lab}/emoji-data.d.ts +0 -0
  726. /package/dist/{components/data-entry → lab}/emoji-data.js +0 -0
  727. /package/dist/{components/data-display → lab}/marquee-reveal.d.ts +0 -0
  728. /package/dist/{components/data-display → lab}/marquee-reveal.js +0 -0
@@ -1,895 +0,0 @@
1
- /**
2
- * Showcase · Marketing page — the composition doctrine's own deliverable (gh#833).
3
- *
4
- * `docs/COMPOSITION-VS-COMPONENT.md` §3 judges Hero, Navbar, Footer, PricingTable, testimonial,
5
- * logo wall, feature grid and CTA band to be COMPOSITIONS: layout + content + token configuration
6
- * over real components, expressible today. The doctrine's remedy for a composition is a `docs/`
7
- * showcase, not a component. Until this page existed that was an assertion. This is the
8
- * demonstration, and its claim is a MEASUREMENT, not a promise:
9
- *
10
- * this page acme-website futurelastic-web
11
- * `<style>` blocks ................ 0 1 1
12
- * page-local class SELECTORS ...... 0 17 28
13
- * bespoke classes ON elements ..... 0 16 25
14
- * non-`ui-*` classes on elements .. 0 38 45
15
- * raw px/rem/em/vw literals ....... 0 29 40
16
- *
17
- * Counted with comments stripped (so a docblock quoting a class or a length is not counted):
18
- * selectors are `/(^|[\s,>+~])\.([a-zA-Z_][\w-]*)\s*(?=[{,.:[]|\s)/m`, classes are every token
19
- * inside a `className`, literals are `/(?<![\w.$}#-])(\d*\.?\d+)(px|rem|em|ch|pt|v\w+)\b/`. The two
20
- * siblings also RE-THEME, which is half of what their stylesheets carry; this page uses the shipped
21
- * theme, so everything it could not express is a framework gap rather than a brand decision.
22
- * `public-landing.tsx` also measures 0/0 and is not a counter-example: it is a narrow
23
- * `CenteredShell preset="public-landing"` page with no full-bleed band, no display type, no
24
- * pricing and no logo wall, i.e. none of the shapes that produced the classes above.
25
- *
26
- * Every LENGTH here is a token reference: `var(--space-section-band)`, `var(--space-section-hero)`,
27
- * `var(--page-measure-wide)`, `var(--band-height-3xl)`, `var(--space-6)`, `var(--space-2)`,
28
- * `var(--overlay-z-index)`. The only class written anywhere below is `.ui-brand-glow`, which the
29
- * package ships (`src/styles/layout.css`).
30
- *
31
- * ── WHAT IS STILL HAND-WRITTEN, AND WHY (the finding this page exists to produce) ───────────────
32
- *
33
- * Zero classes and zero literals did NOT mean zero CSS. Six things below WERE inline `style`
34
- * objects because no PROP reached them. Each one is a named gap, in the order a reader meets them;
35
- * gh#839 closed the first two:
36
- *
37
- * 1. THE SECTION BAND — was `paddingBlock: var(--space-section-band | --space-section-hero)`.
38
- * CLOSED by gh#839: the numeric `GapProp` ladder reaches the two band steps, so
39
- * `pad={{ block: 20 }}` (80px) and `pad={{ block: 24 }}` (96px) state the rhythm through the
40
- * public API, and every band below now does. Neither step has a compact variant and gh#839
41
- * decided it should not: `--space-section-hero` measures 96px at 1440 AND at 320, which is
42
- * deliberate — Tailwind UI's own marketing sections are `py-24 sm:py-32`, i.e. 96px is the
43
- * NARROW rung of the industry pair and the desktop one is the step above. A numeric `pad`
44
- * step is a VALUE (`pad={3}` is 12px everywhere); making one of them responsive would break
45
- * that contract for the whole ladder. `--centered-shell-landing-main-padding-block-compact`
46
- * is not the counter-example it looks like: 40px → 24px is a SHELL's main padding, not a
47
- * marketing band, and it switches inside `.ui-centered-shell`'s own scope, which a plain
48
- * `<section>` has no equivalent of.
49
- * 2. THE CENTRED COLUMN — was `marginInline: auto` + `inlineSize: 100%` +
50
- * `maxInlineSize: var(--page-measure-wide)` + `paddingInline: var(--space-6)`, repeated at
51
- * every band. CLOSED by gh#839 as `Flex measure="wide"` + `pad={{ inline: 6 }}`. gh#831 minted
52
- * `--page-measure-wide` and deliberately did not add `PageContainer measure="wide"`, reasoning
53
- * that a marketing page is full-bleed sections with a centred inner column and `PageContainer`
54
- * owns neither. That reasoning still holds and was not reopened — the prop went to `Flex`, the
55
- * primitive a full-bleed `<section>` can actually put inside itself, where it has seven call
56
- * sites on this page. `measure` adds NO gutter: `pad` owns that, and one band with two padding
57
- * owners is how a measure and its inset drift apart.
58
- * 3. THE STICKY BAR — `position: sticky` + `insetBlockStart` + `zIndex`. `Affix` has since
59
- * shipped (28.8.0, with the measured placeholder that removes the 62px page jump) and this
60
- * page has not yet been moved onto it; `Topbar` still has no `sticky` prop.
61
- * 4. THE GLASS — `--topbar-background-alpha` / `--topbar-backdrop-blur-size` as inline custom
62
- * properties. They are `initial` by design, so a call site MUST set them, and that is correct.
63
- * This used to read `--space-2`, borrowing a token that means something else, because the
64
- * library had no blur SCALE at all. gh#837 closed that: `--blur-sm|md|lg` now exists in
65
- * `foundation.css`, deliberately NOT `--scaling`-multiplied, because a backdrop blur is an
66
- * optical effect and compact density does not mean thinner glass. Measured: `blur(8px)`.
67
- * 5. THE HALO — `position: relative` / `overflow: hidden` on the band and `position: absolute` /
68
- * `inset: 0` on the `.ui-brand-glow` layer. This is the package's own idiom (both siblings
69
- * write `className="ui-brand-glow absolute inset-0"`), spelled as logical inline style so
70
- * `check:rtl` never has to grant an exception.
71
- * 6. THE DISPLAY RAMP IS NOT RESPONSIVE, and this is the one that changed the page. gh#826 gave
72
- * `Heading size` / `Text size` the display steps, and `size` takes a single scalar: there is
73
- * no responsive object form, the way `Flex direction` and `ResponsiveGrid columns` both take
74
- * one. `--font-size-5xl` is `--font-size-display` = 54px at 1440 and 54px at 320. Measured
75
- * with a headline of ordinary marketing length (99 characters): 6 lines at 1280, 10 at 375,
76
- * 12 at 320, i.e. a phone hero five screens tall. The headline in `en`/`ja`/`vi` was cut to
77
- * what 54px can carry (2 lines at 1280, 4 at 375) and the long-copy edge case moved to the
78
- * feature grid, where `features.auditTitle` runs several lines beside `features.ssoTitle` =
79
- * "SSO". NO page-local `clamp()` was written: both siblings wrote one, and writing a third is
80
- * how a framework gap becomes folklore. The package already knows the answer for exactly one
81
- * preset (`--centered-shell-landing-heading-size-compact`, read only by
82
- * `CenteredShell preset="public-landing"`); a composition cannot reach it.
83
- *
84
- * MegaMenu is deliberately ABSENT, and the absence is measured, not an oversight. A site nav and
85
- * this sticky glass bar are mutually exclusive today. `docs/navigation/mega-menu.tsx` records that
86
- * MegaMenu must not go in a `Topbar` slot: `topbar-center` is `display: none` below ~1280px, and
87
- * `topbar-start` is `overflow: clip` with a nowrap row, which put 58 elements outside the viewport
88
- * at 375px. Meanwhile `.ui-topbar` is the ONLY selector that reads the gh#831 glass knobs, and
89
- * turning the blur on makes the bar a backdrop root, i.e. the containing block for its own fixed
90
- * descendants, which is exactly how MegaMenu positions its panel. So the bar carries plain anchors
91
- * at desktop and the narrow answer is the `Sheet`, which is what the MegaMenu doc prescribes.
92
- *
93
- * ── REACHING THE EDGES, AND THE TWO THINGS IT BROKE ─────────────────────────────────────────────
94
- *
95
- * Tidy data is why a docs site's examples never break. On purpose here: a 71-character identifier
96
- * with no break opportunity in it, in three places; CJK beside Latin in one sentence, one plan row
97
- * and one quote; a feature card with NO description beside five that have one; a testimonial with
98
- * NO rating beside two that have one; a plan with NO badge and NO figure beside one carrying three
99
- * badges; a footer column with one link beside one with six; a brand lockup long enough to outgrow
100
- * the bar. Two of those broke the page, and both fixes are documented at the call site:
101
- *
102
- * • The id held the document open at 457px on every phone width. `Text whitespace="pre-wrap"`
103
- * gives `overflow-wrap: break-word`, which does NOT reduce a box's MIN-CONTENT size, and a
104
- * flex item keeps `min-width: auto` — so in the footer row it wrapped nothing. `Flex fill`
105
- * (`flex: 1 1 0` + `min-inline-size: 0`) is what makes the break fire.
106
- * • The lockup measured 222px against the 85px `topbar-start` had left at 375, and was clipped.
107
- * `Logo` has no `truncate`; the package's own answer, in `public-landing.tsx`, is to drop the
108
- * wordmark at phone width.
109
- *
110
- * Measured in Chromium after both, at 320 / 375 / 390 / 768 / 1024 / 1280 / 1440:
111
- * `document.documentElement.scrollWidth` equals the viewport at every one, and zero unclipped
112
- * elements cross the inline edge. The two boxes that do scroll are the `Marquee` viewport and the
113
- * `Carousel` viewport, which is what both components are.
114
- *
115
- * Every string and every `aria-label` comes from `t()` (`docs/i18n/messages/{en,ja,vi}.json`,
116
- * namespace `marketingShowcase` — demo copy the preview registers at startup, never shipped to a
117
- * consumer; gh#858), and the locale picker in the bar switches all three live. Money
118
- * is `Intl.NumberFormat` with the ACTIVE locale and an ISO 4217 code that lives in data, never a
119
- * symbol in the copy. The year is `Intl.DateTimeFormat`. Domains are RFC 2606 reserved
120
- * (`*.example.jp`), the company is fictional, and every wordmark in the logo wall is invented.
121
- */
122
- import { useMemo, useState, type CSSProperties } from "react";
123
- import {
124
- ArrowRight,
125
- CalendarClock,
126
- CircleCheck,
127
- FileSearch,
128
- Globe2,
129
- KeyRound,
130
- Menu,
131
- Route,
132
- Webhook,
133
- } from "lucide-react";
134
-
135
- import {
136
- Avatar,
137
- AvatarFallback,
138
- Badge,
139
- Card,
140
- CardContent,
141
- Carousel,
142
- CarouselContent,
143
- CarouselDots,
144
- CarouselItem,
145
- CarouselNext,
146
- CarouselPrevious,
147
- FeatureList,
148
- Marquee,
149
- StatCard,
150
- } from "@godxjp/ui/data-display";
151
- import { Rating, Segmented } from "@godxjp/ui/data-entry";
152
- import {
153
- Sheet,
154
- SheetBody,
155
- SheetClose,
156
- SheetContent,
157
- SheetDescription,
158
- SheetHeader,
159
- SheetTitle,
160
- SheetTrigger,
161
- } from "@godxjp/ui/feedback";
162
- import { Button, Heading, Icon, Logo, Reveal, Text } from "@godxjp/ui/general";
163
- import { useTranslation } from "@godxjp/ui/i18n";
164
- import { Flex, ResponsiveGrid, Separator, Topbar } from "@godxjp/ui/layout";
165
- import { AppSettingPicker } from "@godxjp/ui/navigation";
166
-
167
- /* ── The inline-style constants named in the docblock. Every value is a token reference; no number
168
- with a unit appears anywhere in this file. Gaps 1 and 2 no longer have one: `Flex measure` and
169
- `Flex pad` state the band through props (gh#839). ──────────────────────────────────────────── */
170
-
171
- /** (5) The halo host and the halo layer. */
172
- const GLOW_HOST: CSSProperties = { position: "relative", overflow: "hidden" };
173
- const GLOW_LAYER: CSSProperties = { position: "absolute", inset: 0 };
174
- const ABOVE_GLOW: CSSProperties = { position: "relative" };
175
-
176
- /** (3) The sticky bar region. `Affix` does not exist; `Topbar` has no `sticky`. */
177
- const STICKY_HEADER: CSSProperties = {
178
- position: "sticky",
179
- insetBlockStart: 0,
180
- zIndex: "var(--overlay-z-index)",
181
- };
182
-
183
- /** (4) gh#831's glass knobs plus the bar geometry its own docstring recommends. */
184
- const GLASS_BAR: CSSProperties = {
185
- "--topbar-height": "var(--band-height-3xl)",
186
- /* Full-bleed glass, content on the shell measure: the same `max(gutter, half the slack)` the
187
- package writes for CenteredShell's landing preset, so no page-local media query. */
188
- "--topbar-inset": "max(var(--space-6), calc((100% - var(--page-measure-wide)) / 2))",
189
- "--topbar-background-alpha": "85%",
190
- "--topbar-backdrop-blur-size": "var(--blur-md)",
191
- } as CSSProperties;
192
-
193
- /** Per-instance halo shaping — the four `--brand-glow-*` knobs, at the call site. */
194
- const HERO_GLOW: CSSProperties = {
195
- "--brand-glow-size": "55% 60%",
196
- "--brand-glow-position": "82% -8%",
197
- "--brand-glow-alpha": "0.20",
198
- } as CSSProperties;
199
-
200
- const CTA_GLOW: CSSProperties = {
201
- "--brand-glow-size": "70% 90%",
202
- "--brand-glow-position": "50% 110%",
203
- "--brand-glow-alpha": "0.16",
204
- } as CSSProperties;
205
-
206
- /* ── Data. RFC 2606 reserved domains, a fictional company, invented customer wordmarks. ──────── */
207
-
208
- const SITE = "works.example.jp";
209
-
210
- /**
211
- * 71 characters, and not one of them is a break opportunity: no hyphen, no underscore, no slash.
212
- * It is in the hero panel AND in a feature card so the failure has two chances to show itself.
213
- */
214
- const ENDPOINT_ID = "whsec0f3a8c1d2e4b5a697c8d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e";
215
-
216
- const NAV_KEYS = ["product", "solutions", "pricing", "docs"] as const;
217
-
218
- /** Invented wordmarks. CJK, Latin and Vietnamese diacritics in one row, plus a very long one. */
219
- const CUSTOMERS = [
220
- { glyph: "A", name: "Aoba Foods" },
221
- { glyph: "北", name: "北陸精密工業" },
222
- { glyph: "M", name: "Meridian Health" },
223
- { glyph: "T", name: "Trường An" },
224
- { glyph: "K", name: "Kita Logistics and Warehousing" },
225
- { glyph: "Ö", name: "Örebro Verkstad" },
226
- { glyph: "海", name: "海運サービス" },
227
- ];
228
-
229
- /** The currency lives in DATA, so nothing in the page hard-codes a symbol or an ISO 4217 code. */
230
- const CURRENCY = "JPY";
231
-
232
- type Plan = {
233
- key: "starter" | "team" | "enterprise";
234
- /** `null` = quoted: the empty slot beside two filled ones. */
235
- monthly: number | null;
236
- yearlyMonthly: number | null;
237
- accent: boolean;
238
- badges: Array<"popular" | "saving" | "fresh">;
239
- features: Array<{ state: "included" | "limited" | "excluded"; key: string; limitKey?: string }>;
240
- };
241
-
242
- const PLANS: Plan[] = [
243
- {
244
- key: "starter",
245
- monthly: 4800,
246
- yearlyMonthly: 4000,
247
- accent: false,
248
- badges: [],
249
- features: [
250
- { state: "limited", key: "featChains", limitKey: "limitedChains" },
251
- { state: "included", key: "featExport" },
252
- { state: "excluded", key: "featDelegation" },
253
- { state: "excluded", key: "featSso" },
254
- { state: "excluded", key: "featResidency" },
255
- { state: "limited", key: "featSupport", limitKey: "limitedSupport" },
256
- ],
257
- },
258
- {
259
- key: "team",
260
- monthly: 9600,
261
- yearlyMonthly: 8000,
262
- accent: true,
263
- badges: ["popular", "saving", "fresh"],
264
- features: [
265
- { state: "included", key: "featChains" },
266
- { state: "included", key: "featExport" },
267
- { state: "included", key: "featDelegation" },
268
- { state: "included", key: "featSso" },
269
- { state: "excluded", key: "featResidency" },
270
- { state: "limited", key: "featSupport", limitKey: "limitedSupport" },
271
- ],
272
- },
273
- {
274
- key: "enterprise",
275
- monthly: null,
276
- yearlyMonthly: null,
277
- accent: false,
278
- badges: [],
279
- features: [
280
- { state: "included", key: "featChains" },
281
- { state: "included", key: "featExport" },
282
- { state: "included", key: "featDelegation" },
283
- { state: "included", key: "featSso" },
284
- { state: "included", key: "featResidency" },
285
- { state: "included", key: "featSupport" },
286
- ],
287
- },
288
- ];
289
-
290
- const FEATURES = [
291
- { key: "routing", icon: Route, hasBody: true, long: false },
292
- /* The long title with NO body: an empty slot beside five filled ones. */
293
- { key: "audit", icon: FileSearch, hasBody: false, long: true },
294
- { key: "evidence", icon: CircleCheck, hasBody: true, long: false },
295
- { key: "webhook", icon: Webhook, hasBody: true, long: false },
296
- { key: "residency", icon: Globe2, hasBody: true, long: false },
297
- { key: "sso", icon: KeyRound, hasBody: true, long: false },
298
- ];
299
-
300
- const QUOTES = [
301
- { key: "1", rating: 5 },
302
- /* Two words, and no rating: the second empty slot. */
303
- { key: "2", rating: null },
304
- { key: "3", rating: 4 },
305
- ] as const;
306
-
307
- const FOOTER_COLUMNS = [
308
- { key: "product", links: ["featuresLink", "pricingLink", "changelog", "status"] },
309
- { key: "company", links: ["about", "careers"] },
310
- {
311
- key: "legal",
312
- links: ["terms", "privacy", "security", "subprocessors", "accessibility", "status"],
313
- },
314
- /* One link beside six. */
315
- { key: "contact", links: ["salesLine"] },
316
- ];
317
-
318
- export default function MarketingPage() {
319
- const { t, locale } = useTranslation();
320
- const [cycle, setCycle] = useState("monthly");
321
- const [navOpen, setNavOpen] = useState(false);
322
-
323
- const money = useMemo(
324
- () =>
325
- new Intl.NumberFormat(locale, {
326
- style: "currency",
327
- currency: CURRENCY,
328
- maximumFractionDigits: 0,
329
- }),
330
- [locale],
331
- );
332
- const count = useMemo(() => new Intl.NumberFormat(locale), [locale]);
333
- const year = useMemo(
334
- () => new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date()),
335
- [locale],
336
- );
337
-
338
- return (
339
- <Flex as="div" direction="col" gap="none">
340
- {/* ── NAVBAR ─────────────────────────────────────────────────────────────────────────── */}
341
- <header style={STICKY_HEADER}>
342
- <Topbar
343
- style={GLASS_BAR}
344
- start={
345
- <Flex align="center" gap="lg">
346
- {/* The lockup measures 222px, and at 375 the start slot has 85px after the end
347
- cluster takes its natural width — so `topbar-start` clipped it (measured: 93 in
348
- 85). The bar's shrink contract says a long brand string should truncate rather
349
- than spill, and `Logo` has no `truncate`; the package's own answer, in
350
- `public-landing.tsx`, is to drop the wordmark at phone width. The mark alone
351
- identifies the product there, and the full name is the first thing in the Sheet. */}
352
- <Flex hideBelow="sm" align="center" gap="none">
353
- <Logo
354
- glyph="E"
355
- wordmark={t("marketingShowcase.brand.name")}
356
- productSuffix={t("marketingShowcase.brand.suffix")}
357
- />
358
- </Flex>
359
- <Flex hideFrom="sm" align="center" gap="none">
360
- <Logo glyph="E" label={t("marketingShowcase.brand.name")} />
361
- </Flex>
362
- <Flex
363
- as="div"
364
- hideBelow="lg"
365
- align="center"
366
- gap="xs"
367
- role="navigation"
368
- aria-label={t("marketingShowcase.nav.label")}
369
- >
370
- {NAV_KEYS.map((key, index) => (
371
- <Button key={key} variant="ghost" size="sm" asChild>
372
- <a href={`#${key}`} aria-current={index === 0 ? "page" : undefined}>
373
- {t(`marketingShowcase.nav.${key}`)}
374
- </a>
375
- </Button>
376
- ))}
377
- </Flex>
378
- </Flex>
379
- }
380
- end={
381
- <Flex align="center" gap="sm">
382
- <AppSettingPicker kind="locale" />
383
- <Flex hideBelow="sm" align="center" gap="sm">
384
- <Button variant="ghost" size="sm" asChild>
385
- <a href="#start">{t("marketingShowcase.nav.signIn")}</a>
386
- </Button>
387
- </Flex>
388
- <Button size="sm" asChild>
389
- <a href="#start">{t("marketingShowcase.nav.getStarted")}</a>
390
- </Button>
391
- {/* The narrow answer the MegaMenu doc prescribes. Nothing in the bar is unreachable
392
- at 375px: every destination hidden above is inside this Sheet. */}
393
- <Flex hideFrom="lg" align="center" gap="none">
394
- <Sheet open={navOpen} onOpenChange={setNavOpen}>
395
- <SheetTrigger asChild>
396
- <Button
397
- variant="ghost"
398
- size="icon-sm"
399
- aria-label={t("marketingShowcase.nav.open")}
400
- >
401
- <Icon as={Menu} size="sm" />
402
- </Button>
403
- </SheetTrigger>
404
- <SheetContent side="right">
405
- <SheetHeader>
406
- <SheetTitle>{t("marketingShowcase.nav.title")}</SheetTitle>
407
- <SheetDescription>{t("marketingShowcase.nav.description")}</SheetDescription>
408
- </SheetHeader>
409
- <SheetBody>
410
- <Flex
411
- direction="col"
412
- gap="xs"
413
- role="navigation"
414
- aria-label={t("marketingShowcase.nav.label")}
415
- >
416
- {NAV_KEYS.map((key) => (
417
- <SheetClose key={key} asChild>
418
- <Button variant="ghost" size="sm" align="start" fullWidth asChild>
419
- <a href={`#${key}`}>{t(`marketingShowcase.nav.${key}`)}</a>
420
- </Button>
421
- </SheetClose>
422
- ))}
423
- <Separator space="sm" />
424
- <SheetClose asChild>
425
- <Button variant="ghost" size="sm" align="start" fullWidth asChild>
426
- <a href="#start">{t("marketingShowcase.nav.signIn")}</a>
427
- </Button>
428
- </SheetClose>
429
- </Flex>
430
- </SheetBody>
431
- </SheetContent>
432
- </Sheet>
433
- </Flex>
434
- </Flex>
435
- }
436
- />
437
- </header>
438
-
439
- <main>
440
- {/* ── HERO ─────────────────────────────────────────────────────────────────────────── */}
441
- <section id="product" style={GLOW_HOST}>
442
- <div
443
- aria-hidden="true"
444
- className="ui-brand-glow"
445
- style={{ ...GLOW_LAYER, ...HERO_GLOW }}
446
- />
447
- <Flex
448
- direction="col"
449
- gap="none"
450
- measure="wide"
451
- pad={{ inline: 6, block: 24 }}
452
- style={ABOVE_GLOW}
453
- >
454
- <ResponsiveGrid columns={{ base: 1, lg: 2 }} gap="xl" align="start">
455
- <Reveal>
456
- <Flex direction="col" gap="lg">
457
- <Flex align="center" gap="sm" wrap>
458
- <Badge tone="primary" shape="pill">
459
- {t("marketingShowcase.hero.eyebrow")}
460
- </Badge>
461
- </Flex>
462
- {/* A real <h1> at the display tier — gh#826's `size` beside `level`, instead of
463
- the `.tx-display` class with a raw font-size both siblings used to carry. */}
464
- <Heading level={1} size="5xl" weight="bold">
465
- {t("marketingShowcase.hero.title")}
466
- </Heading>
467
- <Text size="xl" tone="muted">
468
- {t("marketingShowcase.hero.lead")}
469
- </Text>
470
- <Flex align="center" gap="sm" wrap>
471
- <Button size="lg" asChild>
472
- <a href="#start">
473
- {t("marketingShowcase.hero.primary")}
474
- <Icon as={ArrowRight} size="sm" tone="inherit" />
475
- </a>
476
- </Button>
477
- <Button size="lg" variant="outline" asChild>
478
- <a href="#start">
479
- <Icon as={CalendarClock} size="sm" tone="inherit" />
480
- {t("marketingShowcase.hero.secondary")}
481
- </a>
482
- </Button>
483
- </Flex>
484
- <Text size="xs" tone="muted">
485
- {t("marketingShowcase.hero.trust")}
486
- </Text>
487
- </Flex>
488
- </Reveal>
489
-
490
- <Reveal delay={2}>
491
- <Card variant="outline">
492
- <CardContent solo>
493
- <Flex direction="col" gap="md">
494
- <Flex direction="col" gap="none">
495
- <Heading level={2} size="md">
496
- {t("marketingShowcase.hero.panelTitle")}
497
- </Heading>
498
- <Text size="xs" tone="muted">
499
- {t("marketingShowcase.hero.panelNote")}
500
- </Text>
501
- </Flex>
502
- <ResponsiveGrid columns={{ base: 1, sm: 3 }} gap="sm">
503
- <StatCard
504
- label={t("marketingShowcase.hero.pending")}
505
- value={count.format(18)}
506
- accent="attention"
507
- />
508
- <StatCard
509
- label={t("marketingShowcase.hero.cleared")}
510
- value={count.format(146)}
511
- delta="+12"
512
- />
513
- <StatCard
514
- label={t("marketingShowcase.hero.median")}
515
- value={t("marketingShowcase.hero.medianValue")}
516
- />
517
- </ResponsiveGrid>
518
- <Separator space="xs" />
519
- <Flex direction="col" gap="xs">
520
- <Text size="xs" weight="medium" tone="muted">
521
- {t("marketingShowcase.hero.endpointLabel")}
522
- </Text>
523
- {/* 71 characters with nowhere to break. `whitespace="pre-wrap"` is the
524
- public prop for this (`overflow-wrap: break-word`) and it is enough
525
- HERE, because a column flex item has a definite inline size to break
526
- against. In the footer row it was not; see the note there. */}
527
- <Text as="code" chip size="2xs" whitespace="pre-wrap">
528
- {ENDPOINT_ID}
529
- </Text>
530
- <Text size="2xs" tone="muted">
531
- {t("marketingShowcase.hero.endpointNote")}
532
- </Text>
533
- </Flex>
534
- </Flex>
535
- </CardContent>
536
- </Card>
537
- </Reveal>
538
- </ResponsiveGrid>
539
- </Flex>
540
- </section>
541
-
542
- {/* ── LOGO WALL ────────────────────────────────────────────────────────────────────── */}
543
- <section aria-labelledby="logos-title">
544
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
545
- <Flex direction="col" gap="lg">
546
- <Flex direction="col" gap="xs">
547
- <Heading level={2} size="lg" id="logos-title">
548
- {t("marketingShowcase.logos.title")}
549
- </Heading>
550
- <Text size="sm" tone="muted">
551
- {t("marketingShowcase.logos.caption")}
552
- </Text>
553
- </Flex>
554
- {/* `defaultPlay={false}` is the recommended posture; the pause/play control is
555
- Marquee's own real Button, in the tab order, with a localized name. */}
556
- <Marquee
557
- defaultPlay={false}
558
- speed="slow"
559
- gap="xl"
560
- fade
561
- pauseOnHover
562
- label={t("marketingShowcase.logos.marqueeLabel")}
563
- >
564
- {CUSTOMERS.map((customer) => (
565
- <Logo
566
- key={customer.name}
567
- glyph={customer.glyph}
568
- size="sm"
569
- wordmark={customer.name}
570
- />
571
- ))}
572
- </Marquee>
573
- </Flex>
574
- </Flex>
575
- </section>
576
-
577
- {/* ── FEATURE GRID ─────────────────────────────────────────────────────────────────── */}
578
- <section id="solutions" aria-labelledby="features-title">
579
- <Flex as="div" direction="col" gap="none" surface="muted">
580
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
581
- <Flex direction="col" gap="xl">
582
- <Flex direction="col" gap="xs">
583
- <Heading level={2} size="3xl" weight="bold" id="features-title">
584
- {t("marketingShowcase.features.title")}
585
- </Heading>
586
- <Text size="lg" tone="muted">
587
- {t("marketingShowcase.features.lead")}
588
- </Text>
589
- </Flex>
590
- <ResponsiveGrid columns={{ base: 1, sm: 2, lg: 3 }} gap="md" align="stretch">
591
- {FEATURES.map((feature) => (
592
- <Card key={feature.key} hoverable>
593
- <CardContent solo>
594
- <Flex direction="col" gap="sm">
595
- {/* The doctrine's "icon medallion": Avatar square + a Lucide glyph. */}
596
- <Avatar shape="square" appearance="tinted" size="md">
597
- <AvatarFallback>
598
- <Icon as={feature.icon} size="sm" tone="primary" />
599
- </AvatarFallback>
600
- </Avatar>
601
- <Heading level={3} size="md">
602
- {t(`marketingShowcase.features.${feature.key}Title`)}
603
- </Heading>
604
- {feature.hasBody ? (
605
- <Text size="sm" tone="muted">
606
- {t(`marketingShowcase.features.${feature.key}Body`)}
607
- </Text>
608
- ) : null}
609
- {feature.key === "webhook" ? (
610
- <Text as="code" chip size="2xs" whitespace="pre-wrap">
611
- {ENDPOINT_ID}
612
- </Text>
613
- ) : null}
614
- </Flex>
615
- </CardContent>
616
- </Card>
617
- ))}
618
- </ResponsiveGrid>
619
- </Flex>
620
- </Flex>
621
- </Flex>
622
- </section>
623
-
624
- {/* ── TESTIMONIALS ─────────────────────────────────────────────────────────────────── */}
625
- <section aria-labelledby="quotes-title">
626
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
627
- <Flex direction="col" gap="lg">
628
- <Heading level={2} size="3xl" weight="bold" id="quotes-title">
629
- {t("marketingShowcase.testimonials.title")}
630
- </Heading>
631
- <Carousel opts={{ align: "start", loop: true }}>
632
- <CarouselContent>
633
- {QUOTES.map((quote) => (
634
- <CarouselItem key={quote.key}>
635
- <Card variant="outline">
636
- <CardContent solo>
637
- <Flex direction="col" gap="md">
638
- {quote.rating === null ? null : (
639
- <Rating
640
- readOnly
641
- value={quote.rating}
642
- name={`quote-${quote.key}`}
643
- aria-label={t("marketingShowcase.testimonials.ratingLabel")}
644
- />
645
- )}
646
- <Text size="lg">
647
- {t(`marketingShowcase.testimonials.q${quote.key}`)}
648
- </Text>
649
- <Flex align="center" gap="sm">
650
- <Avatar size="sm">
651
- <AvatarFallback>
652
- {t(`marketingShowcase.testimonials.a${quote.key}`).slice(0, 1)}
653
- </AvatarFallback>
654
- </Avatar>
655
- <Flex direction="col" gap="none">
656
- <Text size="sm" weight="medium">
657
- {t(`marketingShowcase.testimonials.a${quote.key}`)}
658
- </Text>
659
- <Text size="xs" tone="muted">
660
- {t(`marketingShowcase.testimonials.r${quote.key}`)}
661
- </Text>
662
- </Flex>
663
- </Flex>
664
- </Flex>
665
- </CardContent>
666
- </Card>
667
- </CarouselItem>
668
- ))}
669
- </CarouselContent>
670
- {/* The three controls are DIRECT children of Carousel because the component
671
- places them itself: `.ui-carousel-previous` / `-next` are `position: absolute`
672
- against `.ui-carousel`, and `.ui-carousel-dots` carries its own block padding.
673
- Wrapping them in a Flex row produced an empty flex item and moved nothing.
674
- Their accessible names are the component's own (`dataDisplay.carousel.*`). */}
675
- <CarouselPrevious />
676
- <CarouselNext />
677
- <CarouselDots />
678
- </Carousel>
679
- </Flex>
680
- </Flex>
681
- </section>
682
-
683
- {/* ── PRICING ──────────────────────────────────────────────────────────────────────── */}
684
- <section id="pricing" aria-labelledby="pricing-title">
685
- <Flex as="div" direction="col" gap="none" surface="muted">
686
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
687
- <Flex direction="col" gap="xl">
688
- <Flex direction="col" gap="md">
689
- <Heading level={2} size="3xl" weight="bold" id="pricing-title">
690
- {t("marketingShowcase.pricing.title")}
691
- </Heading>
692
- <Text size="lg" tone="muted">
693
- {t("marketingShowcase.pricing.lead")}
694
- </Text>
695
- {/* FeatureList + Card accent + Segmented. The plan said pricing needs nothing
696
- new, and it needed nothing new. */}
697
- <Segmented
698
- value={cycle}
699
- onValueChange={setCycle}
700
- aria-label={t("marketingShowcase.pricing.cycleLabel")}
701
- options={[
702
- { value: "monthly", label: t("marketingShowcase.pricing.monthly") },
703
- {
704
- value: "yearly",
705
- label: t("marketingShowcase.pricing.yearly"),
706
- count: 2,
707
- countLabel: t("marketingShowcase.pricing.saving"),
708
- },
709
- ]}
710
- />
711
- </Flex>
712
- <ResponsiveGrid columns={{ base: 1, md: 3 }} gap="md" align="stretch">
713
- {PLANS.map((plan) => {
714
- const amount = cycle === "yearly" ? plan.yearlyMonthly : plan.monthly;
715
- return (
716
- <Card
717
- key={plan.key}
718
- accent={plan.accent ? "primary" : undefined}
719
- accentPlacement={plan.accent ? "perimeter" : undefined}
720
- >
721
- <CardContent solo>
722
- <Flex direction="col" gap="md">
723
- <Flex align="center" gap="xs" wrap>
724
- <Heading level={3} size="lg">
725
- {t(`marketingShowcase.pricing.${plan.key}Name`)}
726
- </Heading>
727
- {plan.badges.map((badge) => (
728
- <Badge
729
- key={badge}
730
- as="span"
731
- shape="pill"
732
- tone={badge === "popular" ? "primary" : "muted"}
733
- variant={badge === "fresh" ? "outline" : "default"}
734
- >
735
- {t(`marketingShowcase.pricing.${badge}`)}
736
- </Badge>
737
- ))}
738
- </Flex>
739
- <Flex direction="col" gap="none">
740
- {/* The quoted plan has NO figure: an empty slot beside two full
741
- ones, in the row where a missing number usually collapses. */}
742
- <Text size="4xl" weight="bold" tabular>
743
- {amount === null
744
- ? t("marketingShowcase.pricing.quoted")
745
- : money.format(amount)}
746
- </Text>
747
- <Text size="xs" tone="muted">
748
- {amount === null
749
- ? t("marketingShowcase.pricing.quotedNote")
750
- : cycle === "yearly"
751
- ? t("marketingShowcase.pricing.billedYearly")
752
- : t("marketingShowcase.pricing.perMonth")}
753
- </Text>
754
- </Flex>
755
- <Text size="sm" tone="muted">
756
- {t(`marketingShowcase.pricing.${plan.key}Note`)}
757
- </Text>
758
- <FeatureList
759
- items={plan.features.map((feature) => ({
760
- state: feature.state,
761
- label: t(`marketingShowcase.pricing.${feature.key}`),
762
- description: feature.limitKey
763
- ? t(`marketingShowcase.pricing.${feature.limitKey}`)
764
- : undefined,
765
- }))}
766
- />
767
- <Button fullWidth variant={plan.accent ? "default" : "outline"} asChild>
768
- <a href="#start">
769
- {amount === null
770
- ? t("marketingShowcase.pricing.ctaQuote")
771
- : t("marketingShowcase.pricing.cta")}
772
- </a>
773
- </Button>
774
- </Flex>
775
- </CardContent>
776
- </Card>
777
- );
778
- })}
779
- </ResponsiveGrid>
780
- </Flex>
781
- </Flex>
782
- </Flex>
783
- </section>
784
-
785
- {/* ── CTA BAND ─────────────────────────────────────────────────────────────────────── */}
786
- <section id="start" style={GLOW_HOST} aria-labelledby="cta-title">
787
- <div
788
- aria-hidden="true"
789
- className="ui-brand-glow"
790
- style={{ ...GLOW_LAYER, ...CTA_GLOW }}
791
- />
792
- <Flex
793
- direction="col"
794
- gap="none"
795
- measure="wide"
796
- pad={{ inline: 6, block: 20 }}
797
- style={ABOVE_GLOW}
798
- >
799
- <Reveal on="view">
800
- <Flex direction="col" gap="md" align="center">
801
- <Heading level={2} size="4xl" weight="bold" align="center" id="cta-title">
802
- {t("marketingShowcase.cta.title")}
803
- </Heading>
804
- <Text size="lg" tone="muted" align="center">
805
- {t("marketingShowcase.cta.lead")}
806
- </Text>
807
- <Flex align="center" gap="sm" wrap justify="center">
808
- <Button size="lg" asChild>
809
- <a href={`https://${SITE}`}>
810
- {t("marketingShowcase.cta.primary")}
811
- <Icon as={ArrowRight} size="sm" tone="inherit" />
812
- </a>
813
- </Button>
814
- <Button size="lg" variant="outline" asChild>
815
- <a href={`https://${SITE}`}>{t("marketingShowcase.cta.secondary")}</a>
816
- </Button>
817
- </Flex>
818
- <Text size="xs" tone="muted" align="center">
819
- {t("marketingShowcase.cta.note")}
820
- </Text>
821
- </Flex>
822
- </Reveal>
823
- </Flex>
824
- </section>
825
- </main>
826
-
827
- {/* ── FOOTER ───────────────────────────────────────────────────────────────────────── */}
828
- <footer>
829
- <Flex as="div" direction="col" gap="none" surface="muted">
830
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
831
- <Flex direction="col" gap="lg">
832
- {/* ResponsiveGrid.Item span — the asymmetric footer both siblings hand-wrote a
833
- `grid-template-columns: 1.4fr 1fr 1fr 1fr` for. It has shipped the whole time. */}
834
- <ResponsiveGrid columns={12} gap="lg">
835
- <ResponsiveGrid.Item span={{ base: 12, sm: 12, md: 4, lg: 4 }}>
836
- <Flex direction="col" gap="sm">
837
- <Logo
838
- glyph="E"
839
- wordmark={t("marketingShowcase.brand.name")}
840
- productSuffix={t("marketingShowcase.brand.suffix")}
841
- />
842
- <Text size="sm" tone="muted">
843
- {t("marketingShowcase.footer.addressLabel")} ·{" "}
844
- {t("marketingShowcase.footer.address")}
845
- </Text>
846
- <Text size="sm" tone="muted">
847
- {t("marketingShowcase.footer.salesLine")} · sales@{SITE}
848
- </Text>
849
- </Flex>
850
- </ResponsiveGrid.Item>
851
- {FOOTER_COLUMNS.map((column) => (
852
- <ResponsiveGrid.Item key={column.key} span={{ base: 12, sm: 6, md: 2, lg: 2 }}>
853
- <Flex
854
- direction="col"
855
- gap="xs"
856
- align="start"
857
- role="navigation"
858
- aria-label={t(`marketingShowcase.footer.${column.key}`)}
859
- >
860
- <Text size="xs" weight="medium" tone="muted">
861
- {t(`marketingShowcase.footer.${column.key}`)}
862
- </Text>
863
- {column.links.map((link) => (
864
- <Button key={link} variant="link" size="sm" asChild>
865
- <a href={`https://${SITE}`}>{t(`marketingShowcase.footer.${link}`)}</a>
866
- </Button>
867
- ))}
868
- </Flex>
869
- </ResponsiveGrid.Item>
870
- ))}
871
- </ResponsiveGrid>
872
- <Separator space="sm" />
873
- <Flex align="center" justify="between" gap="sm" wrap>
874
- <Text size="xs" tone="muted">
875
- {year} · {t("marketingShowcase.footer.rights")}
876
- </Text>
877
- {/* The hostile case, and the one that actually broke: `whitespace="pre-wrap"`
878
- gives `overflow-wrap: break-word`, which does NOT reduce a box's MIN-CONTENT
879
- size, and a flex item keeps `min-width: auto`. So in this row the 71-character
880
- id held the whole line open and the DOCUMENT scrolled: 457px at 390, 375 and
881
- 320 alike. `Flex fill` is the documented answer (`flex: 1 1 0` +
882
- `min-inline-size: 0`, layout.css:167) and it is what makes the break fire. */}
883
- <Flex fill direction="col" gap="none">
884
- <Text size="2xs" tone="muted" whitespace="pre-wrap" align="end">
885
- {ENDPOINT_ID}
886
- </Text>
887
- </Flex>
888
- </Flex>
889
- </Flex>
890
- </Flex>
891
- </Flex>
892
- </footer>
893
- </Flex>
894
- );
895
- }