@godxjp/ui 31.31.8 → 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 (727) 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/fonts/OFL.txt +93 -0
  318. package/dist/styles/form-layout.css +4 -0
  319. package/dist/styles/index.css +0 -2
  320. package/dist/styles/layers.json +44 -179
  321. package/dist/styles/text-layout.css +0 -15
  322. package/dist/styles.css +2 -0
  323. package/dist/themes/godx.css +43 -0
  324. package/dist/themes/godx.d.ts +13 -0
  325. package/dist/themes/godx.js +12 -0
  326. package/dist/tokens/components/feedback.css +0 -6
  327. package/dist/tokens/derived.css +23 -22
  328. package/dist/tokens/foundation.css +4 -6
  329. package/docs/COMPOSITION-VS-COMPONENT.md +58 -33
  330. package/docs/CONSUMER-RULES.md +1 -1
  331. package/docs/CUSTOMER-THEMING.md +17 -53
  332. package/docs/migrations/v32.md +98 -0
  333. package/package.json +58 -19
  334. package/scripts/_agent-setup.mjs +54 -3
  335. package/scripts/brand-accent.generated.mjs +15 -2
  336. package/scripts/cli.mjs +36 -11
  337. package/scripts/codemod.mjs +522 -0
  338. package/scripts/consumer-rule.md +21 -43
  339. package/scripts/postinstall.mjs +10 -47
  340. package/scripts/prune-css.mjs +1 -1
  341. package/scripts/ui-audit.mjs +5 -2
  342. package/dist/components/data-display/chat-bubble.d.ts +0 -30
  343. package/dist/components/data-display/chat-bubble.js +0 -229
  344. package/dist/components/data-display/hover-card.d.ts +0 -1
  345. package/dist/components/data-display/hover-card.js +0 -7
  346. package/dist/components/data-display/thought-chain.d.ts +0 -42
  347. package/dist/components/data-display/thought-chain.js +0 -177
  348. package/dist/components/data-display/thumbnail.d.ts +0 -37
  349. package/dist/components/data-display/thumbnail.js +0 -20
  350. package/dist/components/data-display/welcome.d.ts +0 -26
  351. package/dist/components/data-display/welcome.js +0 -37
  352. package/dist/components/data-entry/attachments.d.ts +0 -19
  353. package/dist/components/data-entry/attachments.js +0 -366
  354. package/dist/components/data-entry/chat-composer.d.ts +0 -51
  355. package/dist/components/data-entry/chat-composer.js +0 -200
  356. package/dist/components/data-entry/chat-suggestion.d.ts +0 -28
  357. package/dist/components/data-entry/chat-suggestion.js +0 -309
  358. package/dist/components/data-entry/tag-input.d.ts +0 -2
  359. package/dist/components/data-entry/tag-input.js +0 -5
  360. package/dist/components/feedback/banner.d.ts +0 -21
  361. package/dist/components/feedback/banner.js +0 -19
  362. package/dist/components/feedback/callout.d.ts +0 -23
  363. package/dist/components/feedback/callout.js +0 -42
  364. package/dist/components/layout/auth-shell.d.ts +0 -10
  365. package/dist/components/layout/auth-shell.js +0 -42
  366. package/dist/components/layout/space-compact.d.ts +0 -65
  367. package/dist/components/layout/space-compact.js +0 -52
  368. package/dist/components/navigation/conversations.d.ts +0 -39
  369. package/dist/components/navigation/conversations.js +0 -371
  370. package/dist/components/ui/accordion.d.ts +0 -51
  371. package/dist/components/ui/accordion.js +0 -254
  372. package/dist/components/ui/aspect-ratio.d.ts +0 -24
  373. package/dist/components/ui/aspect-ratio.js +0 -21
  374. package/dist/components/ui/avatar.d.ts +0 -16
  375. package/dist/components/ui/avatar.js +0 -115
  376. package/dist/components/ui/credential-reveal.d.ts +0 -9
  377. package/dist/components/ui/credential-reveal.js +0 -160
  378. package/dist/components/ui/hover-card.d.ts +0 -47
  379. package/dist/components/ui/hover-card.js +0 -205
  380. package/dist/components/ui/input-otp.d.ts +0 -48
  381. package/dist/components/ui/input-otp.js +0 -101
  382. package/dist/components/ui/password-input.d.ts +0 -38
  383. package/dist/components/ui/password-input.js +0 -60
  384. package/dist/components/ui/rating.d.ts +0 -38
  385. package/dist/components/ui/rating.js +0 -131
  386. package/dist/components/ui/segmented.d.ts +0 -94
  387. package/dist/components/ui/segmented.js +0 -108
  388. package/dist/components/ui/separator.d.ts +0 -25
  389. package/dist/components/ui/separator.js +0 -74
  390. package/dist/components/ui/toggle-group.d.ts +0 -108
  391. package/dist/components/ui/toggle-group.js +0 -194
  392. package/dist/components/ui/toggle.d.ts +0 -86
  393. package/dist/components/ui/toggle.js +0 -156
  394. package/docs/CANONICAL-CONTRACTS.md +0 -206
  395. package/docs/COMPONENTS.md +0 -163
  396. package/docs/DATETIME.md +0 -78
  397. package/docs/DEVELOPMENT.md +0 -269
  398. package/docs/FRAME-A11Y-CI.md +0 -287
  399. package/docs/FRAME-COVERAGE-LEDGER.md +0 -123
  400. package/docs/FRAME-COVERAGE-REPORT.md +0 -228
  401. package/docs/FRAME-COVERAGE-STANDARD.md +0 -65
  402. package/docs/FRAME-COVERAGE.md +0 -29
  403. package/docs/MEASUREMENT-CONTRACT.md +0 -109
  404. package/docs/PROPS-REGISTRY.md +0 -61
  405. package/docs/PROPS-VOCABULARY.md +0 -100
  406. package/docs/REGISTRY.md +0 -70
  407. package/docs/TESTING.md +0 -107
  408. package/docs/THEME-API-COVERAGE.md +0 -538
  409. package/docs/WHAT-BELONGS-HERE.md +0 -179
  410. package/docs/asset-modules.d.ts +0 -53
  411. package/docs/assets/cover-terrain.svg +0 -6
  412. package/docs/assets/portrait-amber.svg +0 -5
  413. package/docs/assets/portrait-clay.svg +0 -5
  414. package/docs/assets/portrait-indigo.svg +0 -5
  415. package/docs/assets/portrait-iris.svg +0 -5
  416. package/docs/assets/portrait-moss.svg +0 -5
  417. package/docs/assets/portrait-plum.svg +0 -5
  418. package/docs/assets/portrait-slate.svg +0 -5
  419. package/docs/assets/service-mark-rose.svg +0 -6
  420. package/docs/assets/service-mark-teal.svg +0 -5
  421. package/docs/assets/shot-landscape.svg +0 -12
  422. package/docs/assets/shot-portrait.svg +0 -10
  423. package/docs/assets/tcgm/card-1.svg +0 -1
  424. package/docs/assets/tcgm/card-2.svg +0 -1
  425. package/docs/assets/tcgm/card-3.svg +0 -1
  426. package/docs/assets/tcgm/card-4.svg +0 -1
  427. package/docs/assets/tcgm/card-5.svg +0 -1
  428. package/docs/assets/tcgm/card-6.svg +0 -1
  429. package/docs/assets/tcgm/hero-prism.svg +0 -1
  430. package/docs/assets/tcgm/scene-1.svg +0 -1
  431. package/docs/assets/tcgm/scene-2.svg +0 -1
  432. package/docs/assets/tcgm/scene-3.svg +0 -1
  433. package/docs/assets/tcgm/scene-4.svg +0 -1
  434. package/docs/assets/tcgm/scene-5.svg +0 -1
  435. package/docs/assets/tcgm/tcgm-lockup-color.svg +0 -1
  436. package/docs/assets/tcgm/tcgm-symbol-color.svg +0 -1
  437. package/docs/charts/cjk-category-axis.tsx +0 -81
  438. package/docs/charts/compact-bar-trend.tsx +0 -327
  439. package/docs/charts/size-tiers.tsx +0 -192
  440. package/docs/data-display/accordion.tsx +0 -99
  441. package/docs/data-display/avatar.tsx +0 -502
  442. package/docs/data-display/badge.tsx +0 -335
  443. package/docs/data-display/card/examples/detail-panel.tsx +0 -106
  444. package/docs/data-display/card/examples/tab-list.tsx +0 -97
  445. package/docs/data-display/card/index.md +0 -3
  446. package/docs/data-display/card/index.tsx +0 -390
  447. package/docs/data-display/carousel.tsx +0 -160
  448. package/docs/data-display/charts.tsx +0 -278
  449. package/docs/data-display/chat-bubble.tsx +0 -397
  450. package/docs/data-display/code-block.tsx +0 -188
  451. package/docs/data-display/collapsible.tsx +0 -162
  452. package/docs/data-display/credential-reveal.tsx +0 -148
  453. package/docs/data-display/data-table/examples/antd-parity.tsx +0 -257
  454. package/docs/data-display/data-table/examples/approval-queue.tsx +0 -212
  455. package/docs/data-display/data-table/examples/grid-features.tsx +0 -158
  456. package/docs/data-display/data-table/examples/list-page.tsx +0 -175
  457. package/docs/data-display/data-table/examples/selectable-inbox.tsx +0 -113
  458. package/docs/data-display/data-table/examples/server-paged.tsx +0 -179
  459. package/docs/data-display/data-table/examples/striped-list.tsx +0 -173
  460. package/docs/data-display/data-table/index.md +0 -9
  461. package/docs/data-display/data-table/index.tsx +0 -407
  462. package/docs/data-display/descriptions.tsx +0 -263
  463. package/docs/data-display/empty-state.tsx +0 -164
  464. package/docs/data-display/feature-list.tsx +0 -159
  465. package/docs/data-display/hover-card.tsx +0 -181
  466. package/docs/data-display/image.tsx +0 -170
  467. package/docs/data-display/legend.tsx +0 -158
  468. package/docs/data-display/list-row.tsx +0 -441
  469. package/docs/data-display/markdown.tsx +0 -86
  470. package/docs/data-display/marquee.tsx +0 -254
  471. package/docs/data-display/org-chart.tsx +0 -165
  472. package/docs/data-display/permission-matrix.tsx +0 -188
  473. package/docs/data-display/popover-touch.tsx +0 -27
  474. package/docs/data-display/popover.tsx +0 -331
  475. package/docs/data-display/progress.tsx +0 -162
  476. package/docs/data-display/prose.tsx +0 -169
  477. package/docs/data-display/qr-code.tsx +0 -68
  478. package/docs/data-display/scroll-area.tsx +0 -420
  479. package/docs/data-display/service-launcher-card.tsx +0 -445
  480. package/docs/data-display/stat-card.tsx +0 -354
  481. package/docs/data-display/swatch.tsx +0 -107
  482. package/docs/data-display/table.tsx +0 -362
  483. package/docs/data-display/text-diff.tsx +0 -89
  484. package/docs/data-display/thought-chain.tsx +0 -176
  485. package/docs/data-display/thumbnail.tsx +0 -128
  486. package/docs/data-display/timeline-grid.tsx +0 -119
  487. package/docs/data-display/timeline.tsx +0 -671
  488. package/docs/data-display/touch-actions.tsx +0 -36
  489. package/docs/data-display/tree.tsx +0 -724
  490. package/docs/data-display/welcome.tsx +0 -115
  491. package/docs/data-entry/attachments.tsx +0 -160
  492. package/docs/data-entry/block-editor.tsx +0 -105
  493. package/docs/data-entry/branch-scope-picker.tsx +0 -128
  494. package/docs/data-entry/calendar.tsx +0 -226
  495. package/docs/data-entry/cascader.tsx +0 -380
  496. package/docs/data-entry/chat-composer.tsx +0 -619
  497. package/docs/data-entry/chat-suggestion.tsx +0 -301
  498. package/docs/data-entry/checkbox.tsx +0 -256
  499. package/docs/data-entry/color-picker.tsx +0 -189
  500. package/docs/data-entry/command-palette.tsx +0 -179
  501. package/docs/data-entry/command.tsx +0 -341
  502. package/docs/data-entry/country-picker-recipe.tsx +0 -175
  503. package/docs/data-entry/date-picker.tsx +0 -452
  504. package/docs/data-entry/emoji-picker.tsx +0 -35
  505. package/docs/data-entry/form/examples/employee-settings.tsx +0 -267
  506. package/docs/data-entry/form/examples/invoice-form.tsx +0 -387
  507. package/docs/data-entry/form-dynamic-fields.tsx +0 -199
  508. package/docs/data-entry/form-field/examples/a11y-contract.tsx +0 -242
  509. package/docs/data-entry/form-field/examples/create-form.tsx +0 -107
  510. package/docs/data-entry/form-field/index.md +0 -8
  511. package/docs/data-entry/form-field/index.tsx +0 -337
  512. package/docs/data-entry/form-inertia.tsx +0 -80
  513. package/docs/data-entry/form-root.tsx +0 -112
  514. package/docs/data-entry/form.tsx +0 -1498
  515. package/docs/data-entry/input-otp.tsx +0 -258
  516. package/docs/data-entry/input.tsx +0 -796
  517. package/docs/data-entry/label.tsx +0 -102
  518. package/docs/data-entry/markdown-editor.tsx +0 -69
  519. package/docs/data-entry/number-input.tsx +0 -279
  520. package/docs/data-entry/password-input.tsx +0 -102
  521. package/docs/data-entry/password-strength.tsx +0 -99
  522. package/docs/data-entry/radio-group.tsx +0 -316
  523. package/docs/data-entry/rating.tsx +0 -91
  524. package/docs/data-entry/record-picker.tsx +0 -209
  525. package/docs/data-entry/search-input.tsx +0 -121
  526. package/docs/data-entry/segmented-in-filter-row.tsx +0 -60
  527. package/docs/data-entry/segmented.tsx +0 -300
  528. package/docs/data-entry/select-async-contracts.tsx +0 -108
  529. package/docs/data-entry/select-matrix.tsx +0 -209
  530. package/docs/data-entry/select.tsx +0 -547
  531. package/docs/data-entry/slider.tsx +0 -212
  532. package/docs/data-entry/sortable-list.tsx +0 -76
  533. package/docs/data-entry/switch.tsx +0 -314
  534. package/docs/data-entry/tag-input.tsx +0 -145
  535. package/docs/data-entry/textarea.tsx +0 -249
  536. package/docs/data-entry/time-picker.tsx +0 -187
  537. package/docs/data-entry/time-range-picker.tsx +0 -55
  538. package/docs/data-entry/toggle-count.tsx +0 -348
  539. package/docs/data-entry/toggle-group.tsx +0 -438
  540. package/docs/data-entry/toggle.tsx +0 -217
  541. package/docs/data-entry/transfer.tsx +0 -115
  542. package/docs/data-entry/tree-select.tsx +0 -204
  543. package/docs/data-entry/upload-crop-dialog.tsx +0 -109
  544. package/docs/data-entry/upload.tsx +0 -310
  545. package/docs/feedback/alert-dialog.tsx +0 -270
  546. package/docs/feedback/alert.tsx +0 -248
  547. package/docs/feedback/auth-expiry.tsx +0 -104
  548. package/docs/feedback/banner.tsx +0 -183
  549. package/docs/feedback/callout.tsx +0 -220
  550. package/docs/feedback/danger-confirm.tsx +0 -91
  551. package/docs/feedback/dialog-touch.tsx +0 -24
  552. package/docs/feedback/dialog.tsx +0 -373
  553. package/docs/feedback/sheet.tsx +0 -510
  554. package/docs/feedback/skeleton.tsx +0 -168
  555. package/docs/feedback/toast.tsx +0 -135
  556. package/docs/feedback/tooltip.tsx +0 -171
  557. package/docs/feedback/two-factor-setup.tsx +0 -68
  558. package/docs/foundation/_email-specimen.ts +0 -274
  559. package/docs/foundation/_theme-editor-scope.ts +0 -222
  560. package/docs/foundation/colors.tsx +0 -207
  561. package/docs/foundation/density.tsx +0 -242
  562. package/docs/foundation/email-tokens.tsx +0 -323
  563. package/docs/foundation/radius-shadow.tsx +0 -154
  564. package/docs/foundation/spacing.tsx +0 -216
  565. package/docs/foundation/theme-editor.tsx +0 -654
  566. package/docs/foundation/typography.tsx +0 -147
  567. package/docs/general/actions.tsx +0 -175
  568. package/docs/general/activity.tsx +0 -289
  569. package/docs/general/button/examples/destructive-confirm.tsx +0 -90
  570. package/docs/general/button/examples/form-actions.tsx +0 -87
  571. package/docs/general/button/examples/toolbar.tsx +0 -160
  572. package/docs/general/button/index.md +0 -16
  573. package/docs/general/button/index.tsx +0 -236
  574. package/docs/general/float-button.tsx +0 -133
  575. package/docs/general/icon.tsx +0 -217
  576. package/docs/general/logo.tsx +0 -194
  577. package/docs/general/reveal.tsx +0 -309
  578. package/docs/general/typography.tsx +0 -542
  579. package/docs/i18n/messages/en.json +0 -1715
  580. package/docs/i18n/messages/ja.json +0 -1708
  581. package/docs/i18n/messages/vi.json +0 -1708
  582. package/docs/layout/account-chip.tsx +0 -72
  583. package/docs/layout/admin-collection.tsx +0 -122
  584. package/docs/layout/affix.tsx +0 -209
  585. package/docs/layout/app-launcher.tsx +0 -211
  586. package/docs/layout/app-shell-arrangements.tsx +0 -225
  587. package/docs/layout/app-shell-narrow-bar.tsx +0 -205
  588. package/docs/layout/app-shell-states.tsx +0 -171
  589. package/docs/layout/app-shell.tsx +0 -395
  590. package/docs/layout/aspect-ratio.tsx +0 -135
  591. package/docs/layout/auth-account-summary.tsx +0 -103
  592. package/docs/layout/auth-divider.tsx +0 -28
  593. package/docs/layout/auth-footer.tsx +0 -37
  594. package/docs/layout/auth-identity.tsx +0 -70
  595. package/docs/layout/auth-recovery/examples/mfa-challenge.md +0 -41
  596. package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +0 -254
  597. package/docs/layout/auth-recovery/examples/mobile-390.md +0 -25
  598. package/docs/layout/auth-recovery/examples/mobile-390.tsx +0 -82
  599. package/docs/layout/auth-recovery/examples/password-recovery.md +0 -24
  600. package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -197
  601. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +0 -27
  602. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +0 -156
  603. package/docs/layout/auth-recovery/index.md +0 -140
  604. package/docs/layout/auth-recovery/index.tsx +0 -96
  605. package/docs/layout/auth-shell-context.tsx +0 -103
  606. package/docs/layout/auth-shell-device.tsx +0 -112
  607. package/docs/layout/auth-shell-registration.tsx +0 -338
  608. package/docs/layout/auth-shell-variants.tsx +0 -143
  609. package/docs/layout/auth-shell.tsx +0 -59
  610. package/docs/layout/auth-stack.tsx +0 -40
  611. package/docs/layout/centered-shell.tsx +0 -102
  612. package/docs/layout/draggable-panel.tsx +0 -127
  613. package/docs/layout/error-surface/examples/application-403.tsx +0 -84
  614. package/docs/layout/error-surface/examples/application-404.tsx +0 -77
  615. package/docs/layout/error-surface/examples/system-500.tsx +0 -47
  616. package/docs/layout/error-surface/examples/system-503.tsx +0 -48
  617. package/docs/layout/error-surface/index.md +0 -153
  618. package/docs/layout/error-surface/index.tsx +0 -239
  619. package/docs/layout/flex.tsx +0 -444
  620. package/docs/layout/legal-document-shell/_data.ts +0 -110
  621. package/docs/layout/legal-document-shell/examples/desktop-1440.md +0 -12
  622. package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +0 -83
  623. package/docs/layout/legal-document-shell/examples/mobile-390.md +0 -22
  624. package/docs/layout/legal-document-shell/examples/mobile-390.tsx +0 -70
  625. package/docs/layout/legal-document-shell/examples/tablet-1024.md +0 -3
  626. package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +0 -84
  627. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +0 -18
  628. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +0 -61
  629. package/docs/layout/legal-document-shell/index.md +0 -51
  630. package/docs/layout/legal-document-shell/index.tsx +0 -101
  631. package/docs/layout/masonry.tsx +0 -291
  632. package/docs/layout/master-detail.tsx +0 -390
  633. package/docs/layout/mobile-shell.tsx +0 -106
  634. package/docs/layout/nav-list.tsx +0 -584
  635. package/docs/layout/org-switcher.tsx +0 -131
  636. package/docs/layout/page-container.tsx +0 -1020
  637. package/docs/layout/page-cover.tsx +0 -56
  638. package/docs/layout/resizable-panel.tsx +0 -419
  639. package/docs/layout/responsive-grid.tsx +0 -403
  640. package/docs/layout/separator.tsx +0 -327
  641. package/docs/layout/service-role-panel.tsx +0 -144
  642. package/docs/layout/sidebar.tsx +0 -689
  643. package/docs/layout/space-compact.tsx +0 -202
  644. package/docs/layout/split-pane.tsx +0 -532
  645. package/docs/layout/topbar-item.tsx +0 -233
  646. package/docs/layout/topbar.tsx +0 -360
  647. package/docs/navigation/anchor.tsx +0 -295
  648. package/docs/navigation/app-setting-picker.tsx +0 -178
  649. package/docs/navigation/app-setting-toggle.tsx +0 -111
  650. package/docs/navigation/breadcrumb.tsx +0 -207
  651. package/docs/navigation/card-tabs.tsx +0 -344
  652. package/docs/navigation/conversations.tsx +0 -176
  653. package/docs/navigation/dropdown-menu.tsx +0 -345
  654. package/docs/navigation/filter-bar.tsx +0 -247
  655. package/docs/navigation/mega-menu-panel.tsx +0 -86
  656. package/docs/navigation/mega-menu.tsx +0 -254
  657. package/docs/navigation/pagination.tsx +0 -293
  658. package/docs/navigation/steps.tsx +0 -315
  659. package/docs/navigation/tabs-rtl.tsx +0 -28
  660. package/docs/navigation/tabs.tsx +0 -755
  661. package/docs/navigation/toolbar.tsx +0 -347
  662. package/docs/providers/app-provider.tsx +0 -191
  663. package/docs/providers/format-date.tsx +0 -230
  664. package/docs/providers/theme-scope.tsx +0 -186
  665. package/docs/query/button-refetch.tsx +0 -161
  666. package/docs/query/data-state.tsx +0 -262
  667. package/docs/query/infinite-query-state.tsx +0 -97
  668. package/docs/query/mutation-feedback.tsx +0 -128
  669. package/docs/query/touch-actions.tsx +0 -68
  670. package/docs/react-router/prefetch-link.tsx +0 -262
  671. package/docs/roadmap/ai-chat-components.md +0 -206
  672. package/docs/roadmap/antd-parity.md +0 -155
  673. package/docs/roadmap/badge-tag-chip-count.md +0 -172
  674. package/docs/roadmap/list-masonry.md +0 -159
  675. package/docs/roadmap/parity-audit-data-display-feedback.md +0 -567
  676. package/docs/roadmap/parity-audit-data-entry.md +0 -368
  677. package/docs/roadmap/parity-audit-layout-navigation-general.md +0 -459
  678. package/docs/roadmap/parity-backlog.md +0 -77
  679. package/docs/roadmap/tree-components.md +0 -151
  680. package/docs/roadmap/website-components.md +0 -813
  681. package/docs/showcase/acme-portal.tsx +0 -461
  682. package/docs/showcase/acme-website.tsx +0 -499
  683. package/docs/showcase/caimono-price-comparison.tsx +0 -919
  684. package/docs/showcase/case1-warehouse-dashboard.tsx +0 -358
  685. package/docs/showcase/case2-employee-me.tsx +0 -438
  686. package/docs/showcase/case3-approval-workflow.tsx +0 -531
  687. package/docs/showcase/case4-login.tsx +0 -312
  688. package/docs/showcase/case5-shift-calendar.tsx +0 -702
  689. package/docs/showcase/case6-agency-handy.tsx +0 -1120
  690. package/docs/showcase/futurelastic-web.tsx +0 -441
  691. package/docs/showcase/marketing-page.tsx +0 -895
  692. package/docs/showcase/org-switcher.tsx +0 -320
  693. package/docs/showcase/permission-matrix.tsx +0 -354
  694. package/docs/showcase/public-landing.tsx +0 -210
  695. package/docs/showcase/settings-account-sections.tsx +0 -559
  696. package/docs/showcase/settings-security-mfa.tsx +0 -145
  697. package/docs/showcase/table-approval-queue.tsx +0 -199
  698. package/docs/showcase/table-bulk-actions.tsx +0 -468
  699. package/docs/showcase/table-compact-kintone.tsx +0 -438
  700. package/docs/showcase/table-conditional-format.tsx +0 -367
  701. package/docs/showcase/table-crud-list.tsx +0 -544
  702. package/docs/showcase/table-density.tsx +0 -349
  703. package/docs/showcase/table-expandable-rows.tsx +0 -496
  704. package/docs/showcase/table-filter-chips.tsx +0 -468
  705. package/docs/showcase/table-footer-totals.tsx +0 -328
  706. package/docs/showcase/table-grouped-subtotals.tsx +0 -398
  707. package/docs/showcase/table-master-detail.tsx +0 -482
  708. package/docs/showcase/table-pagination.tsx +0 -409
  709. package/docs/showcase/table-states.tsx +0 -371
  710. package/docs/showcase/table-sticky-columns.tsx +0 -377
  711. package/docs/showcase/table-tree-rows.tsx +0 -451
  712. package/docs/showcase/table-view-tabs.tsx +0 -488
  713. package/docs/showcase/tcgm-website.tsx +0 -1047
  714. package/docs/showcase/tenant-brand-color.tsx +0 -338
  715. package/docs/showcase/theme-customization.tsx +0 -1292
  716. package/docs/showcase/theme-lab.tsx +0 -2125
  717. package/docs/themes/flat.css +0 -466
  718. package/docs/themes/glassmorphism.css +0 -960
  719. package/docs/themes/index.ts +0 -219
  720. package/docs/themes/neubrutalism.css +0 -481
  721. /package/dist/components/navigation/{filter-bar.d.ts → toolbar.d.ts} +0 -0
  722. /package/dist/components/navigation/{filter-bar.js → toolbar.js} +0 -0
  723. /package/dist/{components/data-display → lab}/carousel.d.ts +0 -0
  724. /package/dist/{components/data-entry → lab}/emoji-data.d.ts +0 -0
  725. /package/dist/{components/data-entry → lab}/emoji-data.js +0 -0
  726. /package/dist/{components/data-display → lab}/marquee-reveal.d.ts +0 -0
  727. /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
- }