@godxjp/ui 31.31.8 → 32.0.1

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