@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,1047 +0,0 @@
1
- /**
2
- * Showcase · TCG-M "Layered Prism" — a TOKEN-ONLY rebuild of a THIRD brand, this one with MOTION.
3
- *
4
- * Source: the `TCG-M_Complete_Brand_Design_SNS_v1.0` handoff (a hand-written HTML/CSS/JS prototype
5
- * — `07_prototype/index.html` + `site.css` + `app.js`, with `02_foundations/tokens.css` as its
6
- * source of truth). Japanese-first consumer product: trading-card price comparison, news and a
7
- * release calendar. All cards, prices, shops and dates below are the bundle's own FICTIONAL sample
8
- * data and are reproduced as such.
9
- *
10
- * Why this one exists next to acme-website (light/gold) and futurelastic-web (dark/gold): those two
11
- * prove a re-theme, and both are STILL. This brand ships a written MOTION TABLE
12
- * (`02_foundations/04_MOTION_AND_STATES.md`) — press 90ms, hover 140ms, state 200ms, hero-once
13
- * 480ms at y8→0, `cubic-bezier(.2,.8,.2,1)` — plus an explicit motion BUDGET (one decorative motion
14
- * region per viewport; no parallax, no count-up, no infinite float). So the interesting question is
15
- * not "can the tokens paint it" but "can the motion tokens be re-tuned to someone else's timing
16
- * spec, and does the shipped `Reveal` primitive land where the spec says it should". Both are
17
- * answered in the THEME block below: the brand's timing table IS eight token declarations, and the
18
- * hero reveals the ILLUSTRATION ONLY because the spec says "chỉ illustration, text hiện ngay".
19
- *
20
- * Per docs/COMPOSITION-VS-COMPONENT.md every section here (Header/Hero/GameRail/CardGrid/NewsRail/
21
- * Releases/Trust/Footer) FAILS the Framework-Component Test → composition over real primitives.
22
- * ZERO new framework components; nothing is added to `src/components/`.
23
- */
24
- import * as React from "react";
25
- import {
26
- ArrowRight,
27
- CalendarDays,
28
- Clock,
29
- Heart,
30
- Layers,
31
- Menu,
32
- Search,
33
- ShieldCheck,
34
- Sparkles,
35
- ArrowLeftRight,
36
- } from "lucide-react";
37
-
38
- import { Button, Heading, Icon, Reveal, Text } from "@godxjp/ui/general";
39
- import {
40
- Badge,
41
- Card,
42
- CardContent,
43
- Carousel,
44
- CarouselContent,
45
- CarouselItem,
46
- CarouselNext,
47
- CarouselPrevious,
48
- EmptyState,
49
- } from "@godxjp/ui/data-display";
50
- import { Flex, ResponsiveGrid, Separator } from "@godxjp/ui/layout";
51
- import { useTranslation } from "@godxjp/ui/i18n";
52
- import { SearchInput, ToggleGroup, ToggleGroupItem } from "@godxjp/ui/data-entry";
53
- import {
54
- Dialog,
55
- DialogBody,
56
- DialogContent,
57
- DialogDescription,
58
- DialogHeader,
59
- DialogTitle,
60
- Sheet,
61
- SheetBody,
62
- SheetContent,
63
- SheetHeader,
64
- SheetTitle,
65
- Toaster,
66
- toast,
67
- } from "@godxjp/ui/feedback";
68
-
69
- import heroPrism from "../assets/tcgm/hero-prism.svg";
70
- import lockup from "../assets/tcgm/tcgm-lockup-color.svg";
71
- import card1 from "../assets/tcgm/card-1.svg";
72
- import card2 from "../assets/tcgm/card-2.svg";
73
- import card3 from "../assets/tcgm/card-3.svg";
74
- import card4 from "../assets/tcgm/card-4.svg";
75
- import card5 from "../assets/tcgm/card-5.svg";
76
- import card6 from "../assets/tcgm/card-6.svg";
77
- import scene1 from "../assets/tcgm/scene-1.svg";
78
- import scene2 from "../assets/tcgm/scene-2.svg";
79
- import scene3 from "../assets/tcgm/scene-3.svg";
80
- import scene4 from "../assets/tcgm/scene-4.svg";
81
-
82
- // ── Brand stylesheet: the handoff's `tokens.css`, mapped onto the library's semantic roles. ───────
83
- // This is what the consumer ships as their own theme.css. Raw brand values live HERE, never as
84
- // arbitrary utilities in the markup below.
85
- const THEME = `
86
- @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@500;600;700&family=Noto+Sans+JP:wght@400;500;700&display=swap');
87
- [data-tenant="tcgm"] {
88
- /* Colour — 02_foundations/tokens.css, converted to the HSL triplets the library reads.
89
- Measured against WCAG 2.2: white/teal 9.51, ink/off-white 12.30, muted/off-white 5.47,
90
- muted/white 5.73, teal/sky-wash 8.71, teal/lavender-wash 8.35, teal/sand-wash 8.77 — every
91
- pair AA or better. "--input" is the CONTROL boundary held to 3:1 (SC 1.4.11): the brand's own
92
- "--color-border-strong" #718891 is 3.73:1 on white, so the boundary token is that one and NOT
93
- the decorative "--color-border" #DCE7EB, which stays chrome. */
94
- --primary: 192 72% 21%; /* teal #0F4C5C — CTA, logo, heading ink */
95
- --primary-foreground: 0 0% 100%;
96
- --ring: 199 89% 29%; /* focus #08618A — the brand rings in a DIFFERENT blue than
97
- it fills with, so --ring is declared, never inherited */
98
- --focus-ring-color: 199 89% 29%;
99
- --accent: 254 100% 97%; /* lavender wash #F2EEFF — discovery/editorial */
100
- --accent-foreground: 195 57% 16%;
101
- --background: 210 40% 98%; /* off-white #F8FAFC */
102
- --foreground: 195 57% 16%; /* ink #123642 */
103
- --card: 0 0% 100%; --card-foreground: 195 57% 16%;
104
- --secondary: 203 100% 96%; /* sky wash #EAF7FF — the quiet fill, per "white/sky 2.26:1
105
- không dùng": the SATURATED sky is illustration-only */
106
- --secondary-foreground: 192 72% 21%;
107
- --muted: 198 26% 93%; --muted-foreground: 196 17% 39%;
108
- --border: 196 27% 89%; --input: 197 13% 51%;
109
- --success: 161 65% 25%; --warning: 31 70% 31%; --destructive: 349 67% 42%; --info: 202 71% 31%;
110
-
111
- /* Shape — 01_FOUNDATIONS "Radius": 12 control · 20 card · 24 panel · 32 hero · 999 pill. */
112
- --radius: 0.75rem; --radius-md: 12px; --radius-lg: 16px; --radius-xl: 20px; --radius-2xl: 24px;
113
- --card-radius: var(--radius-xl); --control-radius: var(--radius-md);
114
-
115
- /* Elevation — the brand's four shadows verbatim; the hover step is what Card "hoverable" raises
116
- to, so "nâng tối đa 2px và chuyển shadow sm→md" is a token pair, not a hand-written rule. */
117
- --shadow-color: 15 76 92;
118
- --shadow-xs: 0 1px 2px rgb(15 76 92 / .06);
119
- --card-shadow: 0 1px 2px rgb(15 76 92 / .06);
120
- --card-hover-shadow: 0 12px 32px -14px rgb(15 76 92 / .20);
121
- --shadow-sm: 0 4px 14px -6px rgb(15 76 92 / .12);
122
- --shadow-md: 0 12px 32px -14px rgb(15 76 92 / .20);
123
- --shadow-lg: 0 24px 64px -24px rgb(15 76 92 / .26);
124
-
125
- /* Type — Noto Sans JP for Japanese, Montserrat for Latin labels and prices. The brand is
126
- explicit that Montserrat carries no Japanese glyph, so it is the DISPLAY/label face only and
127
- never the body face. */
128
- --font-family-body: "Noto Sans JP", "Hiragino Kaku Gothic ProN", "Yu Gothic", system-ui, sans-serif;
129
- --font-family-sans: var(--font-family-body);
130
- /* HEADINGS ARE NOTO, NOT MONTSERRAT. The prototype points h1-h3 at its --font-jp, and the brand
131
- says why in one line: Montserrat carries no Japanese glyph. A "Montserrat first" display stack
132
- LOOKS right because the browser falls through per glyph, but it hands the Latin inside a
133
- Japanese headline a different face than the headline, which is the opposite of the intent.
134
- Montserrat is the LATIN-label face, and it arrives through .tm-latin below. */
135
- --font-family-display: var(--font-family-body);
136
- --tm-latin: "Montserrat", system-ui, sans-serif;
137
- /* Hero display. The formula is 02_TYPOGRAPHY's own — "Use clamp(2.125rem, 4vw, 3.5rem) cho
138
- hero" — and it is a token rather than a call-site style because --font-size-display is the
139
- BASE KNOB of the whole display ramp, so 3xl/4xl follow it. Pinned at 3.5rem it measured 56px
140
- at 390, where the same document's mobile column says 34px; 2.125rem IS that 34px. */
141
- --font-size-display: clamp(2.125rem, 4vw, 3.5rem);
142
- --letter-spacing-tight: -0.025em; /* JP heading tracking; the Latin −.035em is on .tm-eyebrow */
143
-
144
- /* MOTION — 04_MOTION_AND_STATES.md's timing table, as tokens. This is the whole point of this
145
- showcase: another brand's motion spec arrives as CONFIGURATION, and the shipped "Reveal"
146
- primitive + Card hover + Dialog enter all retime themselves off it with no new CSS.
147
- press 90ms · hover/focus 140ms · tab/state 200ms · enter 260ms · exit 180ms · hero-once 480ms
148
- Ease is the brand's "cubic-bezier(.2,.8,.2,1)" everywhere; it forbids spring overshoot. */
149
- --duration-fast: 140ms;
150
- --duration-base: 200ms;
151
- --duration-slow: 480ms; /* motion-heroOnce */
152
- --ease-standard: cubic-bezier(.2,.8,.2,1);
153
- --ease-emphasized: cubic-bezier(.2,.8,.2,1);
154
- --ease-decelerate: cubic-bezier(.2,.8,.2,1);
155
- --reveal-distance: 8px; /* "Hero once 480ms: 0→1, y8→0" — the 8 is the spec's */
156
- --reveal-stagger-step: 70ms;
157
-
158
- /* The carousel arrow TARGET. 03_COMPONENTS asks for "arrows44px" and 01_FOUNDATIONS sets the
159
- brand floor at 44x44 ("Chuan noi bo target >=44x44 CSS px tren web"), above WCAG 2.2 SC
160
- 2.5.8's 24px. The library default is 2rem/32px; this is the knob that reaches the brand's
161
- number, and it did not exist until gh#931 - the box was two bare literals, so the only way
162
- to hit 44 was to override a library selector from this stylesheet. */
163
- --carousel-arrow-size: 2.75rem;
164
-
165
- /* Measure - the brand's content-max 1280 with 32px desktop gutters. */
166
- --page-measure-wide: 80rem;
167
- color-scheme: light;
168
- }
169
-
170
- /* ── Marketing surface (the consumer's own section stylesheet) ─────────────────────────────── */
171
- [data-tenant="tcgm"] { background: hsl(var(--background)); color: hsl(var(--foreground)); min-block-size: 100vh; }
172
- /* The gutter ladder is the prototype's own: .container is "100% - 64px" on desktop, "- 48px" under
173
- 1024 and "- 32px" under 768. A MEDIA query, not a container one — a container cannot query
174
- itself, and a page gutter is a viewport concern anyway. It is also what gives the 34px headline
175
- room at 390: on a flat 32px gutter the hero column was 278px and "もっと見つけよう。" broke
176
- before the final character. */
177
- [data-tenant="tcgm"] .tm-shell { margin-inline: auto; inline-size: 100%; max-inline-size: var(--page-measure-wide); padding-inline: var(--space-4); container-type: inline-size; }
178
- @media (min-width: 768px) { [data-tenant="tcgm"] .tm-shell { padding-inline: var(--space-6); } }
179
- @media (min-width: 1024px) { [data-tenant="tcgm"] .tm-shell { padding-inline: var(--space-8); } }
180
- [data-tenant="tcgm"] .tm-section { padding-block-start: var(--space-20); }
181
-
182
- /* The demo strip the prototype puts ABOVE the header. It is page chrome, not a Banner: it carries
183
- no action, no dismiss and no live region — the whole page is the sample it is labelling. */
184
- [data-tenant="tcgm"] .tm-demo-notice { background: hsl(var(--accent)); border-block-end: var(--stroke-hairline) solid hsl(var(--border)); padding-block: var(--space-1); text-align: center; }
185
-
186
- /* The sticky header IS this page's bar region. Not a <Topbar>: that is the APPLICATION chrome
187
- (app launcher, org switcher, account cell), and a marketing header is a nav row — the same call
188
- acme-website.tsx and futurelastic-web.tsx each made. */
189
- [data-tenant="tcgm"] .tm-header { position: sticky; inset-block-start: 0; z-index: 30; background: hsl(var(--card)); border-block-end: var(--stroke-hairline) solid hsl(var(--border)); }
190
- [data-tenant="tcgm"] .tm-header-inner { min-block-size: 80px; display: flex; align-items: center; column-gap: var(--space-8); row-gap: var(--space-2); flex-wrap: wrap; padding-block: var(--space-2); }
191
- [data-tenant="tcgm"] .tm-brand { display: block; inline-size: 164px; max-inline-size: 42vw; }
192
- [data-tenant="tcgm"] .tm-eyebrow { font-family: var(--tm-latin); font-weight: 700; font-size: 0.6875rem; line-height: 1.4; letter-spacing: .16em; text-transform: uppercase; color: hsl(var(--primary)); }
193
-
194
- /* The Latin-label face. 02_TYPOGRAPHY: Montserrat is for "Latin short labels/prices" only, so it
195
- is opted into per element rather than inherited by a whole subtree of Japanese. */
196
- [data-tenant="tcgm"] .tm-latin { font-family: var(--tm-latin); }
197
-
198
- /* Responsive VISIBILITY, the only thing the header needs a class for: which controls a phone shows
199
- is presentation, so it belongs in the brand stylesheet rather than as props on four Buttons. */
200
- [data-tenant="tcgm"] .tm-desktop-only { display: none; }
201
- [data-tenant="tcgm"] .tm-mobile-only { display: inline-flex; }
202
- @container (min-width: 768px) {
203
- [data-tenant="tcgm"] .tm-desktop-only { display: inline-flex; }
204
- [data-tenant="tcgm"] .tm-mobile-only { display: none; }
205
- }
206
-
207
- /* HERO. Prism Wash = two low-opacity radial washes, the brand's own motif, and the reason the
208
- library's .ui-brand-glow is NOT used here: that halo is one brand-coloured lobe, and this brand
209
- wants two in two different accents. Static, per "Homepage hero là static, không slideshow". */
210
- [data-tenant="tcgm"] .tm-hero { position: relative; overflow: hidden; margin-block-start: var(--space-8); border: var(--stroke-hairline) solid hsl(var(--border)); border-radius: 32px;
211
- background: radial-gradient(ellipse at 90% 0%, hsl(var(--secondary)), transparent 65%), radial-gradient(ellipse at 0% 100%, hsl(var(--accent)), transparent 70%), hsl(var(--card));
212
- display: grid; grid-template-columns: 1fr; align-items: center; }
213
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-hero { grid-template-columns: 1.15fr 1fr; min-block-size: 460px; } }
214
- [data-tenant="tcgm"] .tm-hero-copy { padding: var(--space-8) var(--space-6) 0; max-inline-size: 650px; }
215
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-hero-copy { padding: var(--space-12) 0 var(--space-12) var(--space-12); } }
216
- [data-tenant="tcgm"] .tm-hero-search { max-inline-size: 550px; }
217
- [data-tenant="tcgm"] .tm-hero-art { position: relative; min-inline-size: 0; block-size: 212px; overflow: hidden; }
218
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-hero-art { block-size: auto; align-self: stretch; overflow: visible; } }
219
- [data-tenant="tcgm"] .tm-hero-art img { position: absolute; inset-block-start: -58px; inset-inline-end: -14px; inline-size: 460px; max-inline-size: none; }
220
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-hero-art img { inset-block: 0; inset-inline: -6% auto; inline-size: 128%; block-size: 100%; object-fit: contain; } }
221
- /* The reveal WRAPS the art, so the observer measures the art's box and the copy is never inside a
222
- box that starts at opacity 0 — the spec's "text hiện ngay" is structural, not a delay of 0. */
223
- [data-tenant="tcgm"] .tm-hero-art .ui-reveal { display: contents; }
224
- [data-tenant="tcgm"] .tm-art-tag { position: absolute; inset-block-end: 49px; inset-inline-end: 30px; display: none; align-items: center; gap: var(--space-2);
225
- background: hsl(var(--card) / .92); border: var(--stroke-hairline) solid hsl(var(--border)); padding: var(--space-3) var(--space-4); border-radius: 14px; box-shadow: var(--shadow-sm); rotate: -4deg; }
226
- @container (min-width: 1024px) { [data-tenant="tcgm"] .tm-art-tag { display: flex; } }
227
-
228
- /* Card artwork sits in a 3:4-ish WELL and is "contain"-fitted — the brand forbids cropping a card's
229
- code or border away (04_ART_DIRECTION "Image ratios"). */
230
- [data-tenant="tcgm"] .tm-artwell { position: relative; display: grid; place-items: center; block-size: 220px; margin-block-end: var(--space-4);
231
- border-radius: 12px; background: linear-gradient(145deg, hsl(var(--muted)), hsl(var(--background))); }
232
- [data-tenant="tcgm"] .tm-artwell img { block-size: 196px; inline-size: 140px; object-fit: contain; filter: drop-shadow(0 6px 10px rgb(15 76 92 / .09)); }
233
- [data-tenant="tcgm"] .tm-sample { position: absolute; inset-block-start: var(--space-2); inset-inline-start: var(--space-2); }
234
- [data-tenant="tcgm"] .tm-watch { position: absolute; inset-block-start: var(--space-3); inset-inline-end: var(--space-3); z-index: 1; background: hsl(var(--card)); }
235
- [data-tenant="tcgm"] .tm-watch[aria-pressed="true"] svg { fill: currentColor; }
236
- [data-tenant="tcgm"] .tm-card-body { position: relative; }
237
- [data-tenant="tcgm"] .tm-card-name { min-block-size: 3.2em; }
238
- [data-tenant="tcgm"] .tm-price-row { display: flex; align-items: end; justify-content: space-between; gap: var(--space-2);
239
- margin-block-start: var(--space-3); padding-block-start: var(--space-3); border-block-start: var(--stroke-hairline) solid hsl(var(--border)); }
240
- /* The trailing "送料別 / サンプル" note is dropped on a narrow card, exactly as the prototype drops
241
- it ("@media(max-width:767px){.card-price>.caption{display:none}}"). At 390 the two-up grid gives
242
- each card ~163px: keeping the note squeezed the price label into three lines and pushed the
243
- figure — the one thing the card exists to show — off its own baseline. The same sentence is
244
- already carried by the section note above the grid, so nothing is lost.
245
- A MEDIA query, like the prototype: an unnamed "@container" resolves against the nearest ancestor
246
- container, which here is the grid (358px at 390), never the 163px card — it measured "shown" at
247
- 390. Making the card its own container would work but buys nothing over the viewport rule the
248
- prototype already specifies. */
249
- [data-tenant="tcgm"] .tm-price-note { display: none; }
250
- @media (min-width: 768px) { [data-tenant="tcgm"] .tm-price-note { display: block; } }
251
-
252
- /* News cover. 16:9, the wordmark plate sits OUTSIDE the artwork's focal area. */
253
- [data-tenant="tcgm"] .tm-news-cover { position: relative; block-size: 180px; overflow: hidden; background: hsl(var(--secondary)); }
254
- [data-tenant="tcgm"] .tm-news-cover img { inline-size: 100%; block-size: 100%; object-fit: cover; object-position: center 39%; }
255
- [data-tenant="tcgm"] .tm-news-word { position: absolute; inset-block-end: var(--space-5); inset-inline-start: var(--space-6); font-family: var(--tm-latin); font-weight: 700; font-size: 1.5rem; line-height: 1.2; letter-spacing: .04em;
256
- color: hsl(var(--primary)); background: hsl(var(--card) / .92); padding: var(--space-1) var(--space-3); border-radius: 6px; }
257
-
258
- /* Release row — the date box is the brand's Sand surface. */
259
- [data-tenant="tcgm"] .tm-datebox { inline-size: 58px; flex: 0 0 auto; text-align: center; border-radius: 12px; padding: var(--space-2);
260
- background: #FAF5EF; font-family: var(--tm-latin); color: hsl(var(--primary)); }
261
-
262
- /* Trust band — Sand, the one warm surface in the system. */
263
- [data-tenant="tcgm"] .tm-trust { background: #FAF5EF; border: var(--stroke-hairline) solid #EBE4DB; border-radius: 28px; padding: var(--space-12); }
264
- [data-tenant="tcgm"] .tm-trust-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-8); }
265
- @container (min-width: 1024px) { [data-tenant="tcgm"] .tm-trust-grid { grid-template-columns: 1fr 1.35fr; gap: var(--space-16, 4rem); } }
266
- [data-tenant="tcgm"] .tm-trust-icon { inline-size: 44px; block-size: 44px; flex: 0 0 auto; display: grid; place-items: center; border-radius: 14px; background: hsl(var(--card)); color: hsl(var(--primary)); }
267
-
268
- [data-tenant="tcgm"] .tm-footer { margin-block-start: var(--space-20); border-block-start: var(--stroke-hairline) solid hsl(var(--border)); background: hsl(var(--card)); padding-block: var(--space-12) var(--space-8); }
269
- [data-tenant="tcgm"] .tm-footer-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-6); }
270
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-footer-grid { grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--space-10); } }
271
- [data-tenant="tcgm"] .tm-footer-main { grid-column: 1 / -1; }
272
- @container (min-width: 768px) { [data-tenant="tcgm"] .tm-footer-main { grid-column: auto; } }
273
-
274
- /* The one piece of motion written by hand rather than tokenised, and it is written ONCE: the
275
- artwork inside a hovered card follows the card's own lift. "@media (hover: hover)" so a touch
276
- device never sticks in a hover state, and the reduced-motion branch is not optional. */
277
- @media (hover: hover) {
278
- [data-tenant="tcgm"] .ui-card:hover .tm-artwell img { transform: translateY(-2px) scale(1.02); }
279
- }
280
- [data-tenant="tcgm"] .tm-artwell img { transition: transform var(--duration-base) var(--ease-standard); }
281
- @media (prefers-reduced-motion: reduce) {
282
- [data-tenant="tcgm"] .tm-artwell img { transition: none; transform: none; }
283
- }
284
- `;
285
-
286
- // ── Sample data. The SHAPE lives here; every word lives in `docs/i18n/messages/{ja,en,vi}.json`
287
- // under `tcgm.*` and arrives through `t()`.
288
- //
289
- // That split is not decoration. A showcase is what the MCP catalog quotes and what a consumer
290
- // copy-pastes, and the library's own chrome (Carousel slide labels, EmptyState, dismiss buttons)
291
- // already follows the viewer's locale — so a hard-coded Japanese label next to it renders TWO
292
- // languages in one row, and teaches the library's first rule backwards. `check:no-consumer-coupling`
293
- // holds new docs files at zero hard-coded locale content for exactly that reason; it caught this
294
- // page with 51. `docs/showcase/caimono-price-comparison.tsx` is the same brief solved the same way.
295
- //
296
- // Every card, price, shop and date is FICTIONAL by design: the brand's own `01_POSITIONING.md`
297
- // forbids implying coverage or a market price it does not have.
298
- type Game = "all" | "pokemon" | "onepiece" | "yugioh" | "duel" | "mtg" | "other";
299
-
300
- const GAMES: Game[] = ["all", "pokemon", "onepiece", "yugioh", "duel", "mtg", "other"];
301
-
302
- type SampleCard = {
303
- id: string;
304
- game: Exclude<Game, "all">;
305
- code: string;
306
- price: number | null;
307
- art: string;
308
- };
309
-
310
- const CARDS: SampleCard[] = [
311
- { id: "demo-01", game: "pokemon", code: "SAMPLE-A001", price: 1280, art: card1 },
312
- { id: "demo-02", game: "onepiece", code: "SAMPLE-B002", price: 2480, art: card2 },
313
- { id: "demo-03", game: "yugioh", code: "SAMPLE-C003", price: 680, art: card3 },
314
- { id: "demo-04", game: "duel", code: "SAMPLE-D004", price: 3980, art: card4 },
315
- { id: "demo-05", game: "mtg", code: "SAMPLE-E005", price: 980, art: card5 },
316
- // The deliberate edge case the handoff ships: NO price. "no price listed" is not zero, and the
317
- // 〜 suffix is dropped with it — 02_VERBAL_IDENTITY is explicit about both.
318
- { id: "demo-06", game: "other", code: "SAMPLE-F006", price: null, art: card6 },
319
- ];
320
-
321
- const NEWS: Array<{ id: string; word: string; art: string }> = [
322
- { id: "compare", word: "COMPARE\nWITH CARE.", art: scene1 },
323
- { id: "edition", word: "FIND YOUR\nEDITION.", art: scene2 },
324
- { id: "watch", word: "YOUR NEXT\nDISCOVERY.", art: scene3 },
325
- { id: "sources", word: "READ THE\nDETAILS.", art: scene4 },
326
- ];
327
-
328
- const RELEASES: Array<{ id: string; day: string }> = [
329
- { id: "prism", day: "25" },
330
- { id: "notes", day: "28" },
331
- { id: "study", day: "30" },
332
- ];
333
-
334
- const TRUST: Array<{ id: string; icon: typeof Layers }> = [
335
- { id: "edition", icon: Layers },
336
- { id: "freshness", icon: Clock },
337
- { id: "ads", icon: ShieldCheck },
338
- ];
339
-
340
- const NAV = ["cards", "news", "calendar"] as const;
341
-
342
- const SHELL = "tm-shell";
343
-
344
- /**
345
- * `Intl.NumberFormat` in the product's own locale, never a hand-rolled thousands separator — and
346
- * `currency: "JPY"` rather than a "¥" + number concatenation, so the sign, the grouping and the
347
- * (absent) minor unit are all the locale's answer. The brand: "JPY không thêm hai số thập phân".
348
- */
349
- function jpy(locale: string) {
350
- return new Intl.NumberFormat(locale, {
351
- style: "currency",
352
- currency: "JPY",
353
- currencyDisplay: "symbol",
354
- });
355
- }
356
-
357
- // ── Sections ───────────────────────────────────────────────────────────────────────────────────
358
-
359
- function DemoNotice() {
360
- const { t } = useTranslation();
361
- return (
362
- <div className="tm-demo-notice">
363
- <Text as="p" size="2xs" tone="default">
364
- {t("tcgm.demoNotice")}
365
- </Text>
366
- </div>
367
- );
368
- }
369
-
370
- function Header({ onMenu }: { onMenu: () => void }) {
371
- const { t } = useTranslation();
372
- return (
373
- <header className="tm-header">
374
- <div className={`${SHELL} tm-header-inner`}>
375
- <img className="tm-brand" src={lockup} alt={t("tcgm.brandAlt")} width={164} height={52} />
376
- <nav aria-label={t("tcgm.nav.label")} className="tm-desktop-only">
377
- <Flex direction="row" gap="xs" align="center" wrap>
378
- {NAV.map((key, i) => (
379
- <Button
380
- key={key}
381
- variant="ghost"
382
- size="sm"
383
- aria-current={i === 0 ? "page" : undefined}
384
- >
385
- {t(`tcgm.nav.${key}`)}
386
- </Button>
387
- ))}
388
- </Flex>
389
- </nav>
390
- <Flex direction="row" gap="xs" align="center" className="ms-auto">
391
- <Button
392
- variant="ghost"
393
- size="icon"
394
- aria-label={t("tcgm.header.search")}
395
- className="tm-desktop-only"
396
- >
397
- <Search aria-hidden="true" />
398
- </Button>
399
- <Button variant="ghost" size="icon" aria-label={t("tcgm.header.watchlist")}>
400
- <Heart aria-hidden="true" />
401
- </Button>
402
- <Button variant="outline" size="sm" className="tm-desktop-only">
403
- {t("tcgm.header.tryApp")}
404
- </Button>
405
- <Button
406
- variant="ghost"
407
- size="icon"
408
- aria-label={t("tcgm.header.openMenu")}
409
- className="tm-mobile-only"
410
- onClick={onMenu}
411
- >
412
- <Menu aria-hidden="true" />
413
- </Button>
414
- </Flex>
415
- </div>
416
- </header>
417
- );
418
- }
419
-
420
- function Hero({ onSearch }: { onSearch: (q: string) => void }) {
421
- const { t } = useTranslation();
422
- const hints: Array<[typeof Layers, string]> = [
423
- [Layers, t("tcgm.hero.hintTitles")],
424
- [ArrowLeftRight, t("tcgm.hero.hintCompare")],
425
- [Sparkles, t("tcgm.hero.hintDiscover")],
426
- ];
427
- return (
428
- <div className={SHELL}>
429
- <section className="tm-hero">
430
- {/* NO Reveal around the copy. 04_MOTION_AND_STATES: "Hero once 480ms … chỉ illustration,
431
- text hiện ngay" — the headline and the search field must be readable and operable on
432
- the first frame, so only the artwork below is wrapped. */}
433
- <div className="tm-hero-copy">
434
- <Flex direction="col" gap="md" align="start">
435
- <p className="tm-eyebrow">{t("tcgm.hero.eyebrow")}</p>
436
- <Heading level={1} size="5xl" weight="bold">
437
- {t("tcgm.hero.titleLine1")}
438
- <br />
439
- {t("tcgm.hero.titleLine2")}
440
- </Heading>
441
- <Text as="p" size="md" tone="muted">
442
- {t("tcgm.hero.leadLine1")}
443
- <br />
444
- {t("tcgm.hero.leadLine2")}
445
- </Text>
446
- <SearchInput
447
- className="tm-hero-search"
448
- placeholder={t("tcgm.hero.searchPlaceholder")}
449
- ariaLabel={t("tcgm.hero.searchLabel")}
450
- onSearch={onSearch}
451
- />
452
- <Flex direction="row" gap="md" wrap>
453
- {hints.map(([Glyph, label]) => (
454
- <Flex key={label} direction="row" gap="xs" align="center">
455
- <Icon as={Glyph} size="xs" tone="muted" />
456
- <Text as="span" size="2xs" tone="muted">
457
- {label}
458
- </Text>
459
- </Flex>
460
- ))}
461
- </Flex>
462
- </Flex>
463
- </div>
464
- <div className="tm-hero-art">
465
- {/* The hero's ONE decorative motion region, played once on mount at the brand's
466
- 480ms/y8 timing. `Reveal` drops the animation entirely under prefers-reduced-motion
467
- and its resting state is the FINISHED one, so the artwork is never hidden. */}
468
- <Reveal on="mount">
469
- <img
470
- src={heroPrism}
471
- alt={t("tcgm.hero.artAlt")}
472
- width={1200}
473
- height={760}
474
- fetchPriority="high"
475
- />
476
- </Reveal>
477
- <div className="tm-art-tag">
478
- <Icon as={Sparkles} size="xs" tone="primary" />
479
- <Text as="span" size="2xs">
480
- {t("tcgm.hero.artTag")}
481
- </Text>
482
- </div>
483
- </div>
484
- </section>
485
- </div>
486
- );
487
- }
488
-
489
- function GameRail({ value, onValueChange }: { value: Game; onValueChange: (g: Game) => void }) {
490
- const { t } = useTranslation();
491
- return (
492
- <div className={SHELL}>
493
- <ToggleGroup
494
- type="single"
495
- disallowEmptySelection
496
- variant="outline"
497
- shape="pill"
498
- size="lg"
499
- wrap
500
- value={value}
501
- onValueChange={(v) => onValueChange(v as Game)}
502
- aria-label={t("tcgm.games.label")}
503
- className="mt-6"
504
- >
505
- {GAMES.map((key) => (
506
- <ToggleGroupItem key={key} value={key}>
507
- {t(`tcgm.games.${key}`)}
508
- </ToggleGroupItem>
509
- ))}
510
- </ToggleGroup>
511
- </div>
512
- );
513
- }
514
-
515
- function SectionHead({
516
- eyebrow,
517
- title,
518
- action,
519
- }: {
520
- eyebrow: string;
521
- title: React.ReactNode;
522
- action?: string;
523
- }) {
524
- return (
525
- <Flex direction="row" justify="between" align="end" gap="md" wrap>
526
- <Flex direction="col" gap="xs">
527
- <p className="tm-eyebrow">{eyebrow}</p>
528
- <Heading level={2} size="3xl" weight="bold">
529
- {title}
530
- </Heading>
531
- </Flex>
532
- {action ? (
533
- <Button variant="link" size="sm">
534
- {action}
535
- <ArrowRight aria-hidden="true" />
536
- </Button>
537
- ) : null}
538
- </Flex>
539
- );
540
- }
541
-
542
- function TradingCard({
543
- card,
544
- watched,
545
- onWatch,
546
- }: {
547
- card: SampleCard;
548
- watched: boolean;
549
- onWatch: (card: SampleCard) => void;
550
- }) {
551
- // NOT `Card asChild`: this card contains a second control (the watch toggle), and a card that is
552
- // itself one link may not contain another — `hoverable` + a real control inside is the branch
553
- // the Card docblock names for exactly this shape.
554
- const { t, locale } = useTranslation();
555
- const name = t(`tcgm.cards.${card.id}.name`);
556
- return (
557
- <Card hoverable className="tm-card-body">
558
- <Button
559
- className="tm-watch"
560
- variant="ghost"
561
- size="icon"
562
- aria-pressed={watched}
563
- // The accessible name says what the press will DO, and it is a whole message per state —
564
- // never a sentence glued together from a name and a verb, which is unbuildable in a
565
- // language that puts them in the other order.
566
- aria-label={t(watched ? "tcgm.card.watchRemove" : "tcgm.card.watchAdd", { name })}
567
- onClick={() => onWatch(card)}
568
- >
569
- <Heart aria-hidden="true" />
570
- </Button>
571
- <CardContent solo>
572
- <Flex direction="col" gap="xs">
573
- <div className="tm-artwell">
574
- <Badge className="tm-sample" variant="outline" tone="default" as="span">
575
- {t("tcgm.card.sampleBadge")}
576
- </Badge>
577
- <img
578
- src={card.art}
579
- alt={t("tcgm.card.artAlt", { name })}
580
- width={140}
581
- height={196}
582
- loading="lazy"
583
- />
584
- </div>
585
- <Text as="p" size="2xs" tone="muted">
586
- {t("tcgm.card.classifiedAs", { game: t(`tcgm.games.${card.game}`) })}
587
- </Text>
588
- <Heading level={3} size="sm" weight="bold" className="tm-card-name">
589
- {name}
590
- </Heading>
591
- <Text as="p" size="2xs" tone="muted" tabular className="tm-latin">
592
- {card.code} · {t(`tcgm.cards.${card.id}.edition`)}
593
- </Text>
594
- <div className="tm-price-row">
595
- <Flex direction="col" gap={1}>
596
- <Text as="span" size="2xs" tone="muted">
597
- {t("tcgm.card.priceLabel")}
598
- </Text>
599
- {card.price === null ? (
600
- <Text as="span" size="sm" weight="bold" tone="muted">
601
- {t("tcgm.card.noPrice")}
602
- </Text>
603
- ) : (
604
- <Text
605
- as="span"
606
- size="2xl"
607
- weight="bold"
608
- tone="primary"
609
- tabular
610
- className="tm-latin"
611
- >
612
- {jpy(locale).format(card.price)}
613
- <Text as="span" size="2xs" weight="regular" tone="muted">
614
- 〜
615
- </Text>
616
- </Text>
617
- )}
618
- </Flex>
619
- <Text as="span" size="2xs" tone="muted" align="end" className="tm-price-note">
620
- {t("tcgm.card.shippingNote")}
621
- <br />
622
- {t("tcgm.card.sampleNote")}
623
- </Text>
624
- </div>
625
- </Flex>
626
- </CardContent>
627
- </Card>
628
- );
629
- }
630
-
631
- /**
632
- * The card grid. `columns` steps are CONTAINER widths, not viewport ones, which is why the third
633
- * column is keyed to `sm` (40rem) and not `md`: inside the 1280px shell the grid's own box is the
634
- * viewport minus the 32px gutters, so a 768 tablet hands it 704px. Keyed to `md` (48rem) it stayed
635
- * 2-up there, where the prototype shows 3.
636
- */
637
- function Collection({
638
- cards,
639
- watched,
640
- onWatch,
641
- onReset,
642
- }: {
643
- cards: SampleCard[];
644
- watched: ReadonlySet<string>;
645
- onWatch: (card: SampleCard) => void;
646
- onReset: () => void;
647
- }) {
648
- const { t } = useTranslation();
649
- return (
650
- <section className={`${SHELL} tm-section`}>
651
- <Flex direction="col" gap="lg">
652
- <Reveal on="view">
653
- <SectionHead
654
- eyebrow={t("tcgm.collection.eyebrow")}
655
- title={t("tcgm.collection.title")}
656
- action={t("tcgm.collection.action")}
657
- />
658
- </Reveal>
659
- <Text as="p" size="2xs" tone="muted" role="status">
660
- {/* The count goes THROUGH the message, so a locale that pluralises decides its own
661
- form — never `{n}` glued to a literal counter word at the call site. */}
662
- {t("tcgm.collection.count", { count: cards.length })} · {t("tcgm.collection.note")}
663
- </Text>
664
- {cards.length ? (
665
- <ResponsiveGrid columns={{ base: 2, sm: 3, lg: 4 }} gap="lg" align="stretch">
666
- {cards.map((card, i) => (
667
- // `on="view"` + a stagger ordinal: the row cascades in as it reaches the viewport,
668
- // capped at the ladder's 6 steps so a long list never waits half a second.
669
- <Reveal key={card.id} on="view" delay={(Math.min(i, 5) + 1) as 1 | 2 | 3 | 4 | 5 | 6}>
670
- <TradingCard card={card} watched={watched.has(card.id)} onWatch={onWatch} />
671
- </Reveal>
672
- ))}
673
- </ResponsiveGrid>
674
- ) : (
675
- <EmptyState
676
- variant="section"
677
- icon={Layers}
678
- title={t("tcgm.collection.emptyTitle")}
679
- description={t("tcgm.collection.emptyBody")}
680
- action={
681
- <Button variant="outline" onClick={onReset}>
682
- {t("tcgm.collection.reset")}
683
- </Button>
684
- }
685
- />
686
- )}
687
- </Flex>
688
- </section>
689
- );
690
- }
691
-
692
- function NewsRail() {
693
- const { t } = useTranslation();
694
- return (
695
- <section className={`${SHELL} tm-section`}>
696
- <Flex direction="col" gap="lg">
697
- <Reveal on="view">
698
- <SectionHead
699
- eyebrow={t("tcgm.news.eyebrow")}
700
- title={t("tcgm.news.title")}
701
- action={t("tcgm.news.action")}
702
- />
703
- </Reveal>
704
- {/* Manual by default, with real previous/next controls beside the rail. The brand allows
705
- autoplay only behind a pause control and forbids it as the default; the library's
706
- Carousel ships no autoplay plugin unless one is passed, so the default IS the spec.
707
-
708
- THE REVEAL WRAPS THE RAIL, NOT THE SLIDES — and this is a measured correction, not a
709
- preference. Per-slide `on="view"` put an IntersectionObserver on a box the carousel
710
- viewport CLIPS (`overflow: hidden`), so a slide parked outside the window has an empty
711
- intersection rect and never leaves `data-reveal-state="out"`: measured on this page at
712
- 1440, 3 of the 4 slides sat at opacity 0 after scrolling the whole document, and stayed
713
- there. That is the one failure Reveal's own docblock forbids — "a reveal that never
714
- reveals". One observer on the unclipped section answers instead, and it also keeps the
715
- brand's motion budget (one decorative motion region per viewport) rather than spending
716
- it on four staggered cards inside a rail. */}
717
- <Reveal on="view">
718
- <Carousel opts={{ align: "start", containScroll: "trimSnaps" }}>
719
- <CarouselContent>
720
- {NEWS.map((n) => (
721
- <CarouselItem key={n.id} className="basis-4/5 sm:basis-1/2 lg:basis-1/3">
722
- <Card hoverable className="h-full overflow-hidden">
723
- <div className="tm-news-cover">
724
- <img src={n.art} alt="" loading="lazy" />
725
- <span className="tm-news-word">
726
- {n.word.split("\n").map((line, li) => (
727
- <React.Fragment key={line}>
728
- {li ? <br /> : null}
729
- {line}
730
- </React.Fragment>
731
- ))}
732
- </span>
733
- </div>
734
- <CardContent solo>
735
- <Flex direction="col" gap="sm" align="start">
736
- <Flex direction="row" gap="sm" align="center" wrap>
737
- <Badge variant="secondary" as="span">
738
- {t(`tcgm.articles.${n.id}.cat`)}
739
- </Badge>
740
- <Text as="span" size="2xs" tone="muted">
741
- {t("tcgm.news.sample")}
742
- </Text>
743
- </Flex>
744
- <Heading level={3} size="md" weight="bold">
745
- {t(`tcgm.articles.${n.id}.title`)}
746
- </Heading>
747
- <Text as="p" size="2xs" tone="muted" tabular>
748
- {t("tcgm.news.meta")}
749
- </Text>
750
- </Flex>
751
- </CardContent>
752
- </Card>
753
- </CarouselItem>
754
- ))}
755
- </CarouselContent>
756
- <Flex direction="row" gap="sm" align="center" justify="end" className="mt-4">
757
- <Text as="span" size="2xs" tone="muted" className="me-auto">
758
- {t("tcgm.news.manual")}
759
- </Text>
760
- <CarouselPrevious />
761
- <CarouselNext />
762
- </Flex>
763
- </Carousel>
764
- </Reveal>
765
- </Flex>
766
- </section>
767
- );
768
- }
769
-
770
- function Releases({ onPick }: { onPick: (title: string) => void }) {
771
- const { t } = useTranslation();
772
- return (
773
- <section className={`${SHELL} tm-section`}>
774
- <Flex direction="col" gap="lg">
775
- <Reveal on="view">
776
- <SectionHead
777
- eyebrow={t("tcgm.releases.eyebrow")}
778
- title={t("tcgm.releases.title")}
779
- action={t("tcgm.releases.action")}
780
- />
781
- </Reveal>
782
- <ResponsiveGrid columns={{ base: 1, md: 3 }} gap="md" align="stretch">
783
- {RELEASES.map((r, i) => (
784
- <Reveal key={r.id} on="view" delay={(i + 1) as 1 | 2 | 3}>
785
- <Card hoverable className="h-full">
786
- <CardContent solo>
787
- <Flex direction="row" gap="md" align="center">
788
- <div className="tm-datebox">
789
- <Text as="span" size="2xs" tone="inherit" className="block tracking-widest">
790
- SEP
791
- </Text>
792
- <Text
793
- as="span"
794
- size="2xl"
795
- weight="bold"
796
- tone="inherit"
797
- tabular
798
- className="tm-latin"
799
- >
800
- {r.day}
801
- </Text>
802
- </div>
803
- <Flex direction="col" gap={1} className="min-w-0">
804
- <Text as="span" size="2xs" tone="muted">
805
- {t(`tcgm.release.${r.id}.kind`)}
806
- </Text>
807
- <Heading level={3} size="sm" weight="bold">
808
- {t(`tcgm.release.${r.id}.title`)}
809
- </Heading>
810
- <Button
811
- variant="link"
812
- size="xs"
813
- className="justify-start"
814
- onClick={() => onPick(t(`tcgm.release.${r.id}.title`))}
815
- >
816
- {t("tcgm.releases.view")}
817
- <ArrowRight aria-hidden="true" />
818
- </Button>
819
- </Flex>
820
- </Flex>
821
- </CardContent>
822
- </Card>
823
- </Reveal>
824
- ))}
825
- </ResponsiveGrid>
826
- </Flex>
827
- </section>
828
- );
829
- }
830
-
831
- function Trust() {
832
- const { t } = useTranslation();
833
- return (
834
- <section className={`${SHELL} tm-section`}>
835
- <Reveal on="view">
836
- <div className="tm-trust">
837
- <div className="tm-trust-grid">
838
- <Flex direction="col" gap="md" align="start">
839
- <p className="tm-eyebrow">{t("tcgm.trust.eyebrow")}</p>
840
- <Heading level={2} size="3xl" weight="bold">
841
- {t("tcgm.trust.titleLine1")}
842
- <br />
843
- {t("tcgm.trust.titleLine2")}
844
- </Heading>
845
- <Text as="p" size="sm" tone="muted">
846
- {t("tcgm.trust.bodyLine1")}
847
- <br />
848
- {t("tcgm.trust.bodyLine2")}
849
- </Text>
850
- <Button variant="link" size="sm" className="px-0">
851
- {t("tcgm.trust.link")}
852
- <ArrowRight aria-hidden="true" />
853
- </Button>
854
- </Flex>
855
- <Flex direction="col" gap="lg">
856
- {TRUST.map((item, i) => (
857
- <Reveal key={item.id} on="view" delay={(i + 1) as 1 | 2 | 3}>
858
- <Flex direction="row" gap="md" align="start">
859
- <span className="tm-trust-icon">
860
- <Icon as={item.icon} size="md" tone="inherit" />
861
- </span>
862
- <Flex direction="col" gap={1}>
863
- <Heading level={3} size="sm" weight="bold">
864
- {t(`tcgm.trust.${item.id}Title`)}
865
- </Heading>
866
- <Text as="p" size="sm" tone="muted">
867
- {t(`tcgm.trust.${item.id}Body`)}
868
- </Text>
869
- </Flex>
870
- </Flex>
871
- </Reveal>
872
- ))}
873
- </Flex>
874
- </div>
875
- </div>
876
- </Reveal>
877
- </section>
878
- );
879
- }
880
-
881
- function Footer() {
882
- const { t } = useTranslation();
883
- const cols: Array<[string, string[]]> = [
884
- ["colFind", ["linkSearch", "linkCompare", "linkWatchlist"]],
885
- ["colRead", ["linkNews", "linkCalendar", "linkBasics"]],
886
- ["colAbout", ["linkMethod", "linkComponents", "linkConsent"]],
887
- ];
888
- return (
889
- <footer className="tm-footer">
890
- <div className={`${SHELL} tm-footer-grid`}>
891
- <Flex direction="col" gap="sm" className="tm-footer-main">
892
- <img
893
- className="tm-brand"
894
- src={lockup}
895
- alt={t("tcgm.brandAlt")}
896
- width={164}
897
- height={52}
898
- loading="lazy"
899
- />
900
- <Text as="p" size="sm" tone="muted">
901
- {t("tcgm.footer.taglineLine1")}
902
- <br />
903
- {t("tcgm.footer.taglineLine2")}
904
- </Text>
905
- <Text as="p" size="2xs" tone="muted">
906
- {t("tcgm.footer.accent")}
907
- </Text>
908
- </Flex>
909
- {cols.map(([head, items]) => (
910
- <Flex key={head} direction="col" gap="xs" align="start">
911
- <Text as="div" size="2xs" weight="bold">
912
- {t(`tcgm.footer.${head}`)}
913
- </Text>
914
- {items.map((item) => (
915
- <Button key={item} variant="link" size="sm" className="text-muted-foreground px-0">
916
- {t(`tcgm.footer.${item}`)}
917
- </Button>
918
- ))}
919
- </Flex>
920
- ))}
921
- </div>
922
- <div className={SHELL}>
923
- <Separator space="lg" />
924
- <Flex direction="row" justify="between" gap="sm" wrap>
925
- <Text as="span" size="2xs" tone="muted">
926
- {t("tcgm.footer.legal")}
927
- </Text>
928
- <Text as="span" size="2xs" tone="muted">
929
- {t("tcgm.footer.disclaimer")}
930
- </Text>
931
- </Flex>
932
- </div>
933
- </footer>
934
- );
935
- }
936
-
937
- // ── Page ───────────────────────────────────────────────────────────────────────────────────────
938
-
939
- export default function TcgmWebsiteShowcase() {
940
- const { t } = useTranslation();
941
- const [game, setGame] = React.useState<Game>("all");
942
- const [query, setQuery] = React.useState("");
943
- const [watched, setWatched] = React.useState<ReadonlySet<string>>(() => new Set());
944
- const [menuOpen, setMenuOpen] = React.useState(false);
945
- const [release, setRelease] = React.useState<string | null>(null);
946
-
947
- const cards = React.useMemo(() => {
948
- const q = query.trim().toLowerCase();
949
- // Searching the RENDERED strings, not a frozen copy of them: the card's name and edition are
950
- // whatever the active locale says they are, so a viewer typing in the language on screen finds
951
- // the card. `localeCompare`-free because this is a substring test, not an ordering.
952
- return CARDS.filter(
953
- (c) =>
954
- (game === "all" || c.game === game) &&
955
- (!q ||
956
- [
957
- t(`tcgm.cards.${c.id}.name`),
958
- c.code,
959
- t(`tcgm.cards.${c.id}.edition`),
960
- t(`tcgm.games.${c.game}`),
961
- ].some((field) => field.toLowerCase().includes(q))),
962
- );
963
- }, [game, query, t]);
964
-
965
- const handleWatch = React.useCallback(
966
- (card: SampleCard) => {
967
- setWatched((prev) => {
968
- const next = new Set(prev);
969
- const had = next.has(card.id);
970
- if (had) next.delete(card.id);
971
- else next.add(card.id);
972
- // The brand's own copy for this pair (02_VERBAL_IDENTITY), and the demo must never imply a
973
- // sync or a notification it does not perform.
974
- toast(t(had ? "tcgm.toast.removed" : "tcgm.toast.saved"));
975
- return next;
976
- });
977
- },
978
- [t],
979
- );
980
-
981
- const reset = React.useCallback(() => {
982
- setGame("all");
983
- setQuery("");
984
- }, []);
985
-
986
- return (
987
- <div data-tenant="tcgm">
988
- <style>{THEME}</style>
989
- <DemoNotice />
990
- <Header onMenu={() => setMenuOpen(true)} />
991
- <main>
992
- <Hero onSearch={setQuery} />
993
- <GameRail value={game} onValueChange={setGame} />
994
- <Collection cards={cards} watched={watched} onWatch={handleWatch} onReset={reset} />
995
- <NewsRail />
996
- <Releases onPick={setRelease} />
997
- <Trust />
998
- </main>
999
- <Footer />
1000
-
1001
- <Sheet open={menuOpen} onOpenChange={setMenuOpen}>
1002
- <SheetContent side="right">
1003
- <SheetHeader>
1004
- <SheetTitle>{t("tcgm.header.menu")}</SheetTitle>
1005
- </SheetHeader>
1006
- <SheetBody>
1007
- <Flex direction="col" gap="xs" align="start">
1008
- {[...NAV, "watchlist", "method"].map((key) => (
1009
- <Button key={key} variant="ghost" size="lg" fullWidth className="justify-start">
1010
- {t(`tcgm.nav.${key}`)}
1011
- <ArrowRight aria-hidden="true" className="ms-auto" />
1012
- </Button>
1013
- ))}
1014
- </Flex>
1015
- </SheetBody>
1016
- </SheetContent>
1017
- </Sheet>
1018
-
1019
- <Dialog open={release !== null} onOpenChange={(open) => !open && setRelease(null)}>
1020
- <DialogContent>
1021
- <DialogHeader>
1022
- <DialogTitle>{t("tcgm.dialog.title")}</DialogTitle>
1023
- <DialogDescription>{t("tcgm.dialog.body")}</DialogDescription>
1024
- </DialogHeader>
1025
- <DialogBody>
1026
- <Flex direction="col" gap="sm" align="start">
1027
- <Badge variant="secondary" as="span">
1028
- {t("tcgm.dialog.sample")}
1029
- </Badge>
1030
- <Heading level={3} size="md" weight="bold">
1031
- {release}
1032
- </Heading>
1033
- <Flex direction="row" gap="xs" align="center">
1034
- <Icon as={CalendarDays} size="xs" tone="muted" />
1035
- <Text as="span" size="2xs" tone="muted" tabular>
1036
- {t("tcgm.dialog.date")}
1037
- </Text>
1038
- </Flex>
1039
- </Flex>
1040
- </DialogBody>
1041
- </DialogContent>
1042
- </Dialog>
1043
-
1044
- <Toaster />
1045
- </div>
1046
- );
1047
- }