@godxjp/ui 31.31.7 → 32.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (728) hide show
  1. package/README.md +102 -121
  2. package/agent/START-HERE.md +10 -10
  3. package/agent/components/Accordion.json +2 -2
  4. package/agent/components/AccountChip.json +1 -1
  5. package/agent/components/Actions.json +1 -1
  6. package/agent/components/Activity.json +2 -2
  7. package/agent/components/Affix.json +1 -1
  8. package/agent/components/Alert.json +22 -6
  9. package/agent/components/AlertDialog.json +8 -1
  10. package/agent/components/Anchor.json +4 -3
  11. package/agent/components/AppLauncher.json +2 -2
  12. package/agent/components/AppProvider.json +19 -11
  13. package/agent/components/AppSettingPicker.json +18 -2
  14. package/agent/components/AppShell.json +4 -5
  15. package/agent/components/AreaChart.json +0 -1
  16. package/agent/components/AspectRatio.json +2 -2
  17. package/agent/components/Attachments.json +3 -3
  18. package/agent/components/AuthAccountSummary.json +1 -1
  19. package/agent/components/AuthDivider.json +1 -1
  20. package/agent/components/AuthExpiryProvider.json +0 -1
  21. package/agent/components/AuthFooter.json +2 -2
  22. package/agent/components/AuthIdentity.json +3 -3
  23. package/agent/components/AuthStack.json +1 -1
  24. package/agent/components/Avatar.json +2 -12
  25. package/agent/components/Badge.json +1 -1
  26. package/agent/components/BarChart.json +0 -1
  27. package/agent/components/BranchScopePicker.json +1 -1
  28. package/agent/components/Breadcrumb.json +1 -1
  29. package/agent/components/Button.json +3 -3
  30. package/agent/components/Calendar.json +1 -1
  31. package/agent/components/Card.json +2 -2
  32. package/agent/components/CardBar.json +0 -1
  33. package/agent/components/CardContent.json +0 -1
  34. package/agent/components/Carousel.json +4 -3
  35. package/agent/components/Cascader.json +1 -1
  36. package/agent/components/CenteredShell.json +78 -17
  37. package/agent/components/ChatBubble.json +3 -3
  38. package/agent/components/ChatBubbleList.json +3 -3
  39. package/agent/components/ChatComposer.json +3 -3
  40. package/agent/components/ChatSuggestion.json +3 -3
  41. package/agent/components/Checkbox.json +1 -1
  42. package/agent/components/CheckboxGroup.json +0 -1
  43. package/agent/components/CodeBlock.json +1 -1
  44. package/agent/components/Collapsible.json +4 -4
  45. package/agent/components/ColorPicker.json +1 -1
  46. package/agent/components/Command.json +5 -5
  47. package/agent/components/CommandPalette.json +1 -1
  48. package/agent/components/CompactBarTrend.json +1 -1
  49. package/agent/components/Conversations.json +3 -3
  50. package/agent/components/CredentialReveal.json +1 -1
  51. package/agent/components/DataState.json +2 -2
  52. package/agent/components/DataTable.json +1 -1
  53. package/agent/components/DatePicker.json +1 -1
  54. package/agent/components/Descriptions.json +1 -1
  55. package/agent/components/Dialog.json +2 -2
  56. package/agent/components/DraggablePanel.json +5 -4
  57. package/agent/components/DropdownMenu.json +1 -1
  58. package/agent/components/EmojiPicker.json +3 -2
  59. package/agent/components/EmptyState.json +1 -1
  60. package/agent/components/ErrorSurface.json +3 -3
  61. package/agent/components/FeatureList.json +1 -1
  62. package/agent/components/Field.json +0 -1
  63. package/agent/components/Flex.json +34 -4
  64. package/agent/components/FloatButton.json +6 -5
  65. package/agent/components/Form.json +1 -1
  66. package/agent/components/FormErrors.json +0 -1
  67. package/agent/components/FormField.json +6 -6
  68. package/agent/components/FormFieldArray.json +0 -1
  69. package/agent/components/FormFieldControl.json +0 -1
  70. package/agent/components/FormRoot.json +1 -1
  71. package/agent/components/Heading.json +3 -0
  72. package/agent/components/Icon.json +1 -1
  73. package/agent/components/Image.json +7 -4
  74. package/agent/components/InfiniteQueryState.json +1 -1
  75. package/agent/components/Input.json +1 -1
  76. package/agent/components/InputOTP.json +2 -2
  77. package/agent/components/Label.json +3 -3
  78. package/agent/components/LegalDocumentShell.json +5 -4
  79. package/agent/components/Legend.json +1 -1
  80. package/agent/components/LineChart.json +0 -1
  81. package/agent/components/Link.json +0 -1
  82. package/agent/components/ListRow.json +1 -1
  83. package/agent/components/Logo.json +5 -4
  84. package/agent/components/Marquee.json +4 -3
  85. package/agent/components/Masonry.json +4 -3
  86. package/agent/components/MasterDetail.json +1 -1
  87. package/agent/components/MegaMenu.json +4 -3
  88. package/agent/components/MobileShell.json +4 -4
  89. package/agent/components/NavList.json +1 -1
  90. package/agent/components/NumberInput.json +1 -1
  91. package/agent/components/OrgChart.json +4 -3
  92. package/agent/components/OrgSwitcher.json +1 -1
  93. package/agent/components/OverlayPortalProvider.json +0 -1
  94. package/agent/components/PageContainer.json +3 -3
  95. package/agent/components/PageCover.json +3 -2
  96. package/agent/components/Pagination.json +1 -1
  97. package/agent/components/PasswordInput.json +1 -1
  98. package/agent/components/PasswordStrength.json +1 -1
  99. package/agent/components/PermissionMatrix.json +1 -1
  100. package/agent/components/PieChart.json +0 -1
  101. package/agent/components/Popover.json +31 -6
  102. package/agent/components/PrefetchLink.json +1 -1
  103. package/agent/components/Progress.json +1 -1
  104. package/agent/components/Prose.json +1 -1
  105. package/agent/components/QrCode.json +1 -1
  106. package/agent/components/Radio.json +0 -1
  107. package/agent/components/RadioGroup.json +2 -2
  108. package/agent/components/RangeTimeline.json +2 -1
  109. package/agent/components/Rating.json +1 -1
  110. package/agent/components/RecordPicker.json +1 -1
  111. package/agent/components/ResizablePanel.json +1 -1
  112. package/agent/components/ResponsiveGrid.json +2 -2
  113. package/agent/components/Reveal.json +3 -3
  114. package/agent/components/ScrollArea.json +2 -2
  115. package/agent/components/SearchInput.json +1 -1
  116. package/agent/components/Segmented.json +1 -1
  117. package/agent/components/Select.json +7 -5
  118. package/agent/components/Separator.json +1 -1
  119. package/agent/components/ServiceCatalogCta.json +0 -1
  120. package/agent/components/ServiceLauncherCard.json +1 -1
  121. package/agent/components/ServiceRolePanel.json +1 -1
  122. package/agent/components/Sheet.json +5 -5
  123. package/agent/components/Sidebar.json +1 -1
  124. package/agent/components/Skeleton.json +26 -12
  125. package/agent/components/Slider.json +2 -2
  126. package/agent/components/SortableList.json +3 -2
  127. package/agent/components/SplitPane.json +1 -1
  128. package/agent/components/StatCard.json +1 -1
  129. package/agent/components/Steps.json +1 -1
  130. package/agent/components/Swatch.json +1 -1
  131. package/agent/components/Switch.json +1 -1
  132. package/agent/components/Table.json +1 -1
  133. package/agent/components/Tabs.json +3 -3
  134. package/agent/components/Text.json +5 -1
  135. package/agent/components/TextDiff.json +5 -4
  136. package/agent/components/Textarea.json +1 -1
  137. package/agent/components/ThemeScope.json +1 -1
  138. package/agent/components/ThoughtChain.json +3 -3
  139. package/agent/components/TimePicker.json +1 -1
  140. package/agent/components/Timeline.json +1 -1
  141. package/agent/components/TimelineGrid.json +5 -4
  142. package/agent/components/Toaster.json +0 -1
  143. package/agent/components/Toggle.json +3 -3
  144. package/agent/components/ToggleGroup.json +1 -1
  145. package/agent/components/Toolbar.json +10 -3
  146. package/agent/components/Tooltip.json +9 -9
  147. package/agent/components/Topbar.json +1 -1
  148. package/agent/components/TopbarItem.json +1 -1
  149. package/agent/components/Transfer.json +2 -2
  150. package/agent/components/Tree.json +1 -1
  151. package/agent/components/TreeSelect.json +1 -1
  152. package/agent/components/TwoFactorSetup.json +1 -1
  153. package/agent/components/Upload.json +1 -1
  154. package/agent/components/UploadCropDialog.json +1 -1
  155. package/agent/components/Welcome.json +3 -3
  156. package/agent/components/formatDate.json +2 -2
  157. package/agent/components/inertiaUpload.json +0 -1
  158. package/agent/components/useZodForm.json +0 -1
  159. package/agent/components-index.json +80 -154
  160. package/agent/components.json +541 -1737
  161. package/agent/index.json +10 -10
  162. package/agent/llms.txt +9 -9
  163. package/agent/patterns/account-recovery-settings.json +1 -1
  164. package/agent/patterns/auth-recovery-panels.json +2 -2
  165. package/agent/patterns/error-pages.json +1 -1
  166. package/agent/patterns/pricing-plans.json +17 -0
  167. package/agent/patterns-index.json +17 -1
  168. package/agent/patterns.json +21 -4
  169. package/agent/rules.json +30 -65
  170. package/agent/tokens.json +27 -57
  171. package/agent/vocabulary.json +3 -3
  172. package/dist/app/app-provider.d.ts +5 -3
  173. package/dist/app/app-provider.js +47 -12
  174. package/dist/app/date-format-labels.d.ts +3 -1
  175. package/dist/app/date-format-labels.js +2 -4
  176. package/dist/app/date-formats.d.ts +21 -2
  177. package/dist/app/date-formats.js +51 -2
  178. package/dist/app/index.d.ts +3 -1
  179. package/dist/app/index.js +5 -0
  180. package/dist/app/locales.d.ts +58 -3
  181. package/dist/app/locales.js +134 -8
  182. package/dist/app/preset.d.ts +25 -0
  183. package/dist/app/preset.js +10 -0
  184. package/dist/app/request-headers.d.ts +3 -3
  185. package/dist/app/request-headers.js +19 -10
  186. package/dist/app/settings-scope.d.ts +54 -0
  187. package/dist/app/settings-scope.js +46 -0
  188. package/dist/app/tenant-theme.js +8 -3
  189. package/dist/app/time-format-labels.d.ts +4 -1
  190. package/dist/app/time-format-labels.js +7 -1
  191. package/dist/app/types.d.ts +10 -2
  192. package/dist/app/use-formatting.d.ts +1 -1
  193. package/dist/components/admin/index.d.ts +1 -1
  194. package/dist/components/admin/index.js +1 -1
  195. package/dist/components/data-display/accordion.d.ts +51 -1
  196. package/dist/components/data-display/accordion.js +247 -1
  197. package/dist/components/data-display/avatar.d.ts +16 -1
  198. package/dist/components/data-display/avatar.js +109 -1
  199. package/dist/components/data-display/credential-reveal.d.ts +9 -2
  200. package/dist/components/data-display/credential-reveal.js +156 -1
  201. package/dist/components/data-display/image.js +5 -3
  202. package/dist/components/data-display/index.d.ts +0 -21
  203. package/dist/components/data-display/index.js +1 -43
  204. package/dist/components/data-display/popover.d.ts +15 -3
  205. package/dist/components/data-display/popover.js +168 -2
  206. package/dist/components/data-entry/branch-scope-picker.d.ts +1 -1
  207. package/dist/components/data-entry/index.d.ts +5 -12
  208. package/dist/components/data-entry/index.js +11 -12
  209. package/dist/components/data-entry/input-otp.d.ts +48 -2
  210. package/dist/components/data-entry/input-otp.js +94 -1
  211. package/dist/components/data-entry/number-input.d.ts +1 -1
  212. package/dist/components/data-entry/password-input.d.ts +38 -2
  213. package/dist/components/data-entry/password-input.js +56 -1
  214. package/dist/components/data-entry/rating.d.ts +38 -2
  215. package/dist/components/data-entry/rating.js +127 -1
  216. package/dist/components/data-entry/segmented.d.ts +94 -2
  217. package/dist/components/data-entry/segmented.js +104 -1
  218. package/dist/components/{ui/tag-input.d.ts → data-entry/select-tags-inline.d.ts} +7 -4
  219. package/dist/components/{ui/tag-input.js → data-entry/select-tags-inline.js} +4 -4
  220. package/dist/components/data-entry/select.js +4 -0
  221. package/dist/components/data-entry/toggle-group.d.ts +108 -2
  222. package/dist/components/data-entry/toggle-group.js +189 -1
  223. package/dist/components/data-entry/toggle.d.ts +86 -2
  224. package/dist/components/data-entry/toggle.js +153 -2
  225. package/dist/components/feedback/alert.d.ts +5 -3
  226. package/dist/components/feedback/alert.js +14 -2
  227. package/dist/components/feedback/index.d.ts +2 -6
  228. package/dist/components/feedback/index.js +1 -13
  229. package/dist/components/feedback/skeleton.d.ts +4 -17
  230. package/dist/components/feedback/skeleton.js +3 -40
  231. package/dist/components/general/index.d.ts +2 -4
  232. package/dist/components/general/index.js +1 -6
  233. package/dist/components/general/typography.d.ts +4 -58
  234. package/dist/components/general/typography.js +7 -141
  235. package/dist/components/layout/aspect-ratio.d.ts +24 -1
  236. package/dist/components/layout/aspect-ratio.js +18 -1
  237. package/dist/components/layout/auth-divider.js +1 -1
  238. package/dist/components/layout/auth-identity.js +6 -2
  239. package/dist/components/layout/centered-shell.d.ts +13 -8
  240. package/dist/components/layout/centered-shell.js +43 -1
  241. package/dist/components/layout/flex.d.ts +1 -1
  242. package/dist/components/layout/flex.js +73 -1
  243. package/dist/components/layout/index.d.ts +1 -13
  244. package/dist/components/layout/index.js +0 -12
  245. package/dist/components/layout/separator.d.ts +25 -2
  246. package/dist/components/layout/separator.js +71 -1
  247. package/dist/components/navigation/{app-setting-toggle.d.ts → app-setting-cycle.d.ts} +3 -4
  248. package/dist/components/navigation/{app-setting-toggle.js → app-setting-cycle.js} +3 -3
  249. package/dist/components/navigation/app-setting-picker.d.ts +6 -2
  250. package/dist/components/navigation/app-setting-picker.js +20 -2
  251. package/dist/components/navigation/index.d.ts +3 -11
  252. package/dist/components/navigation/index.js +1 -9
  253. package/dist/components/navigation/tabs.js +1 -1
  254. package/dist/components/ui/carousel.d.ts +1 -1
  255. package/dist/components/ui/carousel.js +1 -1
  256. package/dist/components/ui/index.d.ts +11 -5
  257. package/dist/components/ui/index.js +5 -5
  258. package/dist/contracts/measurement.json +2 -2
  259. package/dist/email/brand-mark.d.ts +3 -2
  260. package/dist/email/brand-mark.js +1 -1
  261. package/dist/email/tokens.generated.d.ts +6 -6
  262. package/dist/email/tokens.generated.js +6 -6
  263. package/dist/i18n/locale-tags.d.ts +25 -0
  264. package/dist/i18n/locale-tags.js +59 -0
  265. package/dist/i18n/translate.d.ts +20 -3
  266. package/dist/i18n/translate.js +25 -14
  267. package/dist/i18n/use-translation.d.ts +3 -3
  268. package/dist/i18n/use-translation.js +4 -2
  269. package/dist/{components/navigation → lab}/anchor.d.ts +2 -2
  270. package/dist/{components/navigation → lab}/anchor.js +5 -5
  271. package/dist/{components/data-display → lab}/carousel.js +2 -2
  272. package/dist/{components/layout → lab}/draggable-panel.d.ts +8 -8
  273. package/dist/{components/layout → lab}/draggable-panel.js +2 -2
  274. package/dist/{components/data-entry → lab}/emoji-picker.d.ts +2 -2
  275. package/dist/{components/data-entry → lab}/emoji-picker.js +6 -6
  276. package/dist/{components/general → lab}/float-button.d.ts +8 -8
  277. package/dist/{components/general → lab}/float-button.js +7 -7
  278. package/dist/lab/index.d.ts +39 -0
  279. package/dist/lab/index.js +48 -0
  280. package/dist/{components/layout → lab}/legal-document-shell.d.ts +2 -2
  281. package/dist/{components/layout → lab}/legal-document-shell.js +4 -4
  282. package/dist/{components/data-display → lab}/marquee.d.ts +5 -5
  283. package/dist/{components/data-display → lab}/marquee.js +5 -5
  284. package/dist/{components/layout → lab}/masonry.d.ts +2 -2
  285. package/dist/{components/layout → lab}/masonry.js +3 -3
  286. package/dist/{components/navigation → lab}/mega-menu.d.ts +4 -4
  287. package/dist/{components/navigation → lab}/mega-menu.js +2 -2
  288. package/dist/{components/data-display → lab}/org-chart.d.ts +2 -2
  289. package/dist/{components/data-display → lab}/org-chart.js +4 -4
  290. package/dist/{components/layout → lab}/page-cover.d.ts +2 -2
  291. package/dist/{components/layout → lab}/page-cover.js +2 -2
  292. package/dist/{components/data-display → lab}/range-timeline.d.ts +1 -1
  293. package/dist/{components/data-display → lab}/range-timeline.js +6 -6
  294. package/dist/{components/data-entry → lab}/sortable-list.d.ts +2 -2
  295. package/dist/{components/data-entry → lab}/sortable-list.js +3 -3
  296. package/dist/{components/data-display → lab}/text-diff.d.ts +3 -3
  297. package/dist/{components/data-display → lab}/text-diff.js +4 -4
  298. package/dist/{components/data-display → lab}/timeline-grid.d.ts +2 -2
  299. package/dist/{components/data-display → lab}/timeline-grid.js +1 -1
  300. package/dist/lib/control-styles.js +1 -1
  301. package/dist/lib/datetime/format.js +20 -6
  302. package/dist/lib/datetime/sync.d.ts +6 -2
  303. package/dist/lib/datetime/sync.js +14 -18
  304. package/dist/lib/platform.d.ts +1 -1
  305. package/dist/props/components/app.prop.d.ts +28 -13
  306. package/dist/props/components/data-display.prop.d.ts +19 -29
  307. package/dist/props/components/feedback.prop.d.ts +15 -44
  308. package/dist/props/components/general.prop.d.ts +2 -64
  309. package/dist/props/components/index.d.ts +9 -1
  310. package/dist/props/components/layout.prop.d.ts +41 -57
  311. package/dist/props/registry.d.ts +48 -101
  312. package/dist/props/registry.js +45 -129
  313. package/dist/props/vocabulary/index.d.ts +1 -1
  314. package/dist/props/vocabulary/interaction.prop.d.ts +3 -12
  315. package/dist/styles/alert-layout.css +0 -29
  316. package/dist/styles/data-display-layout.css +14 -22
  317. package/dist/styles/dialog-layout.css +4 -0
  318. package/dist/styles/fonts/OFL.txt +93 -0
  319. package/dist/styles/form-layout.css +4 -0
  320. package/dist/styles/index.css +0 -2
  321. package/dist/styles/layers.json +44 -179
  322. package/dist/styles/text-layout.css +0 -15
  323. package/dist/styles.css +2 -0
  324. package/dist/themes/godx.css +43 -0
  325. package/dist/themes/godx.d.ts +13 -0
  326. package/dist/themes/godx.js +12 -0
  327. package/dist/tokens/components/feedback.css +0 -6
  328. package/dist/tokens/derived.css +23 -22
  329. package/dist/tokens/foundation.css +4 -6
  330. package/docs/COMPOSITION-VS-COMPONENT.md +58 -33
  331. package/docs/CONSUMER-RULES.md +1 -1
  332. package/docs/CUSTOMER-THEMING.md +17 -53
  333. package/docs/migrations/v32.md +98 -0
  334. package/package.json +58 -19
  335. package/scripts/_agent-setup.mjs +54 -3
  336. package/scripts/brand-accent.generated.mjs +15 -2
  337. package/scripts/cli.mjs +36 -11
  338. package/scripts/codemod.mjs +522 -0
  339. package/scripts/consumer-rule.md +21 -43
  340. package/scripts/postinstall.mjs +10 -47
  341. package/scripts/prune-css.mjs +1 -1
  342. package/scripts/ui-audit.mjs +5 -2
  343. package/dist/components/data-display/chat-bubble.d.ts +0 -30
  344. package/dist/components/data-display/chat-bubble.js +0 -229
  345. package/dist/components/data-display/hover-card.d.ts +0 -1
  346. package/dist/components/data-display/hover-card.js +0 -7
  347. package/dist/components/data-display/thought-chain.d.ts +0 -42
  348. package/dist/components/data-display/thought-chain.js +0 -177
  349. package/dist/components/data-display/thumbnail.d.ts +0 -37
  350. package/dist/components/data-display/thumbnail.js +0 -20
  351. package/dist/components/data-display/welcome.d.ts +0 -26
  352. package/dist/components/data-display/welcome.js +0 -37
  353. package/dist/components/data-entry/attachments.d.ts +0 -19
  354. package/dist/components/data-entry/attachments.js +0 -366
  355. package/dist/components/data-entry/chat-composer.d.ts +0 -51
  356. package/dist/components/data-entry/chat-composer.js +0 -200
  357. package/dist/components/data-entry/chat-suggestion.d.ts +0 -28
  358. package/dist/components/data-entry/chat-suggestion.js +0 -309
  359. package/dist/components/data-entry/tag-input.d.ts +0 -2
  360. package/dist/components/data-entry/tag-input.js +0 -5
  361. package/dist/components/feedback/banner.d.ts +0 -21
  362. package/dist/components/feedback/banner.js +0 -19
  363. package/dist/components/feedback/callout.d.ts +0 -23
  364. package/dist/components/feedback/callout.js +0 -42
  365. package/dist/components/layout/auth-shell.d.ts +0 -10
  366. package/dist/components/layout/auth-shell.js +0 -42
  367. package/dist/components/layout/space-compact.d.ts +0 -65
  368. package/dist/components/layout/space-compact.js +0 -52
  369. package/dist/components/navigation/conversations.d.ts +0 -39
  370. package/dist/components/navigation/conversations.js +0 -371
  371. package/dist/components/ui/accordion.d.ts +0 -51
  372. package/dist/components/ui/accordion.js +0 -254
  373. package/dist/components/ui/aspect-ratio.d.ts +0 -24
  374. package/dist/components/ui/aspect-ratio.js +0 -21
  375. package/dist/components/ui/avatar.d.ts +0 -16
  376. package/dist/components/ui/avatar.js +0 -115
  377. package/dist/components/ui/credential-reveal.d.ts +0 -9
  378. package/dist/components/ui/credential-reveal.js +0 -160
  379. package/dist/components/ui/hover-card.d.ts +0 -47
  380. package/dist/components/ui/hover-card.js +0 -205
  381. package/dist/components/ui/input-otp.d.ts +0 -48
  382. package/dist/components/ui/input-otp.js +0 -101
  383. package/dist/components/ui/password-input.d.ts +0 -38
  384. package/dist/components/ui/password-input.js +0 -60
  385. package/dist/components/ui/rating.d.ts +0 -38
  386. package/dist/components/ui/rating.js +0 -131
  387. package/dist/components/ui/segmented.d.ts +0 -94
  388. package/dist/components/ui/segmented.js +0 -108
  389. package/dist/components/ui/separator.d.ts +0 -25
  390. package/dist/components/ui/separator.js +0 -74
  391. package/dist/components/ui/toggle-group.d.ts +0 -108
  392. package/dist/components/ui/toggle-group.js +0 -194
  393. package/dist/components/ui/toggle.d.ts +0 -86
  394. package/dist/components/ui/toggle.js +0 -156
  395. package/docs/CANONICAL-CONTRACTS.md +0 -206
  396. package/docs/COMPONENTS.md +0 -163
  397. package/docs/DATETIME.md +0 -78
  398. package/docs/DEVELOPMENT.md +0 -269
  399. package/docs/FRAME-A11Y-CI.md +0 -287
  400. package/docs/FRAME-COVERAGE-LEDGER.md +0 -123
  401. package/docs/FRAME-COVERAGE-REPORT.md +0 -228
  402. package/docs/FRAME-COVERAGE-STANDARD.md +0 -65
  403. package/docs/FRAME-COVERAGE.md +0 -29
  404. package/docs/MEASUREMENT-CONTRACT.md +0 -109
  405. package/docs/PROPS-REGISTRY.md +0 -61
  406. package/docs/PROPS-VOCABULARY.md +0 -100
  407. package/docs/REGISTRY.md +0 -70
  408. package/docs/TESTING.md +0 -107
  409. package/docs/THEME-API-COVERAGE.md +0 -538
  410. package/docs/WHAT-BELONGS-HERE.md +0 -179
  411. package/docs/asset-modules.d.ts +0 -53
  412. package/docs/assets/cover-terrain.svg +0 -6
  413. package/docs/assets/portrait-amber.svg +0 -5
  414. package/docs/assets/portrait-clay.svg +0 -5
  415. package/docs/assets/portrait-indigo.svg +0 -5
  416. package/docs/assets/portrait-iris.svg +0 -5
  417. package/docs/assets/portrait-moss.svg +0 -5
  418. package/docs/assets/portrait-plum.svg +0 -5
  419. package/docs/assets/portrait-slate.svg +0 -5
  420. package/docs/assets/service-mark-rose.svg +0 -6
  421. package/docs/assets/service-mark-teal.svg +0 -5
  422. package/docs/assets/shot-landscape.svg +0 -12
  423. package/docs/assets/shot-portrait.svg +0 -10
  424. package/docs/assets/tcgm/card-1.svg +0 -1
  425. package/docs/assets/tcgm/card-2.svg +0 -1
  426. package/docs/assets/tcgm/card-3.svg +0 -1
  427. package/docs/assets/tcgm/card-4.svg +0 -1
  428. package/docs/assets/tcgm/card-5.svg +0 -1
  429. package/docs/assets/tcgm/card-6.svg +0 -1
  430. package/docs/assets/tcgm/hero-prism.svg +0 -1
  431. package/docs/assets/tcgm/scene-1.svg +0 -1
  432. package/docs/assets/tcgm/scene-2.svg +0 -1
  433. package/docs/assets/tcgm/scene-3.svg +0 -1
  434. package/docs/assets/tcgm/scene-4.svg +0 -1
  435. package/docs/assets/tcgm/scene-5.svg +0 -1
  436. package/docs/assets/tcgm/tcgm-lockup-color.svg +0 -1
  437. package/docs/assets/tcgm/tcgm-symbol-color.svg +0 -1
  438. package/docs/charts/cjk-category-axis.tsx +0 -81
  439. package/docs/charts/compact-bar-trend.tsx +0 -327
  440. package/docs/charts/size-tiers.tsx +0 -192
  441. package/docs/data-display/accordion.tsx +0 -99
  442. package/docs/data-display/avatar.tsx +0 -502
  443. package/docs/data-display/badge.tsx +0 -335
  444. package/docs/data-display/card/examples/detail-panel.tsx +0 -106
  445. package/docs/data-display/card/examples/tab-list.tsx +0 -97
  446. package/docs/data-display/card/index.md +0 -3
  447. package/docs/data-display/card/index.tsx +0 -390
  448. package/docs/data-display/carousel.tsx +0 -160
  449. package/docs/data-display/charts.tsx +0 -278
  450. package/docs/data-display/chat-bubble.tsx +0 -397
  451. package/docs/data-display/code-block.tsx +0 -188
  452. package/docs/data-display/collapsible.tsx +0 -162
  453. package/docs/data-display/credential-reveal.tsx +0 -148
  454. package/docs/data-display/data-table/examples/antd-parity.tsx +0 -257
  455. package/docs/data-display/data-table/examples/approval-queue.tsx +0 -212
  456. package/docs/data-display/data-table/examples/grid-features.tsx +0 -158
  457. package/docs/data-display/data-table/examples/list-page.tsx +0 -175
  458. package/docs/data-display/data-table/examples/selectable-inbox.tsx +0 -113
  459. package/docs/data-display/data-table/examples/server-paged.tsx +0 -179
  460. package/docs/data-display/data-table/examples/striped-list.tsx +0 -173
  461. package/docs/data-display/data-table/index.md +0 -9
  462. package/docs/data-display/data-table/index.tsx +0 -407
  463. package/docs/data-display/descriptions.tsx +0 -263
  464. package/docs/data-display/empty-state.tsx +0 -164
  465. package/docs/data-display/feature-list.tsx +0 -159
  466. package/docs/data-display/hover-card.tsx +0 -181
  467. package/docs/data-display/image.tsx +0 -170
  468. package/docs/data-display/legend.tsx +0 -158
  469. package/docs/data-display/list-row.tsx +0 -441
  470. package/docs/data-display/markdown.tsx +0 -86
  471. package/docs/data-display/marquee.tsx +0 -254
  472. package/docs/data-display/org-chart.tsx +0 -165
  473. package/docs/data-display/permission-matrix.tsx +0 -188
  474. package/docs/data-display/popover-touch.tsx +0 -27
  475. package/docs/data-display/popover.tsx +0 -331
  476. package/docs/data-display/progress.tsx +0 -162
  477. package/docs/data-display/prose.tsx +0 -169
  478. package/docs/data-display/qr-code.tsx +0 -68
  479. package/docs/data-display/scroll-area.tsx +0 -420
  480. package/docs/data-display/service-launcher-card.tsx +0 -445
  481. package/docs/data-display/stat-card.tsx +0 -354
  482. package/docs/data-display/swatch.tsx +0 -107
  483. package/docs/data-display/table.tsx +0 -362
  484. package/docs/data-display/text-diff.tsx +0 -89
  485. package/docs/data-display/thought-chain.tsx +0 -176
  486. package/docs/data-display/thumbnail.tsx +0 -128
  487. package/docs/data-display/timeline-grid.tsx +0 -119
  488. package/docs/data-display/timeline.tsx +0 -671
  489. package/docs/data-display/touch-actions.tsx +0 -36
  490. package/docs/data-display/tree.tsx +0 -724
  491. package/docs/data-display/welcome.tsx +0 -115
  492. package/docs/data-entry/attachments.tsx +0 -160
  493. package/docs/data-entry/block-editor.tsx +0 -105
  494. package/docs/data-entry/branch-scope-picker.tsx +0 -128
  495. package/docs/data-entry/calendar.tsx +0 -226
  496. package/docs/data-entry/cascader.tsx +0 -380
  497. package/docs/data-entry/chat-composer.tsx +0 -619
  498. package/docs/data-entry/chat-suggestion.tsx +0 -301
  499. package/docs/data-entry/checkbox.tsx +0 -256
  500. package/docs/data-entry/color-picker.tsx +0 -189
  501. package/docs/data-entry/command-palette.tsx +0 -179
  502. package/docs/data-entry/command.tsx +0 -341
  503. package/docs/data-entry/country-picker-recipe.tsx +0 -175
  504. package/docs/data-entry/date-picker.tsx +0 -452
  505. package/docs/data-entry/emoji-picker.tsx +0 -35
  506. package/docs/data-entry/form/examples/employee-settings.tsx +0 -267
  507. package/docs/data-entry/form/examples/invoice-form.tsx +0 -387
  508. package/docs/data-entry/form-dynamic-fields.tsx +0 -199
  509. package/docs/data-entry/form-field/examples/a11y-contract.tsx +0 -242
  510. package/docs/data-entry/form-field/examples/create-form.tsx +0 -107
  511. package/docs/data-entry/form-field/index.md +0 -8
  512. package/docs/data-entry/form-field/index.tsx +0 -337
  513. package/docs/data-entry/form-inertia.tsx +0 -80
  514. package/docs/data-entry/form-root.tsx +0 -112
  515. package/docs/data-entry/form.tsx +0 -1498
  516. package/docs/data-entry/input-otp.tsx +0 -258
  517. package/docs/data-entry/input.tsx +0 -796
  518. package/docs/data-entry/label.tsx +0 -102
  519. package/docs/data-entry/markdown-editor.tsx +0 -69
  520. package/docs/data-entry/number-input.tsx +0 -279
  521. package/docs/data-entry/password-input.tsx +0 -102
  522. package/docs/data-entry/password-strength.tsx +0 -99
  523. package/docs/data-entry/radio-group.tsx +0 -316
  524. package/docs/data-entry/rating.tsx +0 -91
  525. package/docs/data-entry/record-picker.tsx +0 -209
  526. package/docs/data-entry/search-input.tsx +0 -121
  527. package/docs/data-entry/segmented-in-filter-row.tsx +0 -60
  528. package/docs/data-entry/segmented.tsx +0 -300
  529. package/docs/data-entry/select-async-contracts.tsx +0 -108
  530. package/docs/data-entry/select-matrix.tsx +0 -209
  531. package/docs/data-entry/select.tsx +0 -547
  532. package/docs/data-entry/slider.tsx +0 -212
  533. package/docs/data-entry/sortable-list.tsx +0 -76
  534. package/docs/data-entry/switch.tsx +0 -314
  535. package/docs/data-entry/tag-input.tsx +0 -145
  536. package/docs/data-entry/textarea.tsx +0 -249
  537. package/docs/data-entry/time-picker.tsx +0 -187
  538. package/docs/data-entry/time-range-picker.tsx +0 -55
  539. package/docs/data-entry/toggle-count.tsx +0 -348
  540. package/docs/data-entry/toggle-group.tsx +0 -438
  541. package/docs/data-entry/toggle.tsx +0 -217
  542. package/docs/data-entry/transfer.tsx +0 -115
  543. package/docs/data-entry/tree-select.tsx +0 -204
  544. package/docs/data-entry/upload-crop-dialog.tsx +0 -109
  545. package/docs/data-entry/upload.tsx +0 -310
  546. package/docs/feedback/alert-dialog.tsx +0 -270
  547. package/docs/feedback/alert.tsx +0 -248
  548. package/docs/feedback/auth-expiry.tsx +0 -104
  549. package/docs/feedback/banner.tsx +0 -183
  550. package/docs/feedback/callout.tsx +0 -220
  551. package/docs/feedback/danger-confirm.tsx +0 -91
  552. package/docs/feedback/dialog-touch.tsx +0 -24
  553. package/docs/feedback/dialog.tsx +0 -373
  554. package/docs/feedback/sheet.tsx +0 -510
  555. package/docs/feedback/skeleton.tsx +0 -168
  556. package/docs/feedback/toast.tsx +0 -135
  557. package/docs/feedback/tooltip.tsx +0 -171
  558. package/docs/feedback/two-factor-setup.tsx +0 -68
  559. package/docs/foundation/_email-specimen.ts +0 -274
  560. package/docs/foundation/_theme-editor-scope.ts +0 -222
  561. package/docs/foundation/colors.tsx +0 -207
  562. package/docs/foundation/density.tsx +0 -242
  563. package/docs/foundation/email-tokens.tsx +0 -323
  564. package/docs/foundation/radius-shadow.tsx +0 -154
  565. package/docs/foundation/spacing.tsx +0 -216
  566. package/docs/foundation/theme-editor.tsx +0 -654
  567. package/docs/foundation/typography.tsx +0 -147
  568. package/docs/general/actions.tsx +0 -175
  569. package/docs/general/activity.tsx +0 -289
  570. package/docs/general/button/examples/destructive-confirm.tsx +0 -90
  571. package/docs/general/button/examples/form-actions.tsx +0 -87
  572. package/docs/general/button/examples/toolbar.tsx +0 -160
  573. package/docs/general/button/index.md +0 -16
  574. package/docs/general/button/index.tsx +0 -236
  575. package/docs/general/float-button.tsx +0 -133
  576. package/docs/general/icon.tsx +0 -217
  577. package/docs/general/logo.tsx +0 -194
  578. package/docs/general/reveal.tsx +0 -309
  579. package/docs/general/typography.tsx +0 -542
  580. package/docs/i18n/messages/en.json +0 -1715
  581. package/docs/i18n/messages/ja.json +0 -1708
  582. package/docs/i18n/messages/vi.json +0 -1708
  583. package/docs/layout/account-chip.tsx +0 -72
  584. package/docs/layout/admin-collection.tsx +0 -122
  585. package/docs/layout/affix.tsx +0 -209
  586. package/docs/layout/app-launcher.tsx +0 -211
  587. package/docs/layout/app-shell-arrangements.tsx +0 -225
  588. package/docs/layout/app-shell-narrow-bar.tsx +0 -205
  589. package/docs/layout/app-shell-states.tsx +0 -171
  590. package/docs/layout/app-shell.tsx +0 -395
  591. package/docs/layout/aspect-ratio.tsx +0 -135
  592. package/docs/layout/auth-account-summary.tsx +0 -103
  593. package/docs/layout/auth-divider.tsx +0 -28
  594. package/docs/layout/auth-footer.tsx +0 -37
  595. package/docs/layout/auth-identity.tsx +0 -70
  596. package/docs/layout/auth-recovery/examples/mfa-challenge.md +0 -41
  597. package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +0 -254
  598. package/docs/layout/auth-recovery/examples/mobile-390.md +0 -25
  599. package/docs/layout/auth-recovery/examples/mobile-390.tsx +0 -82
  600. package/docs/layout/auth-recovery/examples/password-recovery.md +0 -24
  601. package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -197
  602. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +0 -27
  603. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +0 -156
  604. package/docs/layout/auth-recovery/index.md +0 -140
  605. package/docs/layout/auth-recovery/index.tsx +0 -96
  606. package/docs/layout/auth-shell-context.tsx +0 -103
  607. package/docs/layout/auth-shell-device.tsx +0 -112
  608. package/docs/layout/auth-shell-registration.tsx +0 -338
  609. package/docs/layout/auth-shell-variants.tsx +0 -143
  610. package/docs/layout/auth-shell.tsx +0 -59
  611. package/docs/layout/auth-stack.tsx +0 -40
  612. package/docs/layout/centered-shell.tsx +0 -102
  613. package/docs/layout/draggable-panel.tsx +0 -127
  614. package/docs/layout/error-surface/examples/application-403.tsx +0 -84
  615. package/docs/layout/error-surface/examples/application-404.tsx +0 -77
  616. package/docs/layout/error-surface/examples/system-500.tsx +0 -47
  617. package/docs/layout/error-surface/examples/system-503.tsx +0 -48
  618. package/docs/layout/error-surface/index.md +0 -153
  619. package/docs/layout/error-surface/index.tsx +0 -239
  620. package/docs/layout/flex.tsx +0 -444
  621. package/docs/layout/legal-document-shell/_data.ts +0 -110
  622. package/docs/layout/legal-document-shell/examples/desktop-1440.md +0 -12
  623. package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +0 -83
  624. package/docs/layout/legal-document-shell/examples/mobile-390.md +0 -22
  625. package/docs/layout/legal-document-shell/examples/mobile-390.tsx +0 -70
  626. package/docs/layout/legal-document-shell/examples/tablet-1024.md +0 -3
  627. package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +0 -84
  628. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +0 -18
  629. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +0 -61
  630. package/docs/layout/legal-document-shell/index.md +0 -51
  631. package/docs/layout/legal-document-shell/index.tsx +0 -101
  632. package/docs/layout/masonry.tsx +0 -291
  633. package/docs/layout/master-detail.tsx +0 -390
  634. package/docs/layout/mobile-shell.tsx +0 -106
  635. package/docs/layout/nav-list.tsx +0 -584
  636. package/docs/layout/org-switcher.tsx +0 -131
  637. package/docs/layout/page-container.tsx +0 -1020
  638. package/docs/layout/page-cover.tsx +0 -56
  639. package/docs/layout/resizable-panel.tsx +0 -419
  640. package/docs/layout/responsive-grid.tsx +0 -403
  641. package/docs/layout/separator.tsx +0 -327
  642. package/docs/layout/service-role-panel.tsx +0 -144
  643. package/docs/layout/sidebar.tsx +0 -689
  644. package/docs/layout/space-compact.tsx +0 -202
  645. package/docs/layout/split-pane.tsx +0 -532
  646. package/docs/layout/topbar-item.tsx +0 -233
  647. package/docs/layout/topbar.tsx +0 -360
  648. package/docs/navigation/anchor.tsx +0 -295
  649. package/docs/navigation/app-setting-picker.tsx +0 -178
  650. package/docs/navigation/app-setting-toggle.tsx +0 -111
  651. package/docs/navigation/breadcrumb.tsx +0 -207
  652. package/docs/navigation/card-tabs.tsx +0 -344
  653. package/docs/navigation/conversations.tsx +0 -176
  654. package/docs/navigation/dropdown-menu.tsx +0 -345
  655. package/docs/navigation/filter-bar.tsx +0 -247
  656. package/docs/navigation/mega-menu-panel.tsx +0 -86
  657. package/docs/navigation/mega-menu.tsx +0 -254
  658. package/docs/navigation/pagination.tsx +0 -293
  659. package/docs/navigation/steps.tsx +0 -315
  660. package/docs/navigation/tabs-rtl.tsx +0 -28
  661. package/docs/navigation/tabs.tsx +0 -755
  662. package/docs/navigation/toolbar.tsx +0 -347
  663. package/docs/providers/app-provider.tsx +0 -191
  664. package/docs/providers/format-date.tsx +0 -230
  665. package/docs/providers/theme-scope.tsx +0 -186
  666. package/docs/query/button-refetch.tsx +0 -161
  667. package/docs/query/data-state.tsx +0 -262
  668. package/docs/query/infinite-query-state.tsx +0 -97
  669. package/docs/query/mutation-feedback.tsx +0 -128
  670. package/docs/query/touch-actions.tsx +0 -68
  671. package/docs/react-router/prefetch-link.tsx +0 -262
  672. package/docs/roadmap/ai-chat-components.md +0 -206
  673. package/docs/roadmap/antd-parity.md +0 -155
  674. package/docs/roadmap/badge-tag-chip-count.md +0 -172
  675. package/docs/roadmap/list-masonry.md +0 -159
  676. package/docs/roadmap/parity-audit-data-display-feedback.md +0 -567
  677. package/docs/roadmap/parity-audit-data-entry.md +0 -368
  678. package/docs/roadmap/parity-audit-layout-navigation-general.md +0 -459
  679. package/docs/roadmap/parity-backlog.md +0 -77
  680. package/docs/roadmap/tree-components.md +0 -151
  681. package/docs/roadmap/website-components.md +0 -813
  682. package/docs/showcase/acme-portal.tsx +0 -461
  683. package/docs/showcase/acme-website.tsx +0 -499
  684. package/docs/showcase/caimono-price-comparison.tsx +0 -919
  685. package/docs/showcase/case1-warehouse-dashboard.tsx +0 -358
  686. package/docs/showcase/case2-employee-me.tsx +0 -438
  687. package/docs/showcase/case3-approval-workflow.tsx +0 -531
  688. package/docs/showcase/case4-login.tsx +0 -312
  689. package/docs/showcase/case5-shift-calendar.tsx +0 -702
  690. package/docs/showcase/case6-agency-handy.tsx +0 -1120
  691. package/docs/showcase/futurelastic-web.tsx +0 -441
  692. package/docs/showcase/marketing-page.tsx +0 -895
  693. package/docs/showcase/org-switcher.tsx +0 -320
  694. package/docs/showcase/permission-matrix.tsx +0 -354
  695. package/docs/showcase/public-landing.tsx +0 -210
  696. package/docs/showcase/settings-account-sections.tsx +0 -559
  697. package/docs/showcase/settings-security-mfa.tsx +0 -145
  698. package/docs/showcase/table-approval-queue.tsx +0 -199
  699. package/docs/showcase/table-bulk-actions.tsx +0 -468
  700. package/docs/showcase/table-compact-kintone.tsx +0 -438
  701. package/docs/showcase/table-conditional-format.tsx +0 -367
  702. package/docs/showcase/table-crud-list.tsx +0 -544
  703. package/docs/showcase/table-density.tsx +0 -349
  704. package/docs/showcase/table-expandable-rows.tsx +0 -496
  705. package/docs/showcase/table-filter-chips.tsx +0 -468
  706. package/docs/showcase/table-footer-totals.tsx +0 -328
  707. package/docs/showcase/table-grouped-subtotals.tsx +0 -398
  708. package/docs/showcase/table-master-detail.tsx +0 -482
  709. package/docs/showcase/table-pagination.tsx +0 -409
  710. package/docs/showcase/table-states.tsx +0 -371
  711. package/docs/showcase/table-sticky-columns.tsx +0 -377
  712. package/docs/showcase/table-tree-rows.tsx +0 -451
  713. package/docs/showcase/table-view-tabs.tsx +0 -488
  714. package/docs/showcase/tcgm-website.tsx +0 -1047
  715. package/docs/showcase/tenant-brand-color.tsx +0 -338
  716. package/docs/showcase/theme-customization.tsx +0 -1292
  717. package/docs/showcase/theme-lab.tsx +0 -2125
  718. package/docs/themes/flat.css +0 -466
  719. package/docs/themes/glassmorphism.css +0 -960
  720. package/docs/themes/index.ts +0 -219
  721. package/docs/themes/neubrutalism.css +0 -481
  722. /package/dist/components/navigation/{filter-bar.d.ts → toolbar.d.ts} +0 -0
  723. /package/dist/components/navigation/{filter-bar.js → toolbar.js} +0 -0
  724. /package/dist/{components/data-display → lab}/carousel.d.ts +0 -0
  725. /package/dist/{components/data-entry → lab}/emoji-data.d.ts +0 -0
  726. /package/dist/{components/data-entry → lab}/emoji-data.js +0 -0
  727. /package/dist/{components/data-display → lab}/marquee-reveal.d.ts +0 -0
  728. /package/dist/{components/data-display → lab}/marquee-reveal.js +0 -0
@@ -1,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
- }