@open-mercato/core 0.7.1-develop.7202.1.a52dc6707c → 0.8.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 (416) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/build.mjs +11 -0
  3. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +23 -0
  4. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  5. package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
  6. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  7. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +2 -1
  8. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  9. package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -2
  10. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  11. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +2 -1
  12. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  13. package/dist/modules/customers/lib/detailHelpers.js +4 -0
  14. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  15. package/dist/modules/customers/lib/todoCompatibility.js +5 -0
  16. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  17. package/dist/modules/design_system/backend/design-system/page.meta.js +3 -2
  18. package/dist/modules/design_system/backend/design-system/page.meta.js.map +2 -2
  19. package/dist/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  20. package/dist/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  21. package/dist/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  22. package/dist/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  23. package/dist/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  24. package/dist/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  25. package/dist/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  26. package/dist/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  27. package/dist/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  28. package/dist/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  29. package/dist/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  30. package/dist/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  31. package/dist/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  32. package/dist/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  33. package/dist/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  34. package/dist/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  35. package/dist/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  36. package/dist/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  37. package/dist/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  38. package/dist/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  39. package/dist/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  40. package/dist/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  41. package/dist/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  42. package/dist/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  43. package/dist/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  44. package/dist/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  45. package/dist/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  46. package/dist/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  47. package/dist/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  48. package/dist/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  49. package/dist/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  50. package/dist/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  51. package/dist/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  52. package/dist/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  53. package/dist/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  54. package/dist/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  55. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js +67 -0
  56. package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js.map +7 -0
  57. package/dist/modules/design_system/gallery/assets/github-logo.png +0 -0
  58. package/dist/modules/design_system/gallery/assets/images.d.js +1 -0
  59. package/dist/modules/design_system/gallery/assets/images.d.js.map +7 -0
  60. package/dist/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  61. package/dist/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  62. package/dist/modules/design_system/gallery/assets/marketing-artwork.js +83 -0
  63. package/dist/modules/design_system/gallery/assets/marketing-artwork.js.map +7 -0
  64. package/dist/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  65. package/dist/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  66. package/dist/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  67. package/dist/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  68. package/dist/modules/design_system/gallery/assets/select-google.png +0 -0
  69. package/dist/modules/design_system/gallery/assets/select-poland.png +0 -0
  70. package/dist/modules/design_system/gallery/assets/selection-artwork.js +5 -0
  71. package/dist/modules/design_system/gallery/assets/selection-artwork.js.map +7 -0
  72. package/dist/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  73. package/dist/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  74. package/dist/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  75. package/dist/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  76. package/dist/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  77. package/dist/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  78. package/dist/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  79. package/dist/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  80. package/dist/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  81. package/dist/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  82. package/dist/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  83. package/dist/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  84. package/dist/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  85. package/dist/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  86. package/dist/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  87. package/dist/modules/design_system/gallery/assets/upload-images.js +8 -0
  88. package/dist/modules/design_system/gallery/assets/upload-images.js.map +7 -0
  89. package/dist/modules/design_system/gallery/components/BrandStylePreview.js +74 -0
  90. package/dist/modules/design_system/gallery/components/BrandStylePreview.js.map +7 -0
  91. package/dist/modules/design_system/gallery/components/CodeSnippet.js +31 -31
  92. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +2 -2
  93. package/dist/modules/design_system/gallery/components/ColorPlayground.js +408 -0
  94. package/dist/modules/design_system/gallery/components/ColorPlayground.js.map +7 -0
  95. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js +166 -0
  96. package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js.map +7 -0
  97. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js +182 -0
  98. package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js.map +7 -0
  99. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js +80 -0
  100. package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js.map +7 -0
  101. package/dist/modules/design_system/gallery/components/ComponentIndex.js +42 -0
  102. package/dist/modules/design_system/gallery/components/ComponentIndex.js.map +7 -0
  103. package/dist/modules/design_system/gallery/components/DesignSystemHome.js +69 -0
  104. package/dist/modules/design_system/gallery/components/DesignSystemHome.js.map +7 -0
  105. package/dist/modules/design_system/gallery/components/EntryCard.js +47 -41
  106. package/dist/modules/design_system/gallery/components/EntryCard.js.map +2 -2
  107. package/dist/modules/design_system/gallery/components/EntryHeader.js +68 -0
  108. package/dist/modules/design_system/gallery/components/EntryHeader.js.map +7 -0
  109. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js +19 -0
  110. package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js.map +7 -0
  111. package/dist/modules/design_system/gallery/components/FoundationGuide.js +46 -0
  112. package/dist/modules/design_system/gallery/components/FoundationGuide.js.map +7 -0
  113. package/dist/modules/design_system/gallery/components/GalleryLink.js +21 -0
  114. package/dist/modules/design_system/gallery/components/GalleryLink.js.map +7 -0
  115. package/dist/modules/design_system/gallery/components/GalleryNavigation.js +82 -0
  116. package/dist/modules/design_system/gallery/components/GalleryNavigation.js.map +7 -0
  117. package/dist/modules/design_system/gallery/components/GalleryShell.js +147 -67
  118. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +3 -3
  119. package/dist/modules/design_system/gallery/components/IconsBrowser.js +33 -0
  120. package/dist/modules/design_system/gallery/components/IconsBrowser.js.map +7 -0
  121. package/dist/modules/design_system/gallery/components/SourceLibrary.js +93 -0
  122. package/dist/modules/design_system/gallery/components/SourceLibrary.js.map +7 -0
  123. package/dist/modules/design_system/gallery/components/StyleAgents.js +139 -0
  124. package/dist/modules/design_system/gallery/components/StyleAgents.js.map +7 -0
  125. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js +101 -0
  126. package/dist/modules/design_system/gallery/components/ThemeTokenReference.js.map +7 -0
  127. package/dist/modules/design_system/gallery/components/VariantPreview.js +2 -2
  128. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +2 -2
  129. package/dist/modules/design_system/gallery/components/colorPreview.js +58 -0
  130. package/dist/modules/design_system/gallery/components/colorPreview.js.map +7 -0
  131. package/dist/modules/design_system/gallery/components/colorStudio.js +218 -0
  132. package/dist/modules/design_system/gallery/components/colorStudio.js.map +7 -0
  133. package/dist/modules/design_system/gallery/components/styleAgentBranding.js +46 -0
  134. package/dist/modules/design_system/gallery/components/styleAgentBranding.js.map +7 -0
  135. package/dist/modules/design_system/gallery/components/themeTokens.js +32 -0
  136. package/dist/modules/design_system/gallery/components/themeTokens.js.map +7 -0
  137. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js +194 -0
  138. package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js.map +7 -0
  139. package/dist/modules/design_system/gallery/demos/ai-product.js +423 -0
  140. package/dist/modules/design_system/gallery/demos/ai-product.js.map +7 -0
  141. package/dist/modules/design_system/gallery/demos/buttons.js +289 -0
  142. package/dist/modules/design_system/gallery/demos/buttons.js.map +7 -0
  143. package/dist/modules/design_system/gallery/demos/cryptocurrency.js +1708 -0
  144. package/dist/modules/design_system/gallery/demos/cryptocurrency.js.map +7 -0
  145. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js +92 -0
  146. package/dist/modules/design_system/gallery/demos/feeds-code.generated.js.map +7 -0
  147. package/dist/modules/design_system/gallery/demos/feeds.js +148 -0
  148. package/dist/modules/design_system/gallery/demos/feeds.js.map +7 -0
  149. package/dist/modules/design_system/gallery/demos/file-upload.js +72 -0
  150. package/dist/modules/design_system/gallery/demos/file-upload.js.map +7 -0
  151. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js +4875 -0
  152. package/dist/modules/design_system/gallery/demos/foundation-reference-data.js.map +7 -0
  153. package/dist/modules/design_system/gallery/demos/foundation-references.js +188 -0
  154. package/dist/modules/design_system/gallery/demos/foundation-references.js.map +7 -0
  155. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js +6 -0
  156. package/dist/modules/design_system/gallery/demos/key-components-code.generated.js.map +7 -0
  157. package/dist/modules/design_system/gallery/demos/key-components.js +127 -0
  158. package/dist/modules/design_system/gallery/demos/key-components.js.map +7 -0
  159. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js +98 -0
  160. package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js.map +7 -0
  161. package/dist/modules/design_system/gallery/demos/marketing-controls.js +134 -0
  162. package/dist/modules/design_system/gallery/demos/marketing-controls.js.map +7 -0
  163. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js +195 -0
  164. package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js.map +7 -0
  165. package/dist/modules/design_system/gallery/demos/marketing-widgets.js +586 -0
  166. package/dist/modules/design_system/gallery/demos/marketing-widgets.js.map +7 -0
  167. package/dist/modules/design_system/gallery/demos/menu-fixtures.js +40 -0
  168. package/dist/modules/design_system/gallery/demos/menu-fixtures.js.map +7 -0
  169. package/dist/modules/design_system/gallery/demos/menu-sources.js +295 -0
  170. package/dist/modules/design_system/gallery/demos/menu-sources.js.map +7 -0
  171. package/dist/modules/design_system/gallery/demos/menus.js +150 -0
  172. package/dist/modules/design_system/gallery/demos/menus.js.map +7 -0
  173. package/dist/modules/design_system/gallery/demos/rating-reviews.js +53 -0
  174. package/dist/modules/design_system/gallery/demos/rating-reviews.js.map +7 -0
  175. package/dist/modules/design_system/gallery/demos/registered-icons.js +104 -0
  176. package/dist/modules/design_system/gallery/demos/registered-icons.js.map +7 -0
  177. package/dist/modules/design_system/gallery/demos/selection-cards.js +99 -0
  178. package/dist/modules/design_system/gallery/demos/selection-cards.js.map +7 -0
  179. package/dist/modules/design_system/gallery/demos/shell-code.generated.js +189 -0
  180. package/dist/modules/design_system/gallery/demos/shell-code.generated.js.map +7 -0
  181. package/dist/modules/design_system/gallery/demos/shell.js +330 -0
  182. package/dist/modules/design_system/gallery/demos/shell.js.map +7 -0
  183. package/dist/modules/design_system/gallery/demos/source-artwork.js +120 -0
  184. package/dist/modules/design_system/gallery/demos/source-artwork.js.map +7 -0
  185. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js +125 -0
  186. package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js.map +7 -0
  187. package/dist/modules/design_system/gallery/demos/source-filters.js +185 -0
  188. package/dist/modules/design_system/gallery/demos/source-filters.js.map +7 -0
  189. package/dist/modules/design_system/gallery/demos/source-icons.js +69 -0
  190. package/dist/modules/design_system/gallery/demos/source-icons.js.map +7 -0
  191. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js +150 -0
  192. package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js.map +7 -0
  193. package/dist/modules/design_system/gallery/demos/table-cells.js +181 -0
  194. package/dist/modules/design_system/gallery/demos/table-cells.js.map +7 -0
  195. package/dist/modules/design_system/gallery/demos/text-inputs.js +113 -0
  196. package/dist/modules/design_system/gallery/demos/text-inputs.js.map +7 -0
  197. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js +41 -0
  198. package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js.map +7 -0
  199. package/dist/modules/design_system/gallery/demos/time-picker.js +41 -0
  200. package/dist/modules/design_system/gallery/demos/time-picker.js.map +7 -0
  201. package/dist/modules/design_system/gallery/entries/banners.js +123 -60
  202. package/dist/modules/design_system/gallery/entries/banners.js.map +2 -2
  203. package/dist/modules/design_system/gallery/entries/buttons-snippets.js +433 -0
  204. package/dist/modules/design_system/gallery/entries/buttons-snippets.js.map +7 -0
  205. package/dist/modules/design_system/gallery/entries/buttons.js +127 -148
  206. package/dist/modules/design_system/gallery/entries/buttons.js.map +2 -2
  207. package/dist/modules/design_system/gallery/entries/charts.js +532 -186
  208. package/dist/modules/design_system/gallery/entries/charts.js.map +2 -2
  209. package/dist/modules/design_system/gallery/entries/dates.js +191 -3
  210. package/dist/modules/design_system/gallery/entries/dates.js.map +2 -2
  211. package/dist/modules/design_system/gallery/entries/detail.js +118 -77
  212. package/dist/modules/design_system/gallery/entries/detail.js.map +2 -2
  213. package/dist/modules/design_system/gallery/entries/display.js +1449 -240
  214. package/dist/modules/design_system/gallery/entries/display.js.map +2 -2
  215. package/dist/modules/design_system/gallery/entries/feedback.js +1058 -132
  216. package/dist/modules/design_system/gallery/entries/feedback.js.map +2 -2
  217. package/dist/modules/design_system/gallery/entries/filters.js +231 -103
  218. package/dist/modules/design_system/gallery/entries/filters.js.map +2 -2
  219. package/dist/modules/design_system/gallery/entries/foundations.js +368 -57
  220. package/dist/modules/design_system/gallery/entries/foundations.js.map +2 -2
  221. package/dist/modules/design_system/gallery/entries/icons.js +29 -91
  222. package/dist/modules/design_system/gallery/entries/icons.js.map +2 -2
  223. package/dist/modules/design_system/gallery/entries/inputs-snippets.js +154 -0
  224. package/dist/modules/design_system/gallery/entries/inputs-snippets.js.map +7 -0
  225. package/dist/modules/design_system/gallery/entries/inputs.js +2043 -306
  226. package/dist/modules/design_system/gallery/entries/inputs.js.map +2 -2
  227. package/dist/modules/design_system/gallery/entries/library.js +20 -0
  228. package/dist/modules/design_system/gallery/entries/library.js.map +7 -0
  229. package/dist/modules/design_system/gallery/entries/messages.js +121 -103
  230. package/dist/modules/design_system/gallery/entries/messages.js.map +2 -2
  231. package/dist/modules/design_system/gallery/entries/navigation.js +676 -103
  232. package/dist/modules/design_system/gallery/entries/navigation.js.map +2 -2
  233. package/dist/modules/design_system/gallery/entries/notifications.js +131 -78
  234. package/dist/modules/design_system/gallery/entries/notifications.js.map +2 -2
  235. package/dist/modules/design_system/gallery/entries/overlays.js +611 -203
  236. package/dist/modules/design_system/gallery/entries/overlays.js.map +2 -2
  237. package/dist/modules/design_system/gallery/entries/scaffolding.js +1175 -120
  238. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +2 -2
  239. package/dist/modules/design_system/gallery/entries/schedule.js +79 -54
  240. package/dist/modules/design_system/gallery/entries/schedule.js.map +2 -2
  241. package/dist/modules/design_system/gallery/presentation.js +108 -0
  242. package/dist/modules/design_system/gallery/presentation.js.map +7 -0
  243. package/dist/modules/design_system/gallery/registry.js +8 -5
  244. package/dist/modules/design_system/gallery/registry.js.map +2 -2
  245. package/dist/modules/design_system/gallery/source-library.generated.js +5 -0
  246. package/dist/modules/design_system/gallery/source-library.generated.js.map +7 -0
  247. package/dist/modules/design_system/i18n/de.json +7167 -0
  248. package/dist/modules/design_system/i18n/en.json +7167 -0
  249. package/dist/modules/design_system/i18n/es.json +7167 -0
  250. package/dist/modules/design_system/i18n/ko.json +7167 -0
  251. package/dist/modules/design_system/i18n/pl.json +7167 -0
  252. package/dist/modules/push_notifications/lib/queue.js +1 -31
  253. package/dist/modules/push_notifications/lib/queue.js.map +2 -2
  254. package/jest.config.cjs +1 -0
  255. package/jest.mocks/image.js +1 -0
  256. package/package.json +8 -9
  257. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +50 -0
  258. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
  259. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +2 -1
  260. package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -2
  261. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +2 -1
  262. package/src/modules/customers/lib/detailHelpers.ts +4 -0
  263. package/src/modules/customers/lib/todoCompatibility.ts +10 -0
  264. package/src/modules/design_system/backend/design-system/page.meta.ts +3 -2
  265. package/src/modules/design_system/gallery/assets/README.md +30 -0
  266. package/src/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
  267. package/src/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
  268. package/src/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
  269. package/src/modules/design_system/gallery/assets/avatar-photo.png +0 -0
  270. package/src/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
  271. package/src/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
  272. package/src/modules/design_system/gallery/assets/crypto-ada.png +0 -0
  273. package/src/modules/design_system/gallery/assets/crypto-avax.png +0 -0
  274. package/src/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
  275. package/src/modules/design_system/gallery/assets/crypto-brand.png +0 -0
  276. package/src/modules/design_system/gallery/assets/crypto-btc.png +0 -0
  277. package/src/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
  278. package/src/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
  279. package/src/modules/design_system/gallery/assets/crypto-dot.png +0 -0
  280. package/src/modules/design_system/gallery/assets/crypto-eth.png +0 -0
  281. package/src/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
  282. package/src/modules/design_system/gallery/assets/crypto-history.svg +3 -0
  283. package/src/modules/design_system/gallery/assets/crypto-link.svg +3 -0
  284. package/src/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
  285. package/src/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
  286. package/src/modules/design_system/gallery/assets/crypto-more.svg +3 -0
  287. package/src/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
  288. package/src/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
  289. package/src/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
  290. package/src/modules/design_system/gallery/assets/crypto-sol.png +0 -0
  291. package/src/modules/design_system/gallery/assets/crypto-star.svg +3 -0
  292. package/src/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
  293. package/src/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
  294. package/src/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
  295. package/src/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
  296. package/src/modules/design_system/gallery/assets/crypto-trx.png +0 -0
  297. package/src/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
  298. package/src/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
  299. package/src/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
  300. package/src/modules/design_system/gallery/assets/crypto-wei.png +0 -0
  301. package/src/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
  302. package/src/modules/design_system/gallery/assets/cryptocurrency-artwork.ts +63 -0
  303. package/src/modules/design_system/gallery/assets/github-logo.png +0 -0
  304. package/src/modules/design_system/gallery/assets/images.d.ts +9 -0
  305. package/src/modules/design_system/gallery/assets/input-european-union.svg +18 -0
  306. package/src/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
  307. package/src/modules/design_system/gallery/assets/marketing-artwork.ts +79 -0
  308. package/src/modules/design_system/gallery/assets/menu-apex.svg +18 -0
  309. package/src/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
  310. package/src/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
  311. package/src/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
  312. package/src/modules/design_system/gallery/assets/select-google.png +0 -0
  313. package/src/modules/design_system/gallery/assets/select-poland.png +0 -0
  314. package/src/modules/design_system/gallery/assets/selection-artwork.ts +1 -0
  315. package/src/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
  316. package/src/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
  317. package/src/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
  318. package/src/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
  319. package/src/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
  320. package/src/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
  321. package/src/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
  322. package/src/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
  323. package/src/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
  324. package/src/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
  325. package/src/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
  326. package/src/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
  327. package/src/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
  328. package/src/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
  329. package/src/modules/design_system/gallery/assets/style-studio-product.png +0 -0
  330. package/src/modules/design_system/gallery/assets/upload-images.ts +5 -0
  331. package/src/modules/design_system/gallery/components/BrandStylePreview.tsx +94 -0
  332. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +34 -34
  333. package/src/modules/design_system/gallery/components/ColorPlayground.tsx +324 -0
  334. package/src/modules/design_system/gallery/components/ColorStudioCompositions.tsx +96 -0
  335. package/src/modules/design_system/gallery/components/ColorStudioSpecimen.tsx +164 -0
  336. package/src/modules/design_system/gallery/components/CompactEntrySpecimen.tsx +65 -0
  337. package/src/modules/design_system/gallery/components/ComponentIndex.tsx +47 -0
  338. package/src/modules/design_system/gallery/components/DesignSystemHome.tsx +66 -0
  339. package/src/modules/design_system/gallery/components/EntryCard.tsx +52 -37
  340. package/src/modules/design_system/gallery/components/EntryHeader.tsx +80 -0
  341. package/src/modules/design_system/gallery/components/FamilyEntryPreview.tsx +22 -0
  342. package/src/modules/design_system/gallery/components/FoundationGuide.tsx +43 -0
  343. package/src/modules/design_system/gallery/components/GalleryLink.tsx +19 -0
  344. package/src/modules/design_system/gallery/components/GalleryNavigation.tsx +86 -0
  345. package/src/modules/design_system/gallery/components/GalleryShell.tsx +149 -63
  346. package/src/modules/design_system/gallery/components/IconsBrowser.tsx +40 -0
  347. package/src/modules/design_system/gallery/components/SourceLibrary.tsx +90 -0
  348. package/src/modules/design_system/gallery/components/StyleAgents.tsx +115 -0
  349. package/src/modules/design_system/gallery/components/ThemeTokenReference.tsx +76 -0
  350. package/src/modules/design_system/gallery/components/VariantPreview.tsx +2 -2
  351. package/src/modules/design_system/gallery/components/colorPreview.ts +63 -0
  352. package/src/modules/design_system/gallery/components/colorStudio.ts +260 -0
  353. package/src/modules/design_system/gallery/components/styleAgentBranding.ts +42 -0
  354. package/src/modules/design_system/gallery/components/themeTokens.ts +26 -0
  355. package/src/modules/design_system/gallery/demos/ai-product-code.generated.ts +3 -0
  356. package/src/modules/design_system/gallery/demos/ai-product.tsx +188 -0
  357. package/src/modules/design_system/gallery/demos/buttons.tsx +331 -0
  358. package/src/modules/design_system/gallery/demos/cryptocurrency.tsx +1943 -0
  359. package/src/modules/design_system/gallery/demos/feeds-code.generated.ts +4 -0
  360. package/src/modules/design_system/gallery/demos/feeds.tsx +82 -0
  361. package/src/modules/design_system/gallery/demos/file-upload.tsx +61 -0
  362. package/src/modules/design_system/gallery/demos/foundation-reference-data.ts +4872 -0
  363. package/src/modules/design_system/gallery/demos/foundation-references.tsx +140 -0
  364. package/src/modules/design_system/gallery/demos/key-components-code.generated.ts +3 -0
  365. package/src/modules/design_system/gallery/demos/key-components.tsx +106 -0
  366. package/src/modules/design_system/gallery/demos/marketing-controls-code.generated.ts +3 -0
  367. package/src/modules/design_system/gallery/demos/marketing-controls.tsx +92 -0
  368. package/src/modules/design_system/gallery/demos/marketing-widgets-code.generated.ts +3 -0
  369. package/src/modules/design_system/gallery/demos/marketing-widgets.tsx +189 -0
  370. package/src/modules/design_system/gallery/demos/menu-fixtures.tsx +48 -0
  371. package/src/modules/design_system/gallery/demos/menu-sources.ts +5 -0
  372. package/src/modules/design_system/gallery/demos/menus.tsx +122 -0
  373. package/src/modules/design_system/gallery/demos/rating-reviews.tsx +44 -0
  374. package/src/modules/design_system/gallery/demos/registered-icons.tsx +117 -0
  375. package/src/modules/design_system/gallery/demos/selection-cards.tsx +97 -0
  376. package/src/modules/design_system/gallery/demos/shell-code.generated.ts +3 -0
  377. package/src/modules/design_system/gallery/demos/shell.tsx +183 -0
  378. package/src/modules/design_system/gallery/demos/source-artwork.tsx +88 -0
  379. package/src/modules/design_system/gallery/demos/source-filters-code.generated.ts +3 -0
  380. package/src/modules/design_system/gallery/demos/source-filters.tsx +119 -0
  381. package/src/modules/design_system/gallery/demos/source-icons.tsx +62 -0
  382. package/src/modules/design_system/gallery/demos/table-cells-code.generated.ts +3 -0
  383. package/src/modules/design_system/gallery/demos/table-cells.tsx +144 -0
  384. package/src/modules/design_system/gallery/demos/text-inputs.tsx +90 -0
  385. package/src/modules/design_system/gallery/demos/time-picker-code.generated.ts +5 -0
  386. package/src/modules/design_system/gallery/demos/time-picker.tsx +31 -0
  387. package/src/modules/design_system/gallery/entries/banners.tsx +143 -94
  388. package/src/modules/design_system/gallery/entries/buttons-snippets.ts +432 -0
  389. package/src/modules/design_system/gallery/entries/buttons.tsx +125 -196
  390. package/src/modules/design_system/gallery/entries/charts.tsx +545 -233
  391. package/src/modules/design_system/gallery/entries/dates.tsx +171 -3
  392. package/src/modules/design_system/gallery/entries/detail.tsx +142 -115
  393. package/src/modules/design_system/gallery/entries/display.tsx +1691 -319
  394. package/src/modules/design_system/gallery/entries/feedback.tsx +1082 -169
  395. package/src/modules/design_system/gallery/entries/filters.tsx +238 -143
  396. package/src/modules/design_system/gallery/entries/foundations.tsx +404 -61
  397. package/src/modules/design_system/gallery/entries/icons.tsx +31 -117
  398. package/src/modules/design_system/gallery/entries/inputs-snippets.ts +156 -0
  399. package/src/modules/design_system/gallery/entries/inputs.tsx +2146 -503
  400. package/src/modules/design_system/gallery/entries/library.tsx +16 -0
  401. package/src/modules/design_system/gallery/entries/messages.tsx +114 -106
  402. package/src/modules/design_system/gallery/entries/navigation.tsx +782 -192
  403. package/src/modules/design_system/gallery/entries/notifications.tsx +145 -120
  404. package/src/modules/design_system/gallery/entries/overlays.tsx +696 -280
  405. package/src/modules/design_system/gallery/entries/scaffolding.tsx +1192 -158
  406. package/src/modules/design_system/gallery/entries/schedule.tsx +72 -58
  407. package/src/modules/design_system/gallery/presentation.ts +106 -0
  408. package/src/modules/design_system/gallery/registry.ts +8 -6
  409. package/src/modules/design_system/gallery/source-library.generated.ts +2 -0
  410. package/src/modules/design_system/i18n/de.json +7112 -3
  411. package/src/modules/design_system/i18n/en.json +7112 -3
  412. package/src/modules/design_system/i18n/es.json +7112 -3
  413. package/src/modules/design_system/i18n/ko.json +7112 -3
  414. package/src/modules/design_system/i18n/pl.json +7112 -3
  415. package/src/modules/push_notifications/AGENTS.md +9 -5
  416. package/src/modules/push_notifications/lib/queue.ts +15 -44
@@ -1,5 +1,21 @@
1
+ import {
2
+ ContentLabelExample,
3
+ ContentCardExample,
4
+ KeyIconExamples,
5
+ PaymentIconExamples,
6
+ ChartLegendExamples,
7
+ ChartLegendDotExamples,
8
+ } from '../demos/key-components'
9
+ import { keyComponentExampleCode } from '../demos/key-components-code.generated'
10
+ import { TableCellExamples, TableHeaderExamples, tableCellExampleCode } from '../demos/table-cells'
11
+ import { tableHeaderExampleCode } from '../demos/table-cells-code.generated'
12
+ import { ActivityFeedExample } from '../demos/feeds'
13
+ import { activityFeedExampleCode } from '../demos/feeds-code.generated'
1
14
  import * as React from 'react'
2
- import { Building2, MoreHorizontal } from 'lucide-react'
15
+ import { Building2, Check, ChevronLeft, ChevronRight, MoreHorizontal, Pin, Plus, Star, User, X } from 'lucide-react'
16
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
17
+ import { Button } from '@open-mercato/ui/primitives/button'
18
+ import { ButtonGroup } from '@open-mercato/ui/primitives/button-group'
3
19
  import { Badge } from '@open-mercato/ui/primitives/badge'
4
20
  import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
5
21
  import { Tag } from '@open-mercato/ui/primitives/tag'
@@ -33,21 +49,766 @@ import {
33
49
  ActivityFeedStatusChip,
34
50
  } from '@open-mercato/ui/primitives/activity-feed'
35
51
  import { IconButton } from '@open-mercato/ui/primitives/icon-button'
52
+ import githubLogo from '../assets/github-logo.png'
53
+ import avatarPhoto from '../assets/avatar-photo.png'
54
+ import avatarMemoji from '../assets/avatar-memoji.png'
55
+ import avatarIllustration from '../assets/avatar-illustration.png'
36
56
  import type { GalleryEntry } from '../types'
57
+ function BadgeEntrySemanticPreview() {
58
+ const t = useT()
59
+ return (
60
+ <>
61
+ <Badge variant="success">{t('design_system.gallery.samples.content.success')}</Badge>
62
+ <Badge variant="warning">{t('design_system.gallery.samples.content.warning')}</Badge>
63
+ <Badge variant="info">{t('design_system.gallery.samples.content.info')}</Badge>
64
+ <Badge variant="neutral">{t('design_system.gallery.samples.content.neutral')}</Badge>
65
+ <Badge variant="error">{t('design_system.gallery.samples.content.error')}</Badge>
66
+ <Badge variant="brand">{t('design_system.gallery.samples.content.brand')}</Badge>
67
+ </>
68
+ )
69
+ }
70
+ function BadgeEntrySizesPreview() {
71
+ const t = useT()
72
+ return (
73
+ <>
74
+ <Badge variant="info" size="lg">
75
+ {t('design_system.gallery.samples.content.large')}
76
+ </Badge>
77
+ <Badge variant="info" size="default">
78
+ {t('design_system.gallery.samples.content.default')}
79
+ </Badge>
80
+ <Badge variant="info" size="sm">
81
+ {t('design_system.gallery.samples.content.small')}
82
+ </Badge>
83
+ </>
84
+ )
85
+ }
86
+ function BadgeEntryDotPreview() {
87
+ const t = useT()
88
+ return (
89
+ <>
90
+ <Badge variant="success" dot>
91
+ {t('design_system.gallery.samples.content.active')}
92
+ </Badge>
93
+ <Badge variant="neutral" dot>
94
+ {t('design_system.gallery.samples.content.draft')}
95
+ </Badge>
96
+ <Badge variant="brand" dot>
97
+ {t('design_system.gallery.samples.content.customView')}
98
+ </Badge>
99
+ </>
100
+ )
101
+ }
102
+ function StatusBadgeEntryWithDotPreview() {
103
+ const t = useT()
104
+ return (
105
+ <>
106
+ <StatusBadge variant="success" dot>
107
+ {t('design_system.gallery.samples.content.active')}
108
+ </StatusBadge>
109
+ <StatusBadge variant="warning" dot>
110
+ {t('design_system.gallery.samples.content.pending')}
111
+ </StatusBadge>
112
+ <StatusBadge variant="error" dot>
113
+ {t('design_system.gallery.samples.content.failed')}
114
+ </StatusBadge>
115
+ <StatusBadge variant="info" dot>
116
+ {t('design_system.gallery.samples.content.syncing')}
117
+ </StatusBadge>
118
+ <StatusBadge variant="neutral" dot>
119
+ {t('design_system.gallery.samples.content.archived')}
120
+ </StatusBadge>
121
+ </>
122
+ )
123
+ }
124
+ function StatusBadgeEntryWithoutDotPreview() {
125
+ const t = useT()
126
+ return (
127
+ <>
128
+ <StatusBadge variant="success">{t('design_system.gallery.samples.content.paid')}</StatusBadge>
129
+ <StatusBadge variant="neutral">{t('design_system.gallery.samples.content.draft')}</StatusBadge>
130
+ </>
131
+ )
132
+ }
133
+ function TagEntryDotPreview() {
134
+ const t = useT()
135
+ return (
136
+ <>
137
+ <Tag variant="success" dot>
138
+ {t('design_system.gallery.samples.content.customer')}
139
+ </Tag>
140
+ <Tag variant="brand" dot>
141
+ {t('design_system.gallery.samples.content.renewal')}
142
+ </Tag>
143
+ <Tag variant="pink" dot>
144
+ {t('design_system.gallery.samples.content.campaign')}
145
+ </Tag>
146
+ </>
147
+ )
148
+ }
149
+ function TableEntryDefaultPreview() {
150
+ const t = useT()
151
+ return (
152
+ <Table>
153
+ <TableHeader>
154
+ <TableRow>
155
+ <TableHead>{t('design_system.gallery.samples.content.order')}</TableHead>
156
+ <TableHead>{t('design_system.gallery.samples.content.customer')}</TableHead>
157
+ <TableHead>{t('design_system.gallery.samples.content.status')}</TableHead>
158
+ <TableHead className="text-right">{t('design_system.gallery.samples.content.total')}</TableHead>
159
+ </TableRow>
160
+ </TableHeader>
161
+ <TableBody>
162
+ <TableRow>
163
+ <TableCell>#1042</TableCell>
164
+ <TableCell>Wei Chen</TableCell>
165
+ <TableCell>
166
+ <StatusBadge variant="success" dot>
167
+ {t('design_system.gallery.samples.content.paid')}
168
+ </StatusBadge>
169
+ </TableCell>
170
+ <TableCell className="text-right">$1,250.00</TableCell>
171
+ </TableRow>
172
+ <TableRow>
173
+ <TableCell>#1041</TableCell>
174
+ <TableCell>Laura Perez</TableCell>
175
+ <TableCell>
176
+ <StatusBadge variant="warning" dot>
177
+ {t('design_system.gallery.samples.content.pending')}
178
+ </StatusBadge>
179
+ </TableCell>
180
+ <TableCell className="text-right">$310.50</TableCell>
181
+ </TableRow>
182
+ <TableRow>
183
+ <TableCell>#1040</TableCell>
184
+ <TableCell>Omar Haddad</TableCell>
185
+ <TableCell>
186
+ <StatusBadge variant="neutral" dot>
187
+ {t('design_system.gallery.samples.content.draft')}
188
+ </StatusBadge>
189
+ </TableCell>
190
+ <TableCell className="text-right">$89.00</TableCell>
191
+ </TableRow>
192
+ </TableBody>
193
+ </Table>
194
+ )
195
+ }
196
+ function TableEntryStripedPreview() {
197
+ const t = useT()
198
+ return (
199
+ <Table variant="striped">
200
+ <TableHeader>
201
+ <TableRow>
202
+ <TableHead>SKU</TableHead>
203
+ <TableHead>{t('design_system.gallery.samples.content.product')}</TableHead>
204
+ <TableHead className="text-right">{t('design_system.gallery.samples.content.stock')}</TableHead>
205
+ </TableRow>
206
+ </TableHeader>
207
+ <TableBody>
208
+ <TableRow>
209
+ <TableCell>AP-100</TableCell>
210
+ <TableCell>{t('design_system.gallery.samples.content.apexDeskLamp')}</TableCell>
211
+ <TableCell className="text-right">120</TableCell>
212
+ </TableRow>
213
+ <TableRow>
214
+ <TableCell>AP-101</TableCell>
215
+ <TableCell>{t('design_system.gallery.samples.content.apexMonitorStand')}</TableCell>
216
+ <TableCell className="text-right">64</TableCell>
217
+ </TableRow>
218
+ <TableRow>
219
+ <TableCell>AP-102</TableCell>
220
+ <TableCell>{t('design_system.gallery.samples.content.apexCableKit')}</TableCell>
221
+ <TableCell className="text-right">310</TableCell>
222
+ </TableRow>
223
+ <TableRow>
224
+ <TableCell>AP-103</TableCell>
225
+ <TableCell>{t('design_system.gallery.samples.content.apexLaptopRiser')}</TableCell>
226
+ <TableCell className="text-right">18</TableCell>
227
+ </TableRow>
228
+ </TableBody>
229
+ </Table>
230
+ )
231
+ }
232
+ function TableEntryWithFooterPreview() {
233
+ const t = useT()
234
+ return (
235
+ <Table>
236
+ <TableHeader>
237
+ <TableRow>
238
+ <TableHead>{t('design_system.gallery.samples.content.line')}</TableHead>
239
+ <TableHead className="text-right">{t('design_system.gallery.samples.content.amount')}</TableHead>
240
+ </TableRow>
241
+ </TableHeader>
242
+ <TableBody>
243
+ <TableRow>
244
+ <TableCell>{t('design_system.gallery.samples.content.subtotal')}</TableCell>
245
+ <TableCell className="text-right">$1,560.50</TableCell>
246
+ </TableRow>
247
+ <TableRow>
248
+ <TableCell>{t('design_system.gallery.samples.content.shipping')}</TableCell>
249
+ <TableCell className="text-right">$24.00</TableCell>
250
+ </TableRow>
251
+ </TableBody>
252
+ <TableFooter>
253
+ <TableRow>
254
+ <TableCell>{t('design_system.gallery.samples.content.total')}</TableCell>
255
+ <TableCell className="text-right">$1,584.50</TableCell>
256
+ </TableRow>
257
+ </TableFooter>
258
+ </Table>
259
+ )
260
+ }
261
+ function CardEntryDefaultPreview() {
262
+ const t = useT()
263
+ return (
264
+ <Card className="w-full max-w-sm">
265
+ <CardHeader>
266
+ <CardTitle>{t('design_system.gallery.samples.content.monthlyRevenue')}</CardTitle>
267
+ <CardDescription>{t('design_system.gallery.samples.content.netRevenueAcrossAllChannels')}</CardDescription>
268
+ </CardHeader>
269
+ <CardContent>
270
+ <p className="text-2xl font-semibold">$48,210</p>
271
+ </CardContent>
272
+ <CardFooter>
273
+ <p className="text-sm text-muted-foreground">{t('design_system.gallery.samples.content.updated5MinutesAgo')}</p>
274
+ </CardFooter>
275
+ </Card>
276
+ )
277
+ }
278
+ function CardEntryWithActionPreview() {
279
+ const t = useT()
280
+ return (
281
+ <Card className="w-full max-w-sm">
282
+ <CardHeader>
283
+ <CardTitle>{t('design_system.gallery.samples.content.teamMembers')}</CardTitle>
284
+ <CardDescription>{t('design_system.gallery.samples.content.peopleWithAccessToThisWorkspace')}</CardDescription>
285
+ <CardAction>
286
+ <IconButton type="button" variant="ghost" aria-label={t('design_system.gallery.samples.content.more')}>
287
+ <MoreHorizontal />
288
+ </IconButton>
289
+ </CardAction>
290
+ </CardHeader>
291
+ <CardContent>
292
+ <AvatarStack max={3} size="sm">
293
+ <Avatar label="Wei Chen" size="sm" />
294
+ <Avatar label="Laura Perez" size="sm" />
295
+ <Avatar label="Omar Haddad" size="sm" />
296
+ <Avatar label="Ines Kowalska" size="sm" />
297
+ </AvatarStack>
298
+ </CardContent>
299
+ </Card>
300
+ )
301
+ }
302
+ function SeparatorEntryDefaultPreview() {
303
+ const t = useT()
304
+ return (
305
+ <div className="w-full max-w-sm">
306
+ <p className="text-sm">{t('design_system.gallery.samples.content.shippingDetails')}</p>
307
+ <Separator className="my-3" />
308
+ <p className="text-sm text-muted-foreground">{t('design_system.gallery.samples.content.billingDetails')}</p>
309
+ </div>
310
+ )
311
+ }
312
+ function SeparatorEntryLabeledPreview() {
313
+ const t = useT()
314
+ return (
315
+ <div className="w-full max-w-sm">
316
+ <Separator label={t('design_system.gallery.samples.content.or')} />
317
+ </div>
318
+ )
319
+ }
320
+ function ScrollAreaEntryVerticalPreview() {
321
+ const t = useT()
322
+ return (
323
+ <ScrollArea className="h-40 w-full max-w-xs rounded-md border">
324
+ <div className="p-3">
325
+ {Array.from(
326
+ {
327
+ length: 20,
328
+ },
329
+ (_, i) => (
330
+ <p key={i} className="border-b py-1.5 text-sm last:border-b-0">
331
+ {t('design_system.gallery.samples.content.warehouseZone')}
332
+ {String.fromCharCode(65 + (i % 6))}-{i + 1}
333
+ </p>
334
+ ),
335
+ )}
336
+ </div>
337
+ </ScrollArea>
338
+ )
339
+ }
340
+ function ScrollAreaEntryHorizontalPreview() {
341
+ const t = useT()
342
+ return (
343
+ <ScrollArea scrollbars="horizontal" className="w-full max-w-xs rounded-md border">
344
+ <div className="flex w-max gap-2 p-3">
345
+ {Array.from(
346
+ {
347
+ length: 12,
348
+ },
349
+ (_, i) => (
350
+ <Tag key={i} variant="neutral" shape="square">
351
+ {t('design_system.gallery.samples.content.channel')}
352
+ {i + 1}
353
+ </Tag>
354
+ ),
355
+ )}
356
+ </div>
357
+ </ScrollArea>
358
+ )
359
+ }
360
+ function ActivityFeedEntryBasicPreview() {
361
+ const t = useT()
362
+ return (
363
+ <ActivityFeed className="w-full max-w-md">
364
+ <ActivityFeedItem
365
+ avatar={<Avatar label="Wei Chen" size="sm" />}
366
+ title={
367
+ <>
368
+ Wei Chen{' '}
369
+ <span className="font-normal text-muted-foreground">
370
+ {t('design_system.gallery.samples.content.created')}
371
+ </span>
372
+ {t('design_system.gallery.samples.content.order1042')}
373
+ </>
374
+ }
375
+ timestamp={t('design_system.gallery.samples.content.4MinAgo')}
376
+ />
377
+ <ActivityFeedItem
378
+ avatar={<Avatar label="Laura Perez" size="sm" />}
379
+ title={
380
+ <>
381
+ Laura Perez{' '}
382
+ <span className="font-normal text-muted-foreground">
383
+ {t('design_system.gallery.samples.content.updatedTheShippingAddress')}
384
+ </span>
385
+ </>
386
+ }
387
+ timestamp={t('design_system.gallery.samples.content.1HourAgo')}
388
+ actions={
389
+ <IconButton variant="ghost" size="sm" aria-label={t('design_system.gallery.samples.content.more')}>
390
+ <MoreHorizontal />
391
+ </IconButton>
392
+ }
393
+ />
394
+ </ActivityFeed>
395
+ )
396
+ }
397
+ function ActivityFeedEntryWithAttachmentPreview() {
398
+ const t = useT()
399
+ return (
400
+ <ActivityFeed className="w-full max-w-md">
401
+ <ActivityFeedItem
402
+ avatar={<Avatar label="Omar Haddad" size="sm" />}
403
+ title={
404
+ <>
405
+ Omar Haddad{' '}
406
+ <span className="font-normal text-muted-foreground">
407
+ {t('design_system.gallery.samples.content.uploaded')}
408
+ </span>
409
+ {t('design_system.gallery.samples.content.q2FinancialReport')}
410
+ </>
411
+ }
412
+ timestamp={t('design_system.gallery.samples.content.2DaysAgo')}
413
+ >
414
+ <ActivityFeedFileChip name="apex-report.pdf" size="4mb" onDownload={() => {}} />
415
+ </ActivityFeedItem>
416
+ </ActivityFeed>
417
+ )
418
+ }
419
+ function ActivityFeedEntryWithCommentPreview() {
420
+ const t = useT()
421
+ return (
422
+ <ActivityFeed className="w-full max-w-md">
423
+ <ActivityFeedItem
424
+ avatar={<Avatar label="Ines Kowalska" size="sm" />}
425
+ title={
426
+ <>
427
+ Ines Kowalska{' '}
428
+ <span className="font-normal text-muted-foreground">
429
+ {t('design_system.gallery.samples.content.commented')}
430
+ </span>
431
+ </>
432
+ }
433
+ timestamp={t('design_system.gallery.samples.content.6DaysAgo')}
434
+ >
435
+ <ActivityFeedComment onReply={() => {}}>
436
+ {t('design_system.gallery.samples.content.pleaseReviseTheRiskMetricsBeforeFriday')}
437
+ </ActivityFeedComment>
438
+ </ActivityFeedItem>
439
+ </ActivityFeed>
440
+ )
441
+ }
442
+ function ActivityFeedEntryStatusChipsPreview() {
443
+ const t = useT()
444
+ return (
445
+ <ActivityFeed className="w-full max-w-md">
446
+ <ActivityFeedItem
447
+ avatar={<Avatar label="Ravi Patel" size="sm" />}
448
+ title={
449
+ <>
450
+ Ravi Patel{' '}
451
+ <span className="font-normal text-muted-foreground">
452
+ {t('design_system.gallery.samples.content.moved3Tasks')}
453
+ </span>
454
+ </>
455
+ }
456
+ timestamp={t('design_system.gallery.samples.content.1WeekAgo')}
457
+ >
458
+ <ActivityFeedStatusChip status="success">
459
+ {t('design_system.gallery.samples.content.approved')}
460
+ </ActivityFeedStatusChip>
461
+ <ActivityFeedStatusChip status="warning">
462
+ {t('design_system.gallery.samples.content.needsReview')}
463
+ </ActivityFeedStatusChip>
464
+ <ActivityFeedStatusChip status="error">
465
+ {t('design_system.gallery.samples.content.blocked')}
466
+ </ActivityFeedStatusChip>
467
+ </ActivityFeedItem>
468
+ </ActivityFeed>
469
+ )
470
+ }
471
+ const githubLogoSrc = typeof githubLogo === 'string' ? githubLogo : githubLogo.src
472
+ const avatarPhotoSrc = typeof avatarPhoto === 'string' ? avatarPhoto : avatarPhoto.src
473
+ const avatarMemojiSrc = typeof avatarMemoji === 'string' ? avatarMemoji : avatarMemoji.src
474
+ const avatarIllustrationSrc = typeof avatarIllustration === 'string' ? avatarIllustration : avatarIllustration.src
475
+ function AvatarBadgesDemo() {
476
+ const t = useT()
477
+ return (
478
+ <div className="flex flex-wrap items-center gap-6 p-2">
479
+ <Avatar
480
+ label="Wei Chen"
481
+ ariaLabel={t('design_system.gallery.examples.avatar.verified')}
482
+ badge={<Check className="size-3" />}
483
+ badgeClassName="bg-status-info-icon text-white"
484
+ />
485
+ <Avatar
486
+ label="Laura Perez"
487
+ ariaLabel={t('design_system.gallery.examples.avatar.pinned')}
488
+ badge={<Pin className="size-3" />}
489
+ badgeClassName="bg-accent-indigo text-white"
490
+ />
491
+ <Avatar
492
+ label="Omar Haddad"
493
+ ariaLabel={t('design_system.gallery.examples.avatar.favorite')}
494
+ badge={<Star className="size-3" />}
495
+ badgeClassName="bg-status-success-icon text-white"
496
+ />
497
+ <Avatar
498
+ label="Ines Kowalska"
499
+ ariaLabel={t('design_system.gallery.examples.avatar.add')}
500
+ badge={<Plus className="size-3" />}
501
+ />
502
+ <Avatar
503
+ label="Ravi Patel"
504
+ ariaLabel={t('design_system.gallery.examples.avatar.remove')}
505
+ badge={<X className="size-3" />}
506
+ badgeClassName="bg-status-error-icon text-white"
507
+ />
508
+ <Avatar
509
+ label="James Brown"
510
+ ariaLabel={t('design_system.gallery.examples.avatar.notification')}
511
+ status="error"
512
+ statusPosition="top-right"
513
+ />
514
+ </div>
515
+ )
516
+ }
517
+ function SeparatorActionDemo({ kind }: { kind: 'icon' | 'icon-group' | 'text' | 'text-group' }) {
518
+ const t = useT()
519
+ return (
520
+ <div className="flex w-full items-center gap-2.5">
521
+ <Separator className="min-w-0 flex-1" />
522
+ {kind === 'icon' ? (
523
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.add')}>
524
+ <Plus className="size-5" />
525
+ </IconButton>
526
+ ) : kind === 'icon-group' ? (
527
+ <ButtonGroup aria-label={t('design_system.gallery.examples.separator.actions')}>
528
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.previous')}>
529
+ <ChevronLeft className="size-5" />
530
+ </IconButton>
531
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.add')}>
532
+ <Plus className="size-5" />
533
+ </IconButton>
534
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.next')}>
535
+ <ChevronRight className="size-5" />
536
+ </IconButton>
537
+ </ButtonGroup>
538
+ ) : kind === 'text' ? (
539
+ <Button type="button" size="sm" variant="outline" className="px-2.5">
540
+ {t('design_system.gallery.examples.separator.add')}
541
+ </Button>
542
+ ) : (
543
+ <ButtonGroup size="sm" aria-label={t('design_system.gallery.examples.separator.actions')}>
544
+ <Button type="button" size="sm" variant="outline" className="px-3.5">
545
+ {t('design_system.gallery.examples.separator.previous')}
546
+ </Button>
547
+ <Button type="button" size="sm" variant="outline" className="px-3.5">
548
+ {t('design_system.gallery.examples.separator.add')}
549
+ </Button>
550
+ <Button type="button" size="sm" variant="outline" className="px-3.5">
551
+ {t('design_system.gallery.examples.separator.next')}
552
+ </Button>
553
+ </ButtonGroup>
554
+ )}
555
+ <Separator className="min-w-0 flex-1" />
556
+ </div>
557
+ )
558
+ }
559
+ function SeparatorTextDemo({ kind }: { kind: 'label-alignments' | 'text' }) {
560
+ const t = useT()
561
+ return kind === 'text' ? (
562
+ <Separator section label={t('design_system.gallery.examples.separator.or')} className="bg-transparent px-2 py-1" />
563
+ ) : (
564
+ <div className="grid w-full gap-6">
565
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="start" />
566
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="center" />
567
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="end" />
568
+ </div>
569
+ )
570
+ }
37
571
 
38
572
  // Component titles and variant names are proper nouns from the codebase and
39
573
  // are deliberately not translated. `code` MUST contain the entry's importPath
40
574
  // (enforced by the registry-integrity test) and is always reviewed alongside
41
575
  // its sibling `render`.
42
576
 
577
+ function BadgeAppearanceDemo({ appearance }: { appearance: 'filled' | 'light' | 'lighter' | 'stroke' }) {
578
+ const t = useT()
579
+ return (
580
+ <div className="space-y-4">
581
+ <div className="flex flex-wrap gap-3">
582
+ {(['neutral', 'info', 'warning', 'error', 'success', 'pink', 'yellow', 'purple', 'sky', 'teal'] as const).map(
583
+ (tone) => (
584
+ <Badge key={tone} appearance={appearance} tone={tone} dot>
585
+ {tone}
586
+ </Badge>
587
+ ),
588
+ )}
589
+ </div>
590
+ <p className="max-w-2xl text-xs leading-5 text-muted-foreground">
591
+ {t('design_system.gallery.examples.badgeTag.paletteHint')}
592
+ </p>
593
+ </div>
594
+ )
595
+ }
596
+ function BadgeSourceSizeDemo() {
597
+ const t = useT()
598
+ const label = t('design_system.gallery.examples.badgeTag.label')
599
+ return (
600
+ <div className="flex flex-col gap-6">
601
+ {([16, 20] as const).map((size) => (
602
+ <div key={size} className="flex flex-wrap items-center gap-3">
603
+ <span className="w-12 text-xs text-muted-foreground">{size}px</span>
604
+ <Badge size={size} appearance="filled" tone="purple">
605
+ {label}
606
+ </Badge>
607
+ <Badge size={size} appearance="light" tone="yellow" dot>
608
+ {label}
609
+ </Badge>
610
+ <Badge size={size} appearance="lighter" tone="sky" leadingIcon={<User />}>
611
+ {label}
612
+ </Badge>
613
+ <Badge size={size} appearance="stroke" tone="teal" trailingIcon={<ChevronRight />}>
614
+ {label}
615
+ </Badge>
616
+ <Badge size={size} appearance="filled" tone="info" numeric>
617
+ {2}
618
+ </Badge>
619
+ <Badge size={size} appearance="filled" tone="info" numeric>
620
+ {125}
621
+ </Badge>
622
+ <Badge size={size} appearance="stroke" tone="purple" disabled>
623
+ {label}
624
+ </Badge>
625
+ </div>
626
+ ))}
627
+ </div>
628
+ )
629
+ }
630
+ function BadgeContentDemo() {
631
+ const t = useT()
632
+ const label = t('design_system.gallery.examples.badgeTag.label')
633
+ return (
634
+ <div className="flex flex-wrap items-center gap-3">
635
+ <Badge appearance="lighter" tone="info">
636
+ {label}
637
+ </Badge>
638
+ <Badge appearance="lighter" tone="info" dot>
639
+ {label}
640
+ </Badge>
641
+ <Badge appearance="lighter" tone="info" leadingIcon={<User />}>
642
+ {label}
643
+ </Badge>
644
+ <Badge appearance="lighter" tone="info" trailingIcon={<ChevronRight />}>
645
+ {label}
646
+ </Badge>
647
+ <Badge appearance="filled" tone="info">
648
+ {4}
649
+ </Badge>
650
+ <Badge appearance="stroke" tone="info">
651
+ {24}
652
+ </Badge>
653
+ </div>
654
+ )
655
+ }
656
+ function BadgeDisabledDemo() {
657
+ const t = useT()
658
+ return (
659
+ <div className="flex flex-wrap gap-3">
660
+ {(['filled', 'light', 'lighter', 'stroke'] as const).map((appearance) => (
661
+ <Badge key={appearance} appearance={appearance} tone="info" disabled leadingIcon={<User />}>
662
+ {t('design_system.gallery.examples.badgeTag.locked')}
663
+ </Badge>
664
+ ))}
665
+ </div>
666
+ )
667
+ }
668
+ function RemovableBadgeDemo() {
669
+ const t = useT()
670
+ const [visible, setVisible] = React.useState(true)
671
+ const region = t('design_system.gallery.examples.badgeTag.region')
672
+ const locked = t('design_system.gallery.examples.badgeTag.locked')
673
+ return (
674
+ <div className="flex flex-wrap items-center gap-3">
675
+ {visible && (
676
+ <Badge
677
+ appearance="lighter"
678
+ tone="neutral"
679
+ removable
680
+ onRemove={() => setVisible(false)}
681
+ removeAriaLabel={t('design_system.gallery.examples.badgeTag.remove', {
682
+ label: region,
683
+ })}
684
+ >
685
+ {region}
686
+ </Badge>
687
+ )}
688
+ <Badge
689
+ appearance="lighter"
690
+ tone="neutral"
691
+ disabled
692
+ removable
693
+ onRemove={() => setVisible(false)}
694
+ removeAriaLabel={t('design_system.gallery.examples.badgeTag.remove', {
695
+ label: locked,
696
+ })}
697
+ >
698
+ {locked}
699
+ </Badge>
700
+ <Button type="button" variant="outline" size="sm" disabled={visible} onClick={() => setVisible(true)}>
701
+ {t('design_system.gallery.examples.badgeTag.restore')}
702
+ </Button>
703
+ </div>
704
+ )
705
+ }
706
+ function StatusAppearanceDemo({ appearance }: { appearance: 'light' | 'stroke' }) {
707
+ return (
708
+ <div className="grid gap-4">
709
+ {[true, false].map((dot) => (
710
+ <div key={String(dot)} className="flex flex-wrap gap-3">
711
+ {(['success', 'warning', 'error', 'info', 'neutral'] as const).map((variant) => (
712
+ <StatusBadge key={variant} variant={variant} appearance={appearance} dot={dot}>
713
+ {variant}
714
+ </StatusBadge>
715
+ ))}
716
+ </div>
717
+ ))}
718
+ </div>
719
+ )
720
+ }
721
+ function TagAppearanceDemo({ appearance }: { appearance: 'stroke' | 'gray' }) {
722
+ const t = useT()
723
+ return (
724
+ <div className="space-y-4">
725
+ <div className="flex flex-wrap items-center gap-3">
726
+ <Tag appearance={appearance}>{t('design_system.gallery.examples.badgeTag.label')}</Tag>
727
+ <Tag appearance={appearance} leading={<User />}>
728
+ {t('design_system.gallery.examples.badgeTag.customer')}
729
+ </Tag>
730
+ <Tag
731
+ appearance={appearance}
732
+ leading={<img src={avatarPhotoSrc} alt="" className="size-4 rounded-full object-cover" />}
733
+ >
734
+ James Brown
735
+ </Tag>
736
+ <Tag appearance={appearance} leading={<span>🇵🇱</span>}>
737
+ {t('design_system.gallery.examples.badgeTag.country')}
738
+ </Tag>
739
+ <Tag
740
+ appearance={appearance}
741
+ leading={<img src={githubLogoSrc} alt="" className="size-4 rounded-sm bg-white" />}
742
+ >
743
+ GitHub
744
+ </Tag>
745
+ <Tag appearance={appearance} leading={<Building2 />} sublabel="(4)">
746
+ Open Mercato
747
+ </Tag>
748
+ </div>
749
+ <p className="max-w-2xl text-xs leading-5 text-muted-foreground">
750
+ {t('design_system.gallery.examples.badgeTag.tagHint')}
751
+ </p>
752
+ </div>
753
+ )
754
+ }
755
+ function RemovableTagDemo() {
756
+ const t = useT()
757
+ const [removed, setRemoved] = React.useState<string[]>([])
758
+ const region = t('design_system.gallery.examples.badgeTag.region')
759
+ const locked = t('design_system.gallery.examples.badgeTag.locked')
760
+ return (
761
+ <div className="space-y-4">
762
+ <p className="max-w-2xl text-xs leading-5 text-muted-foreground">
763
+ {t('design_system.gallery.examples.badgeTag.statesHint')}
764
+ </p>
765
+ <div className="flex flex-wrap items-center gap-3">
766
+ {(['stroke', 'gray'] as const).map((appearance) => (
767
+ <React.Fragment key={appearance}>
768
+ {!removed.includes(appearance) && (
769
+ <Tag
770
+ appearance={appearance}
771
+ leading={<User />}
772
+ sublabel="(4)"
773
+ onRemove={() => setRemoved((current) => [...current, appearance])}
774
+ removeAriaLabel={t('design_system.gallery.examples.badgeTag.remove', {
775
+ label: region,
776
+ })}
777
+ >
778
+ {region}
779
+ </Tag>
780
+ )}
781
+ <Tag
782
+ appearance={appearance}
783
+ disabled
784
+ leading={<User />}
785
+ sublabel="(4)"
786
+ onRemove={() => setRemoved((current) => [...current, appearance])}
787
+ removeAriaLabel={t('design_system.gallery.examples.badgeTag.remove', {
788
+ label: locked,
789
+ })}
790
+ >
791
+ {locked}
792
+ </Tag>
793
+ </React.Fragment>
794
+ ))}
795
+ <Button type="button" variant="outline" size="sm" disabled={!removed.length} onClick={() => setRemoved([])}>
796
+ {t('design_system.gallery.examples.badgeTag.restore')}
797
+ </Button>
798
+ </div>
799
+ </div>
800
+ )
801
+ }
43
802
  const badgeEntry: GalleryEntry = {
44
803
  id: 'badge',
45
804
  title: 'Badge',
46
805
  importPath: '@open-mercato/ui/primitives/badge',
806
+ figmaNodeId: '118:2324',
47
807
  usage: {
48
808
  do: [
49
809
  'Counts and short semantic labels; the brand variant for custom-view and renewal pills.',
50
810
  'Semantic variants (success/warning/info/neutral/error) come from status tokens — no custom colors.',
811
+ 'Four appearances and ten color families; numeric sizes16/20 follow measured source dimensions. Named sizes and semantic status palettes retain application defaults; new category fills use measured Figma colors with accessible text.',
51
812
  ],
52
813
  dont: ['Not for system statuses (use StatusBadge) or user-applied labels (use Tag).'],
53
814
  },
@@ -55,16 +816,7 @@ const badgeEntry: GalleryEntry = {
55
816
  {
56
817
  id: 'semantic',
57
818
  title: 'Semantic variants',
58
- render: () => (
59
- <>
60
- <Badge variant="success">Success</Badge>
61
- <Badge variant="warning">Warning</Badge>
62
- <Badge variant="info">Info</Badge>
63
- <Badge variant="neutral">Neutral</Badge>
64
- <Badge variant="error">Error</Badge>
65
- <Badge variant="brand">Brand</Badge>
66
- </>
67
- ),
819
+ render: () => <BadgeEntrySemanticPreview />,
68
820
  code: `import { Badge } from '@open-mercato/ui/primitives/badge'
69
821
 
70
822
  <Badge variant="success">Success</Badge>
@@ -77,13 +829,7 @@ const badgeEntry: GalleryEntry = {
77
829
  {
78
830
  id: 'sizes',
79
831
  title: 'Sizes',
80
- render: () => (
81
- <>
82
- <Badge variant="info" size="lg">Large</Badge>
83
- <Badge variant="info" size="default">Default</Badge>
84
- <Badge variant="info" size="sm">Small</Badge>
85
- </>
86
- ),
832
+ render: () => <BadgeEntrySizesPreview />,
87
833
  code: `import { Badge } from '@open-mercato/ui/primitives/badge'
88
834
 
89
835
  <Badge variant="info" size="lg">Large</Badge>
@@ -93,13 +839,7 @@ const badgeEntry: GalleryEntry = {
93
839
  {
94
840
  id: 'dot',
95
841
  title: 'With dot',
96
- render: () => (
97
- <>
98
- <Badge variant="success" dot>Active</Badge>
99
- <Badge variant="neutral" dot>Draft</Badge>
100
- <Badge variant="brand" dot>Custom view</Badge>
101
- </>
102
- ),
842
+ render: () => <BadgeEntryDotPreview />,
103
843
  code: `import { Badge } from '@open-mercato/ui/primitives/badge'
104
844
 
105
845
  <Badge variant="success" dot>Active</Badge>
@@ -109,24 +849,115 @@ const badgeEntry: GalleryEntry = {
109
849
  {
110
850
  id: 'removable',
111
851
  title: 'Removable',
112
- render: () => (
113
- <>
114
- <Badge variant="neutral" removable onRemove={() => {}}>Filter: Region</Badge>
115
- <Badge variant="brand" removable onRemove={() => {}}>Renewal</Badge>
116
- </>
117
- ),
852
+ render: () => <RemovableBadgeDemo />,
853
+ code: `import * as React from 'react'
854
+ import { Badge } from '@open-mercato/ui/primitives/badge'
855
+ import { Button } from '@open-mercato/ui/primitives/button'
856
+
857
+ const [visible, setVisible] = React.useState(true)
858
+ {visible && <Badge appearance="lighter" tone="neutral" removable onRemove={() => setVisible(false)} removeAriaLabel={removeLabel}>{label}</Badge>}
859
+ <Badge appearance="lighter" tone="neutral" disabled removable onRemove={() => setVisible(false)} removeAriaLabel={removeLockedLabel}>{lockedLabel}</Badge>
860
+ <Button type="button" variant="outline" size="sm" disabled={visible} onClick={() => setVisible(true)}>{restoreLabel}</Button>`,
861
+ },
862
+ {
863
+ id: 'appearance-filled',
864
+ title: 'Filled appearance',
865
+ render: () => <BadgeAppearanceDemo appearance="filled" />,
118
866
  code: `import { Badge } from '@open-mercato/ui/primitives/badge'
119
867
 
120
- <Badge variant="neutral" removable onRemove={() => setRegion(null)}>Filter: Region</Badge>
121
- <Badge variant="brand" removable onRemove={() => clearTag()}>Renewal</Badge>`,
868
+ {(['neutral', 'info', 'warning', 'error', 'success', 'pink', 'yellow', 'purple', 'sky', 'teal'] as const).map(tone => (
869
+ <Badge key={tone} appearance="filled" tone={tone} dot>{tone}</Badge>
870
+ ))}`,
122
871
  },
123
- ],
872
+ {
873
+ id: 'appearance-light',
874
+ title: 'Light appearance',
875
+ render: () => <BadgeAppearanceDemo appearance="light" />,
876
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
877
+
878
+ {(['neutral', 'info', 'warning', 'error', 'success', 'pink', 'yellow', 'purple', 'sky', 'teal'] as const).map(tone => (
879
+ <Badge key={tone} appearance="light" tone={tone} dot>{tone}</Badge>
880
+ ))}`,
881
+ },
882
+ {
883
+ id: 'appearance-lighter',
884
+ title: 'Lighter appearance',
885
+ render: () => <BadgeAppearanceDemo appearance="lighter" />,
886
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
887
+
888
+ {(['neutral', 'info', 'warning', 'error', 'success', 'pink', 'yellow', 'purple', 'sky', 'teal'] as const).map(tone => (
889
+ <Badge key={tone} appearance="lighter" tone={tone} dot>{tone}</Badge>
890
+ ))}`,
891
+ },
892
+ {
893
+ id: 'appearance-stroke',
894
+ title: 'Stroke appearance',
895
+ render: () => <BadgeAppearanceDemo appearance="stroke" />,
896
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
897
+
898
+ {(['neutral', 'info', 'warning', 'error', 'success', 'pink', 'yellow', 'purple', 'sky', 'teal'] as const).map(tone => (
899
+ <Badge key={tone} appearance="stroke" tone={tone} dot>{tone}</Badge>
900
+ ))}`,
901
+ },
902
+ {
903
+ id: 'content',
904
+ title: 'Basic, dot, icons and numeric content',
905
+ render: () => <BadgeContentDemo />,
906
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
907
+ import { User, ChevronRight } from 'lucide-react'
908
+
909
+ <Badge appearance="lighter" tone="info">{label}</Badge>
910
+ <Badge appearance="lighter" tone="info" dot>{label}</Badge>
911
+ <Badge appearance="lighter" tone="info" leadingIcon={<User />}>{label}</Badge>
912
+ <Badge appearance="lighter" tone="info" trailingIcon={<ChevronRight />}>{label}</Badge>
913
+ <Badge appearance="filled" tone="info">{4}</Badge>
914
+ <Badge appearance="stroke" tone="info">{24}</Badge>`,
915
+ },
916
+ {
917
+ id: 'disabled',
918
+ title: 'Disabled appearances',
919
+ render: () => <BadgeDisabledDemo />,
920
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
921
+ import { User } from 'lucide-react'
922
+
923
+ {(['filled', 'light', 'lighter', 'stroke'] as const).map(appearance => (
924
+ <Badge key={appearance} appearance={appearance} tone="info" disabled leadingIcon={<User />}>{label}</Badge>
925
+ ))}`,
926
+ },
927
+ {
928
+ id: 'source-sizes',
929
+ title: 'Source16px /20px and numeric content',
930
+ render: () => <BadgeSourceSizeDemo />,
931
+ code: `import { Badge } from '@open-mercato/ui/primitives/badge'
932
+ import { User, ChevronRight } from 'lucide-react'
933
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
934
+
935
+ function BadgeSourceSizeDemo() {
936
+ const t = useT()
937
+ const label = t('design_system.gallery.examples.badgeTag.label')
938
+ return <div className="flex flex-col gap-6">
939
+ {([16, 20] as const).map(size => <div key={size} className="flex flex-wrap items-center gap-3">
940
+ <span className="w-12 text-xs text-muted-foreground">{size}px</span>
941
+ <Badge size={size} appearance="filled" tone="purple">{label}</Badge>
942
+ <Badge size={size} appearance="light" tone="yellow" dot>{label}</Badge>
943
+ <Badge size={size} appearance="lighter" tone="sky" leadingIcon={<User />}>{label}</Badge>
944
+ <Badge size={size} appearance="stroke" tone="teal" trailingIcon={<ChevronRight />}>{label}</Badge>
945
+ <Badge size={size} appearance="filled" tone="info" numeric>{2}</Badge>
946
+ <Badge size={size} appearance="filled" tone="info" numeric>{125}</Badge>
947
+ <Badge size={size} appearance="stroke" tone="purple" disabled>{label}</Badge>
948
+ </div>)}
949
+ </div>
124
950
  }
125
951
 
952
+ <BadgeSourceSizeDemo />`,
953
+ },
954
+ ],
955
+ }
126
956
  const statusBadgeEntry: GalleryEntry = {
127
957
  id: 'status-badge',
128
958
  title: 'StatusBadge',
129
959
  importPath: '@open-mercato/ui/primitives/status-badge',
960
+ figmaNodeId: '171:5100',
130
961
  usage: {
131
962
  do: [
132
963
  'System-computed statuses (active, pending, failed) — drive variants through a shared StatusMap.',
@@ -138,15 +969,7 @@ const statusBadgeEntry: GalleryEntry = {
138
969
  {
139
970
  id: 'with-dot',
140
971
  title: 'Variants with dot',
141
- render: () => (
142
- <>
143
- <StatusBadge variant="success" dot>Active</StatusBadge>
144
- <StatusBadge variant="warning" dot>Pending</StatusBadge>
145
- <StatusBadge variant="error" dot>Failed</StatusBadge>
146
- <StatusBadge variant="info" dot>Syncing</StatusBadge>
147
- <StatusBadge variant="neutral" dot>Archived</StatusBadge>
148
- </>
149
- ),
972
+ render: () => <StatusBadgeEntryWithDotPreview />,
150
973
  code: `import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
151
974
 
152
975
  <StatusBadge variant="success" dot>Active</StatusBadge>
@@ -158,24 +981,39 @@ const statusBadgeEntry: GalleryEntry = {
158
981
  {
159
982
  id: 'without-dot',
160
983
  title: 'Without dot',
161
- render: () => (
162
- <>
163
- <StatusBadge variant="success">Paid</StatusBadge>
164
- <StatusBadge variant="neutral">Draft</StatusBadge>
165
- </>
166
- ),
984
+ render: () => <StatusBadgeEntryWithoutDotPreview />,
167
985
  code: `import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
168
986
 
169
987
  <StatusBadge variant="success">Paid</StatusBadge>
170
988
  <StatusBadge variant="neutral">Draft</StatusBadge>`,
171
989
  },
990
+ {
991
+ id: 'appearance-light',
992
+ title: 'Light appearance, with and without dot',
993
+ render: () => <StatusAppearanceDemo appearance="light" />,
994
+ code: `import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
995
+
996
+ {[true, false].map(dot => (['success', 'warning', 'error', 'info', 'neutral'] as const).map(variant => (
997
+ <StatusBadge key={variant + String(dot)} variant={variant} appearance="light" dot={dot}>{variant}</StatusBadge>
998
+ )))}`,
999
+ },
1000
+ {
1001
+ id: 'appearance-stroke',
1002
+ title: 'Stroke appearance, with and without dot',
1003
+ render: () => <StatusAppearanceDemo appearance="stroke" />,
1004
+ code: `import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
1005
+
1006
+ {[true, false].map(dot => (['success', 'warning', 'error', 'info', 'neutral'] as const).map(variant => (
1007
+ <StatusBadge key={variant + String(dot)} variant={variant} appearance="stroke" dot={dot}>{variant}</StatusBadge>
1008
+ )))}`,
1009
+ },
172
1010
  ],
173
1011
  }
174
-
175
1012
  const tagEntry: GalleryEntry = {
176
1013
  id: 'tag',
177
1014
  title: 'Tag',
178
1015
  importPath: '@open-mercato/ui/primitives/tag',
1016
+ figmaNodeId: '431:16147',
179
1017
  usage: {
180
1018
  do: ['User-applied labels and categories; map domain types via TagMap for consistency.'],
181
1019
  dont: ['Not for system status — that is StatusBadge.'],
@@ -210,13 +1048,7 @@ const tagEntry: GalleryEntry = {
210
1048
  {
211
1049
  id: 'dot',
212
1050
  title: 'With dot',
213
- render: () => (
214
- <>
215
- <Tag variant="success" dot>Customer</Tag>
216
- <Tag variant="brand" dot>Renewal</Tag>
217
- <Tag variant="pink" dot>Campaign</Tag>
218
- </>
219
- ),
1051
+ render: () => <TagEntryDotPreview />,
220
1052
  code: `import { Tag } from '@open-mercato/ui/primitives/tag'
221
1053
 
222
1054
  <Tag variant="success" dot>Customer</Tag>
@@ -229,7 +1061,9 @@ const tagEntry: GalleryEntry = {
229
1061
  render: () => (
230
1062
  <>
231
1063
  <Tag shape="square">default</Tag>
232
- <Tag variant="info" shape="square" dot>info</Tag>
1064
+ <Tag variant="info" shape="square" dot>
1065
+ info
1066
+ </Tag>
233
1067
  </>
234
1068
  ),
235
1069
  code: `import { Tag } from '@open-mercato/ui/primitives/tag'
@@ -240,24 +1074,68 @@ const tagEntry: GalleryEntry = {
240
1074
  {
241
1075
  id: 'removable',
242
1076
  title: 'Removable',
243
- render: () => (
244
- <>
245
- <Tag variant="neutral" onRemove={() => {}}>Wholesale</Tag>
246
- <Tag variant="neutral" onRemove={() => {}} disabled>Locked</Tag>
247
- </>
248
- ),
1077
+ render: () => <RemovableTagDemo />,
1078
+ code: `import * as React from 'react'
1079
+ import { Tag } from '@open-mercato/ui/primitives/tag'
1080
+ import { Button } from '@open-mercato/ui/primitives/button'
1081
+ import { User } from 'lucide-react'
1082
+
1083
+ const [removed, setRemoved] = React.useState<string[]>([])
1084
+ {(['stroke', 'gray'] as const).map(appearance => <React.Fragment key={appearance}>
1085
+ {!removed.includes(appearance) && <Tag appearance={appearance} leading={<User />} sublabel="(4)" onRemove={() => setRemoved(current => [...current, appearance])} removeAriaLabel={removeLabel}>{label}</Tag>}
1086
+ <Tag appearance={appearance} disabled leading={<User />} sublabel="(4)" onRemove={() => setRemoved(current => [...current, appearance])} removeAriaLabel={removeLockedLabel}>{lockedLabel}</Tag>
1087
+ </React.Fragment>)}
1088
+ <Button type="button" variant="outline" size="sm" disabled={!removed.length} onClick={() => setRemoved([])}>{restoreLabel}</Button>`,
1089
+ },
1090
+ {
1091
+ id: 'appearance-stroke',
1092
+ title: 'Stroke appearance and leading content',
1093
+ render: () => <TagAppearanceDemo appearance="stroke" />,
249
1094
  code: `import { Tag } from '@open-mercato/ui/primitives/tag'
1095
+ import { User, Building2 } from 'lucide-react'
250
1096
 
251
- <Tag variant="neutral" onRemove={() => removeTag('wholesale')}>Wholesale</Tag>
252
- <Tag variant="neutral" onRemove={() => {}} disabled>Locked</Tag>`,
1097
+ <Tag appearance="stroke">{label}</Tag>
1098
+ <Tag appearance="stroke" leading={<User />}>{customerLabel}</Tag>
1099
+ <Tag appearance="stroke" leading={<img src={avatarPhotoSrc} alt="" className="size-4 rounded-full object-cover" />}>James Brown</Tag>
1100
+ <Tag appearance="stroke" leading={<span>🇵🇱</span>}>{countryLabel}</Tag>
1101
+ <Tag appearance="stroke" leading={<img src={githubLogoSrc} alt="" className="size-4 rounded-sm bg-white" />}>GitHub</Tag>
1102
+ <Tag appearance="stroke" leading={<Building2 />} sublabel="(4)">Open Mercato</Tag>`,
1103
+ },
1104
+ {
1105
+ id: 'appearance-gray',
1106
+ title: 'Gray appearance and leading content',
1107
+ render: () => <TagAppearanceDemo appearance="gray" />,
1108
+ code: `import { Tag } from '@open-mercato/ui/primitives/tag'
1109
+ import { User, Building2 } from 'lucide-react'
1110
+
1111
+ <Tag appearance="gray">{label}</Tag>
1112
+ <Tag appearance="gray" leading={<User />}>{customerLabel}</Tag>
1113
+ <Tag appearance="gray" leading={<img src={avatarPhotoSrc} alt="" className="size-4 rounded-full object-cover" />}>James Brown</Tag>
1114
+ <Tag appearance="gray" leading={<span>🇵🇱</span>}>{countryLabel}</Tag>
1115
+ <Tag appearance="gray" leading={<img src={githubLogoSrc} alt="" className="size-4 rounded-sm bg-white" />}>GitHub</Tag>
1116
+ <Tag appearance="gray" leading={<Building2 />} sublabel="(4)">Open Mercato</Tag>`,
253
1117
  },
254
1118
  ],
255
1119
  }
256
-
257
1120
  const avatarEntry: GalleryEntry = {
258
1121
  id: 'avatar',
259
1122
  title: 'Avatar',
260
1123
  importPath: '@open-mercato/ui/primitives/avatar',
1124
+ figmaNodeId: '245:18786',
1125
+ usage: {
1126
+ do: [
1127
+ 'Use src for photos, Memoji, and illustrations; use label for initials or icon for an entity symbol.',
1128
+ 'Numeric sizes reproduce all nine Figma diameters: 20, 24, 32, 40, 48, 56, 64, 72, and 80 px. Legacy xs/sm/md/lg/xl sizes remain 20/28/36/48/64 px.',
1129
+ 'Numeric 20–32 px initials use one letter; 40–80 px use two. Font size, line height, and medium weight follow the source. The application font and tracking remain governed by existing tokens.',
1130
+ 'Photo stacks use the audited size-specific overlaps. Initial stacks reduce overlap where two letters need more room, and full overflow counts can widen beyond the avatar diameter.',
1131
+ 'The six top-status examples use the existing circular badge slot and semantic colors. They show supported compositions, not an exact replica of the Figma verified silhouette.',
1132
+ 'Local James Brown assets come from Figma nodes 246:11135, 246:11139, and 246:11141. The production image crop can differ from Figma.',
1133
+ ],
1134
+ dont: [
1135
+ 'Do not assume square avatars or simultaneous top and bottom decorations are supported by the current API.',
1136
+ 'Do not render interactive actions inside the decorative badge slot; put actions in a separate button.',
1137
+ ],
1138
+ },
261
1139
  variants: [
262
1140
  {
263
1141
  id: 'sizes',
@@ -279,6 +1157,102 @@ const avatarEntry: GalleryEntry = {
279
1157
  <Avatar label="Wei Chen" size="md" />
280
1158
  <Avatar label="Wei Chen" size="sm" />
281
1159
  <Avatar label="Wei Chen" size="xs" />`,
1160
+ },
1161
+ {
1162
+ id: 'figma-sizes',
1163
+ title: 'Figma sizes (20–80 px)',
1164
+ render: () => (
1165
+ <div className="flex flex-wrap items-end gap-6">
1166
+ {([20, 24, 32, 40, 48, 56, 64, 72, 80] as const).map((size) => (
1167
+ <div key={size} className="flex flex-col items-center gap-3">
1168
+ <Avatar label="Wei Chen" size={size} />
1169
+ <code className="text-xs text-muted-foreground">{size}px</code>
1170
+ </div>
1171
+ ))}
1172
+ </div>
1173
+ ),
1174
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1175
+
1176
+ <Avatar label="Wei Chen" size={20} />
1177
+ <Avatar label="Wei Chen" size={24} />
1178
+ <Avatar label="Wei Chen" size={32} />
1179
+ <Avatar label="Wei Chen" size={40} />
1180
+ <Avatar label="Wei Chen" size={48} />
1181
+ <Avatar label="Wei Chen" size={56} />
1182
+ <Avatar label="Wei Chen" size={64} />
1183
+ <Avatar label="Wei Chen" size={72} />
1184
+ <Avatar label="Wei Chen" size={80} />`,
1185
+ },
1186
+ {
1187
+ id: 'figma-stack-sizes',
1188
+ title: 'Figma stack sizes and readable initials',
1189
+ render: () => (
1190
+ <div className="grid w-full gap-6">
1191
+ {([20, 24, 32, 40, 48, 56, 64, 72, 80] as const).map((size) => (
1192
+ <div key={size} className="flex flex-wrap items-center gap-6">
1193
+ <code className="text-xs text-muted-foreground">{size}px</code>
1194
+ <AvatarStack size={size} max={3} overflowCount={12}>
1195
+ <Avatar label="Wei Chen" size={size} />
1196
+ <Avatar label="Laura Perez" size={size} />
1197
+ <Avatar label="Omar Haddad" size={size} />
1198
+ </AvatarStack>
1199
+ </div>
1200
+ ))}
1201
+ </div>
1202
+ ),
1203
+ code: `import { Avatar, AvatarStack } from '@open-mercato/ui/primitives/avatar'
1204
+
1205
+ {([20, 24, 32, 40, 48, 56, 64, 72, 80] as const).map((size) => (
1206
+ <AvatarStack key={size} size={size} max={3} overflowCount={12}>
1207
+ <Avatar label="Wei Chen" size={size} />
1208
+ <Avatar label="Laura Perez" size={size} />
1209
+ <Avatar label="Omar Haddad" size={size} />
1210
+ </AvatarStack>
1211
+ ))}`,
1212
+ },
1213
+ {
1214
+ id: 'photo',
1215
+ title: 'Photo source',
1216
+ render: () => <Avatar label="James Brown" src={avatarPhotoSrc} size="lg" />,
1217
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1218
+ import photo from './avatar-photo.png'
1219
+
1220
+ <Avatar label="James Brown" src={typeof photo === 'string' ? photo : photo.src} size="lg" />`,
1221
+ },
1222
+ {
1223
+ id: 'memoji',
1224
+ title: 'Memoji source',
1225
+ render: () => <Avatar label="James Brown" src={avatarMemojiSrc} size="lg" variant="monochrome" />,
1226
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1227
+ import memoji from './avatar-memoji.png'
1228
+
1229
+ <Avatar label="James Brown" src={typeof memoji === 'string' ? memoji : memoji.src} size="lg" variant="monochrome" />`,
1230
+ },
1231
+ {
1232
+ id: 'illustration',
1233
+ title: 'Illustration source',
1234
+ render: () => <Avatar label="James Brown" src={avatarIllustrationSrc} size="lg" variant="monochrome" />,
1235
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1236
+ import illustration from './avatar-illustration.png'
1237
+
1238
+ <Avatar label="James Brown" src={typeof illustration === 'string' ? illustration : illustration.src} size="lg" variant="monochrome" />`,
1239
+ },
1240
+ {
1241
+ id: 'solid-background',
1242
+ title: 'Solid background',
1243
+ render: () => <Avatar label="James Brown" icon={<span />} size="lg" variant="monochrome" />,
1244
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1245
+
1246
+ <Avatar label="James Brown" icon={<span />} size="lg" variant="monochrome" />`,
1247
+ },
1248
+ {
1249
+ id: 'person-icon',
1250
+ title: 'Person icon',
1251
+ render: () => <Avatar label="James Brown" icon={<User />} size="lg" variant="monochrome" />,
1252
+ code: `import { User } from 'lucide-react'
1253
+ import { Avatar } from '@open-mercato/ui/primitives/avatar'
1254
+
1255
+ <Avatar label="James Brown" icon={<User />} size="lg" variant="monochrome" />`,
282
1256
  },
283
1257
  {
284
1258
  id: 'variants',
@@ -314,6 +1288,94 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
314
1288
  <Avatar label="Laura Perez" status="busy" />
315
1289
  <Avatar label="Omar Haddad" status="away" />
316
1290
  <Avatar label="Ines Kowalska" status="offline" />`,
1291
+ },
1292
+ {
1293
+ id: 'top-badges',
1294
+ title: 'Top Status compositions',
1295
+ render: () => <AvatarBadgesDemo />,
1296
+ code: `import { Check, Pin, Star, Plus, X } from 'lucide-react'
1297
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1298
+ import { Avatar } from '@open-mercato/ui/primitives/avatar'
1299
+
1300
+ function AvatarBadges() {
1301
+ const t = useT()
1302
+ return (
1303
+ <div className="flex flex-wrap items-center gap-6 p-2">
1304
+ <Avatar label="Wei Chen" ariaLabel={t('design_system.gallery.examples.avatar.verified')} badge={<Check className="size-3" />} badgeClassName="bg-status-info-icon text-white" />
1305
+ <Avatar label="Laura Perez" ariaLabel={t('design_system.gallery.examples.avatar.pinned')} badge={<Pin className="size-3" />} badgeClassName="bg-accent-indigo text-white" />
1306
+ <Avatar label="Omar Haddad" ariaLabel={t('design_system.gallery.examples.avatar.favorite')} badge={<Star className="size-3" />} badgeClassName="bg-status-success-icon text-white" />
1307
+ <Avatar label="Ines Kowalska" ariaLabel={t('design_system.gallery.examples.avatar.add')} badge={<Plus className="size-3" />} />
1308
+ <Avatar label="Ravi Patel" ariaLabel={t('design_system.gallery.examples.avatar.remove')} badge={<X className="size-3" />} badgeClassName="bg-status-error-icon text-white" />
1309
+ <Avatar label="James Brown" ariaLabel={t('design_system.gallery.examples.avatar.notification')} status="error" statusPosition="top-right" />
1310
+ </div>
1311
+ )
1312
+ }`,
1313
+ },
1314
+ {
1315
+ id: 'company-badge',
1316
+ title: 'Company badge composition',
1317
+ render: () => (
1318
+ <Avatar
1319
+ label="Acme Corp"
1320
+ src={avatarPhotoSrc}
1321
+ size="lg"
1322
+ badge={<Building2 className="size-3" />}
1323
+ badgeClassName="top-auto bottom-0 translate-y-1/4"
1324
+ />
1325
+ ),
1326
+ code: `import { Building2 } from 'lucide-react'
1327
+ import { Avatar } from '@open-mercato/ui/primitives/avatar'
1328
+ import photo from './avatar-photo.png'
1329
+
1330
+ <Avatar label="Acme Corp" src={typeof photo === 'string' ? photo : photo.src} size="lg" badge={<Building2 className="size-3" />} badgeClassName="top-auto bottom-0 translate-y-1/4" />`,
1331
+ },
1332
+ {
1333
+ id: 'rings',
1334
+ title: 'Ring tones (code extension)',
1335
+ render: () => (
1336
+ <div className="flex flex-wrap gap-6 p-2">
1337
+ <Avatar label="Wei Chen" ring />
1338
+ <Avatar label="Laura Perez" ring="success" />
1339
+ <Avatar label="Omar Haddad" ring="warning" />
1340
+ <Avatar label="Ines Kowalska" ring="error" />
1341
+ <Avatar label="Ravi Patel" ring="muted" />
1342
+ </div>
1343
+ ),
1344
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1345
+
1346
+ <div className="flex flex-wrap gap-6 p-2">
1347
+ <Avatar label="Wei Chen" ring />
1348
+ <Avatar label="Laura Perez" ring="success" />
1349
+ <Avatar label="Omar Haddad" ring="warning" />
1350
+ <Avatar label="Ines Kowalska" ring="error" />
1351
+ <Avatar label="Ravi Patel" ring="muted" />
1352
+ </div>`,
1353
+ },
1354
+ {
1355
+ id: 'stack-sizes',
1356
+ title: 'AvatarStack sizes and full overflow counts',
1357
+ render: () => (
1358
+ <div className="grid gap-6">
1359
+ {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
1360
+ <AvatarStack key={size} size={size} max={3} overflowCount={12}>
1361
+ <Avatar label="Wei Chen" size={size} />
1362
+ <Avatar label="Laura Perez" size={size} />
1363
+ <Avatar label="Omar Haddad" size={size} />
1364
+ </AvatarStack>
1365
+ ))}
1366
+ </div>
1367
+ ),
1368
+ code: `import { Avatar, AvatarStack } from '@open-mercato/ui/primitives/avatar'
1369
+
1370
+ <div className="grid gap-6">
1371
+ {(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
1372
+ <AvatarStack key={size} size={size} max={3} overflowCount={12}>
1373
+ <Avatar label="Wei Chen" size={size} />
1374
+ <Avatar label="Laura Perez" size={size} />
1375
+ <Avatar label="Omar Haddad" size={size} />
1376
+ </AvatarStack>
1377
+ ))}
1378
+ </div>`,
317
1379
  },
318
1380
  {
319
1381
  id: 'stack',
@@ -339,7 +1401,6 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
339
1401
  },
340
1402
  ],
341
1403
  }
342
-
343
1404
  const kbdEntry: GalleryEntry = {
344
1405
  id: 'kbd',
345
1406
  title: 'Kbd',
@@ -377,54 +1438,34 @@ const kbdEntry: GalleryEntry = {
377
1438
  },
378
1439
  ],
379
1440
  }
380
-
381
1441
  const tableEntry: GalleryEntry = {
382
1442
  id: 'table',
383
1443
  title: 'Table',
384
1444
  importPath: '@open-mercato/ui/primitives/table',
385
1445
  figmaNodeId: '167144:147544',
386
1446
  variants: [
1447
+ {
1448
+ id: 'header-states',
1449
+ title: 'Header / default, disabled, empty and sorting',
1450
+ render: () => <TableHeaderExamples />,
1451
+ code: tableHeaderExampleCode,
1452
+ },
1453
+ {
1454
+ id: 'cells-48',
1455
+ title: 'Cell catalogue / 48px rows',
1456
+ render: () => <TableCellExamples rowHeight={48} />,
1457
+ code: tableCellExampleCode(48),
1458
+ },
1459
+ {
1460
+ id: 'cells-64',
1461
+ title: 'Cell catalogue / 64px rows',
1462
+ render: () => <TableCellExamples rowHeight={64} />,
1463
+ code: tableCellExampleCode(64),
1464
+ },
387
1465
  {
388
1466
  id: 'default',
389
1467
  title: 'default',
390
- render: () => (
391
- <Table>
392
- <TableHeader>
393
- <TableRow>
394
- <TableHead>Order</TableHead>
395
- <TableHead>Customer</TableHead>
396
- <TableHead>Status</TableHead>
397
- <TableHead className="text-right">Total</TableHead>
398
- </TableRow>
399
- </TableHeader>
400
- <TableBody>
401
- <TableRow>
402
- <TableCell>#1042</TableCell>
403
- <TableCell>Wei Chen</TableCell>
404
- <TableCell>
405
- <StatusBadge variant="success" dot>Paid</StatusBadge>
406
- </TableCell>
407
- <TableCell className="text-right">$1,250.00</TableCell>
408
- </TableRow>
409
- <TableRow>
410
- <TableCell>#1041</TableCell>
411
- <TableCell>Laura Perez</TableCell>
412
- <TableCell>
413
- <StatusBadge variant="warning" dot>Pending</StatusBadge>
414
- </TableCell>
415
- <TableCell className="text-right">$310.50</TableCell>
416
- </TableRow>
417
- <TableRow>
418
- <TableCell>#1040</TableCell>
419
- <TableCell>Omar Haddad</TableCell>
420
- <TableCell>
421
- <StatusBadge variant="neutral" dot>Draft</StatusBadge>
422
- </TableCell>
423
- <TableCell className="text-right">$89.00</TableCell>
424
- </TableRow>
425
- </TableBody>
426
- </Table>
427
- ),
1468
+ render: () => <TableEntryDefaultPreview />,
428
1469
  code: `import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@open-mercato/ui/primitives/table'
429
1470
  import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
430
1471
 
@@ -450,39 +1491,7 @@ import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
450
1491
  {
451
1492
  id: 'striped',
452
1493
  title: 'striped',
453
- render: () => (
454
- <Table variant="striped">
455
- <TableHeader>
456
- <TableRow>
457
- <TableHead>SKU</TableHead>
458
- <TableHead>Product</TableHead>
459
- <TableHead className="text-right">Stock</TableHead>
460
- </TableRow>
461
- </TableHeader>
462
- <TableBody>
463
- <TableRow>
464
- <TableCell>AP-100</TableCell>
465
- <TableCell>Apex Desk Lamp</TableCell>
466
- <TableCell className="text-right">120</TableCell>
467
- </TableRow>
468
- <TableRow>
469
- <TableCell>AP-101</TableCell>
470
- <TableCell>Apex Monitor Stand</TableCell>
471
- <TableCell className="text-right">64</TableCell>
472
- </TableRow>
473
- <TableRow>
474
- <TableCell>AP-102</TableCell>
475
- <TableCell>Apex Cable Kit</TableCell>
476
- <TableCell className="text-right">310</TableCell>
477
- </TableRow>
478
- <TableRow>
479
- <TableCell>AP-103</TableCell>
480
- <TableCell>Apex Laptop Riser</TableCell>
481
- <TableCell className="text-right">18</TableCell>
482
- </TableRow>
483
- </TableBody>
484
- </Table>
485
- ),
1494
+ render: () => <TableEntryStripedPreview />,
486
1495
  code: `import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@open-mercato/ui/primitives/table'
487
1496
 
488
1497
  <Table variant="striped">
@@ -499,32 +1508,7 @@ import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
499
1508
  {
500
1509
  id: 'with-footer',
501
1510
  title: 'With footer',
502
- render: () => (
503
- <Table>
504
- <TableHeader>
505
- <TableRow>
506
- <TableHead>Line</TableHead>
507
- <TableHead className="text-right">Amount</TableHead>
508
- </TableRow>
509
- </TableHeader>
510
- <TableBody>
511
- <TableRow>
512
- <TableCell>Subtotal</TableCell>
513
- <TableCell className="text-right">$1,560.50</TableCell>
514
- </TableRow>
515
- <TableRow>
516
- <TableCell>Shipping</TableCell>
517
- <TableCell className="text-right">$24.00</TableCell>
518
- </TableRow>
519
- </TableBody>
520
- <TableFooter>
521
- <TableRow>
522
- <TableCell>Total</TableCell>
523
- <TableCell className="text-right">$1,584.50</TableCell>
524
- </TableRow>
525
- </TableFooter>
526
- </Table>
527
- ),
1511
+ render: () => <TableEntryWithFooterPreview />,
528
1512
  code: `import { Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell } from '@open-mercato/ui/primitives/table'
529
1513
 
530
1514
  <Table>
@@ -540,7 +1524,6 @@ import { StatusBadge } from '@open-mercato/ui/primitives/status-badge'
540
1524
  },
541
1525
  ],
542
1526
  }
543
-
544
1527
  const cardEntry: GalleryEntry = {
545
1528
  id: 'card',
546
1529
  title: 'Card',
@@ -549,20 +1532,7 @@ const cardEntry: GalleryEntry = {
549
1532
  {
550
1533
  id: 'default',
551
1534
  title: 'default',
552
- render: () => (
553
- <Card className="w-full max-w-sm">
554
- <CardHeader>
555
- <CardTitle>Monthly revenue</CardTitle>
556
- <CardDescription>Net revenue across all channels.</CardDescription>
557
- </CardHeader>
558
- <CardContent>
559
- <p className="text-2xl font-semibold">$48,210</p>
560
- </CardContent>
561
- <CardFooter>
562
- <p className="text-sm text-muted-foreground">Updated 5 minutes ago</p>
563
- </CardFooter>
564
- </Card>
565
- ),
1535
+ render: () => <CardEntryDefaultPreview />,
566
1536
  code: `import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@open-mercato/ui/primitives/card'
567
1537
 
568
1538
  <Card>
@@ -581,87 +1551,226 @@ const cardEntry: GalleryEntry = {
581
1551
  {
582
1552
  id: 'with-action',
583
1553
  title: 'With action slot',
584
- render: () => (
585
- <Card className="w-full max-w-sm">
586
- <CardHeader>
587
- <CardTitle>Team members</CardTitle>
588
- <CardDescription>People with access to this workspace.</CardDescription>
589
- <CardAction>
590
- <IconButton variant="ghost" aria-label="More">
591
- <MoreHorizontal />
592
- </IconButton>
593
- </CardAction>
594
- </CardHeader>
595
- <CardContent>
596
- <AvatarStack max={3} size="sm">
597
- <Avatar label="Wei Chen" size="sm" />
598
- <Avatar label="Laura Perez" size="sm" />
599
- <Avatar label="Omar Haddad" size="sm" />
600
- <Avatar label="Ines Kowalska" size="sm" />
601
- </AvatarStack>
602
- </CardContent>
603
- </Card>
604
- ),
1554
+ render: () => <CardEntryWithActionPreview />,
605
1555
  code: `import { MoreHorizontal } from 'lucide-react'
606
1556
  import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent } from '@open-mercato/ui/primitives/card'
607
1557
  import { IconButton } from '@open-mercato/ui/primitives/icon-button'
1558
+ import { Avatar, AvatarStack } from '@open-mercato/ui/primitives/avatar'
608
1559
 
609
- <Card>
1560
+ <Card className="w-full max-w-sm">
610
1561
  <CardHeader>
611
1562
  <CardTitle>Team members</CardTitle>
612
1563
  <CardDescription>People with access to this workspace.</CardDescription>
613
1564
  <CardAction>
614
- <IconButton variant="ghost" aria-label="More"><MoreHorizontal /></IconButton>
1565
+ <IconButton type="button" variant="ghost" aria-label="More"><MoreHorizontal /></IconButton>
615
1566
  </CardAction>
616
1567
  </CardHeader>
617
- <CardContent>{/* content */}</CardContent>
1568
+ <CardContent>
1569
+ <AvatarStack max={3} size="sm">
1570
+ <Avatar label="Wei Chen" size="sm" />
1571
+ <Avatar label="Laura Perez" size="sm" />
1572
+ <Avatar label="Omar Haddad" size="sm" />
1573
+ <Avatar label="Ines Kowalska" size="sm" />
1574
+ </AvatarStack>
1575
+ </CardContent>
618
1576
  </Card>`,
619
1577
  },
620
1578
  ],
621
1579
  }
622
-
623
1580
  const separatorEntry: GalleryEntry = {
624
1581
  id: 'separator',
625
1582
  title: 'Separator',
626
1583
  importPath: '@open-mercato/ui/primitives/separator',
1584
+ figmaNodeId: '414:4401',
1585
+ usage: {
1586
+ do: [
1587
+ 'The nine Figma Content Divider layouts are represented: line, line spacing, text and line, text only, solid text, icon button, icon button group, text button, and text button group.',
1588
+ 'Place action buttons between two flexible Separator rules with gap-2.5. ButtonGroup supplies joined borders; do not place interactive controls inside a separator role.',
1589
+ 'Vertical, dashed, and label-alignment examples expose the existing code API beyond the nine Figma layouts.',
1590
+ 'Compositions use production tokens and responsive width. The labeled primitive remains 12/16 px; the audited Figma text-and-line label is 11/12 px.',
1591
+ ],
1592
+ },
627
1593
  variants: [
628
1594
  {
629
1595
  id: 'default',
630
1596
  title: 'default',
1597
+ render: () => <SeparatorEntryDefaultPreview />,
1598
+ code: `import { Separator } from '@open-mercato/ui/primitives/separator'
1599
+
1600
+ <Separator className="my-3" />`,
1601
+ },
1602
+ {
1603
+ id: 'line-spacing',
1604
+ title: 'Line Spacing',
631
1605
  render: () => (
632
- <div className="w-full max-w-sm">
633
- <p className="text-sm">Shipping details</p>
634
- <Separator className="my-3" />
635
- <p className="text-sm text-muted-foreground">Billing details</p>
1606
+ <div className="flex h-1 w-full items-center">
1607
+ <Separator />
636
1608
  </div>
637
1609
  ),
638
1610
  code: `import { Separator } from '@open-mercato/ui/primitives/separator'
639
1611
 
640
- <Separator className="my-3" />`,
1612
+ <div className="flex h-1 w-full items-center"><Separator /></div>`,
641
1613
  },
642
1614
  {
643
1615
  id: 'labeled',
644
1616
  title: 'Labeled',
645
- render: () => (
646
- <div className="w-full max-w-sm">
647
- <Separator label="OR" />
648
- </div>
649
- ),
1617
+ render: () => <SeparatorEntryLabeledPreview />,
650
1618
  code: `import { Separator } from '@open-mercato/ui/primitives/separator'
651
1619
 
652
1620
  <Separator label="OR" />`,
1621
+ },
1622
+ {
1623
+ id: 'text-divider',
1624
+ title: 'Text Divider',
1625
+ render: () => <SeparatorTextDemo kind="text" />,
1626
+ code: `import { useT } from '@open-mercato/shared/lib/i18n/context'
1627
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1628
+
1629
+ function TextDivider() {
1630
+ const t = useT()
1631
+ return <Separator section label={t('design_system.gallery.examples.separator.or')} className="bg-transparent px-2 py-1" />
1632
+ }`,
1633
+ },
1634
+ {
1635
+ id: 'label-alignments',
1636
+ title: 'Label alignments (code extension)',
1637
+ render: () => <SeparatorTextDemo kind="label-alignments" />,
1638
+ code: `import { useT } from '@open-mercato/shared/lib/i18n/context'
1639
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1640
+
1641
+ function LabelAlignments() {
1642
+ const t = useT()
1643
+ return (
1644
+ <div className="grid w-full gap-6">
1645
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="start" />
1646
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="center" />
1647
+ <Separator label={t('design_system.gallery.examples.separator.or')} labelAlign="end" />
1648
+ </div>
1649
+ )
1650
+ }`,
653
1651
  },
654
1652
  {
655
1653
  id: 'section',
656
1654
  title: 'Section header',
657
1655
  render: () => (
658
1656
  <div className="w-full max-w-sm">
659
- <Separator section label={'Amount & account'} />
1657
+ <Separator section label={'Amount & account'} className="px-5" />
660
1658
  </div>
661
1659
  ),
662
1660
  code: `import { Separator } from '@open-mercato/ui/primitives/separator'
663
1661
 
664
- <Separator section label="Amount & account" />`,
1662
+ <Separator section label="Amount & account" className="px-5" />`,
1663
+ },
1664
+ {
1665
+ id: 'icon-button',
1666
+ title: 'Icon Button',
1667
+ render: () => <SeparatorActionDemo kind="icon" />,
1668
+ code: `import { Plus } from 'lucide-react'
1669
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1670
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
1671
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1672
+
1673
+ function IconDivider() {
1674
+ const t = useT()
1675
+ return (
1676
+ <div className="flex w-full items-center gap-2.5">
1677
+ <Separator className="min-w-0 flex-1" />
1678
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.add')}><Plus className="size-5" /></IconButton>
1679
+ <Separator className="min-w-0 flex-1" />
1680
+ </div>
1681
+ )
1682
+ }`,
1683
+ },
1684
+ {
1685
+ id: 'icon-button-group',
1686
+ title: 'Icon Button Group',
1687
+ render: () => <SeparatorActionDemo kind="icon-group" />,
1688
+ code: `import { ChevronLeft, Plus, ChevronRight } from 'lucide-react'
1689
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1690
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
1691
+ import { ButtonGroup } from '@open-mercato/ui/primitives/button-group'
1692
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1693
+
1694
+ function IconGroupDivider() {
1695
+ const t = useT()
1696
+ return (
1697
+ <div className="flex w-full items-center gap-2.5">
1698
+ <Separator className="min-w-0 flex-1" />
1699
+ <ButtonGroup aria-label={t('design_system.gallery.examples.separator.actions')}>
1700
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.previous')}><ChevronLeft className="size-5" /></IconButton>
1701
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.add')}><Plus className="size-5" /></IconButton>
1702
+ <IconButton size="default" aria-label={t('design_system.gallery.examples.separator.next')}><ChevronRight className="size-5" /></IconButton>
1703
+ </ButtonGroup>
1704
+ <Separator className="min-w-0 flex-1" />
1705
+ </div>
1706
+ )
1707
+ }`,
1708
+ },
1709
+ {
1710
+ id: 'text-button',
1711
+ title: 'Text Button',
1712
+ render: () => <SeparatorActionDemo kind="text" />,
1713
+ code: `import { useT } from '@open-mercato/shared/lib/i18n/context'
1714
+ import { Button } from '@open-mercato/ui/primitives/button'
1715
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1716
+
1717
+ function TextButtonDivider() {
1718
+ const t = useT()
1719
+ return (
1720
+ <div className="flex w-full items-center gap-2.5">
1721
+ <Separator className="min-w-0 flex-1" />
1722
+ <Button type="button" size="sm" variant="outline" className="px-2.5">{t('design_system.gallery.examples.separator.add')}</Button>
1723
+ <Separator className="min-w-0 flex-1" />
1724
+ </div>
1725
+ )
1726
+ }`,
1727
+ },
1728
+ {
1729
+ id: 'text-button-group',
1730
+ title: 'Text Button Group',
1731
+ render: () => <SeparatorActionDemo kind="text-group" />,
1732
+ code: `import { useT } from '@open-mercato/shared/lib/i18n/context'
1733
+ import { Button } from '@open-mercato/ui/primitives/button'
1734
+ import { ButtonGroup } from '@open-mercato/ui/primitives/button-group'
1735
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1736
+
1737
+ function TextGroupDivider() {
1738
+ const t = useT()
1739
+ return (
1740
+ <div className="flex w-full items-center gap-2.5">
1741
+ <Separator className="min-w-0 flex-1" />
1742
+ <ButtonGroup size="sm" aria-label={t('design_system.gallery.examples.separator.actions')}>
1743
+ <Button type="button" size="sm" variant="outline" className="px-3.5">{t('design_system.gallery.examples.separator.previous')}</Button>
1744
+ <Button type="button" size="sm" variant="outline" className="px-3.5">{t('design_system.gallery.examples.separator.add')}</Button>
1745
+ <Button type="button" size="sm" variant="outline" className="px-3.5">{t('design_system.gallery.examples.separator.next')}</Button>
1746
+ </ButtonGroup>
1747
+ <Separator className="min-w-0 flex-1" />
1748
+ </div>
1749
+ )
1750
+ }`,
1751
+ },
1752
+ {
1753
+ id: 'vertical',
1754
+ title: 'Vertical (code extension)',
1755
+ render: () => (
1756
+ <div className="flex h-16 items-center gap-6">
1757
+ <Avatar label="Wei Chen" />
1758
+ <Separator orientation="vertical" />
1759
+ <Avatar label="Laura Perez" />
1760
+ <Separator orientation="vertical" variant="dashed" />
1761
+ <Avatar label="Omar Haddad" />
1762
+ </div>
1763
+ ),
1764
+ code: `import { Avatar } from '@open-mercato/ui/primitives/avatar'
1765
+ import { Separator } from '@open-mercato/ui/primitives/separator'
1766
+
1767
+ <div className="flex h-16 items-center gap-6">
1768
+ <Avatar label="Wei Chen" />
1769
+ <Separator orientation="vertical" />
1770
+ <Avatar label="Laura Perez" />
1771
+ <Separator orientation="vertical" variant="dashed" />
1772
+ <Avatar label="Omar Haddad" />
1773
+ </div>`,
665
1774
  },
666
1775
  {
667
1776
  id: 'dashed',
@@ -677,26 +1786,156 @@ const separatorEntry: GalleryEntry = {
677
1786
  },
678
1787
  ],
679
1788
  }
680
-
1789
+ function FigmaScrollDemo({
1790
+ size,
1791
+ variant,
1792
+ horizontal = false,
1793
+ }: {
1794
+ size: 'md' | 'sm' | 'xs'
1795
+ variant: 'default' | 'lighter'
1796
+ horizontal?: boolean
1797
+ }) {
1798
+ const t = useT()
1799
+ return (
1800
+ <ScrollArea
1801
+ type="always"
1802
+ scrollbarSize={size}
1803
+ scrollbarVariant={variant}
1804
+ scrollbars={horizontal ? 'horizontal' : 'vertical'}
1805
+ className="h-60 w-full max-w-xs rounded-md border border-border"
1806
+ >
1807
+ <div className={horizontal ? 'flex w-max gap-4 p-6' : 'flex flex-col gap-2 p-4 pr-8'}>
1808
+ {Array.from(
1809
+ {
1810
+ length: 20,
1811
+ },
1812
+ (_, index) => (
1813
+ <p key={index} className="whitespace-nowrap text-sm">
1814
+ {t('design_system.gallery.samples.scroll.row', {
1815
+ number: index + 1,
1816
+ })}
1817
+ </p>
1818
+ ),
1819
+ )}
1820
+ </div>
1821
+ </ScrollArea>
1822
+ )
1823
+ }
681
1824
  const scrollAreaEntry: GalleryEntry = {
682
1825
  id: 'scroll-area',
683
1826
  title: 'ScrollArea',
684
1827
  importPath: '@open-mercato/ui/primitives/scroll-area',
1828
+ figmaNodeId: '166941:61889',
685
1829
  variants: [
1830
+ {
1831
+ id: 'default-md',
1832
+ title: 'default / Medium',
1833
+ render: () => <FigmaScrollDemo size="md" variant="default" />,
1834
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1835
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1836
+
1837
+ const t = useT()
1838
+
1839
+ <ScrollArea type="always" scrollbarSize="md" scrollbarVariant="default" className="h-60 w-full max-w-xs rounded-md border border-border">
1840
+ <div className="flex flex-col gap-2 p-4 pr-8">
1841
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1842
+ </div>
1843
+ </ScrollArea>`,
1844
+ },
1845
+ {
1846
+ id: 'default-sm',
1847
+ title: 'default / Small',
1848
+ render: () => <FigmaScrollDemo size="sm" variant="default" />,
1849
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1850
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1851
+
1852
+ const t = useT()
1853
+
1854
+ <ScrollArea type="always" scrollbarSize="sm" scrollbarVariant="default" className="h-60 w-full max-w-xs rounded-md border border-border">
1855
+ <div className="flex flex-col gap-2 p-4 pr-8">
1856
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1857
+ </div>
1858
+ </ScrollArea>`,
1859
+ },
1860
+ {
1861
+ id: 'default-xs',
1862
+ title: 'default / X-Small',
1863
+ render: () => <FigmaScrollDemo size="xs" variant="default" />,
1864
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1865
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1866
+
1867
+ const t = useT()
1868
+
1869
+ <ScrollArea type="always" scrollbarSize="xs" scrollbarVariant="default" className="h-60 w-full max-w-xs rounded-md border border-border">
1870
+ <div className="flex flex-col gap-2 p-4 pr-8">
1871
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1872
+ </div>
1873
+ </ScrollArea>`,
1874
+ },
1875
+ {
1876
+ id: 'lighter-md',
1877
+ title: 'lighter / Medium',
1878
+ render: () => <FigmaScrollDemo size="md" variant="lighter" />,
1879
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1880
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1881
+
1882
+ const t = useT()
1883
+
1884
+ <ScrollArea type="always" scrollbarSize="md" scrollbarVariant="lighter" className="h-60 w-full max-w-xs rounded-md border border-border">
1885
+ <div className="flex flex-col gap-2 p-4 pr-8">
1886
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1887
+ </div>
1888
+ </ScrollArea>`,
1889
+ },
1890
+ {
1891
+ id: 'lighter-sm',
1892
+ title: 'lighter / Small',
1893
+ render: () => <FigmaScrollDemo size="sm" variant="lighter" />,
1894
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1895
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1896
+
1897
+ const t = useT()
1898
+
1899
+ <ScrollArea type="always" scrollbarSize="sm" scrollbarVariant="lighter" className="h-60 w-full max-w-xs rounded-md border border-border">
1900
+ <div className="flex flex-col gap-2 p-4 pr-8">
1901
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1902
+ </div>
1903
+ </ScrollArea>`,
1904
+ },
1905
+ {
1906
+ id: 'lighter-xs',
1907
+ title: 'lighter / X-Small',
1908
+ render: () => <FigmaScrollDemo size="xs" variant="lighter" />,
1909
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1910
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1911
+
1912
+ const t = useT()
1913
+
1914
+ <ScrollArea type="always" scrollbarSize="xs" scrollbarVariant="lighter" className="h-60 w-full max-w-xs rounded-md border border-border">
1915
+ <div className="flex flex-col gap-2 p-4 pr-8">
1916
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1917
+ </div>
1918
+ </ScrollArea>`,
1919
+ },
1920
+ {
1921
+ id: 'horizontal-figma',
1922
+ title: 'Horizontal / Lighter / Medium',
1923
+ render: () => <FigmaScrollDemo size="md" variant="lighter" horizontal />,
1924
+ code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
1925
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
1926
+
1927
+ const t = useT()
1928
+
1929
+ <ScrollArea type="always" scrollbarSize="md" scrollbarVariant="lighter" scrollbars="horizontal" className="h-60 w-full max-w-xs rounded-md border border-border">
1930
+ <div className="flex w-max gap-4 p-6">
1931
+ {Array.from({ length: 20 }, (_, index) => <p key={index} className="whitespace-nowrap text-sm">{t('design_system.gallery.samples.scroll.row', { number: index + 1 })}</p>)}
1932
+ </div>
1933
+ </ScrollArea>`,
1934
+ },
686
1935
  {
687
1936
  id: 'vertical',
688
1937
  title: 'Vertical',
689
- render: () => (
690
- <ScrollArea className="h-40 w-full max-w-xs rounded-md border">
691
- <div className="p-3">
692
- {Array.from({ length: 20 }, (_, i) => (
693
- <p key={i} className="border-b py-1.5 text-sm last:border-b-0">
694
- Warehouse zone {String.fromCharCode(65 + (i % 6))}-{i + 1}
695
- </p>
696
- ))}
697
- </div>
698
- </ScrollArea>
699
- ),
1938
+ render: () => <ScrollAreaEntryVerticalPreview />,
700
1939
  code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
701
1940
 
702
1941
  <ScrollArea className="h-40 rounded-md border">
@@ -710,17 +1949,7 @@ const scrollAreaEntry: GalleryEntry = {
710
1949
  {
711
1950
  id: 'horizontal',
712
1951
  title: 'Horizontal',
713
- render: () => (
714
- <ScrollArea scrollbars="horizontal" className="w-full max-w-xs rounded-md border">
715
- <div className="flex w-max gap-2 p-3">
716
- {Array.from({ length: 12 }, (_, i) => (
717
- <Tag key={i} variant="neutral" shape="square">
718
- Channel {i + 1}
719
- </Tag>
720
- ))}
721
- </div>
722
- </ScrollArea>
723
- ),
1952
+ render: () => <ScrollAreaEntryHorizontalPreview />,
724
1953
  code: `import { ScrollArea } from '@open-mercato/ui/primitives/scroll-area'
725
1954
  import { Tag } from '@open-mercato/ui/primitives/tag'
726
1955
 
@@ -734,42 +1963,22 @@ import { Tag } from '@open-mercato/ui/primitives/tag'
734
1963
  },
735
1964
  ],
736
1965
  }
737
-
738
1966
  const activityFeedEntry: GalleryEntry = {
739
1967
  id: 'activity-feed',
1968
+ figmaNodeId: '166035:46833',
740
1969
  title: 'ActivityFeed',
741
1970
  importPath: '@open-mercato/ui/primitives/activity-feed',
742
1971
  variants: [
1972
+ {
1973
+ id: 'source-composition',
1974
+ title: '5 entry types / filter / actions',
1975
+ render: () => <ActivityFeedExample />,
1976
+ code: activityFeedExampleCode,
1977
+ },
743
1978
  {
744
1979
  id: 'basic',
745
1980
  title: 'Basic entries',
746
- render: () => (
747
- <ActivityFeed className="w-full max-w-md">
748
- <ActivityFeedItem
749
- avatar={<Avatar label="Wei Chen" size="sm" />}
750
- title={
751
- <>
752
- Wei Chen <span className="font-normal text-muted-foreground">created</span> Order #1042
753
- </>
754
- }
755
- timestamp="4 min ago"
756
- />
757
- <ActivityFeedItem
758
- avatar={<Avatar label="Laura Perez" size="sm" />}
759
- title={
760
- <>
761
- Laura Perez <span className="font-normal text-muted-foreground">updated the shipping address</span>
762
- </>
763
- }
764
- timestamp="1 hour ago"
765
- actions={
766
- <IconButton variant="ghost" size="sm" aria-label="More">
767
- <MoreHorizontal />
768
- </IconButton>
769
- }
770
- />
771
- </ActivityFeed>
772
- ),
1981
+ render: () => <ActivityFeedEntryBasicPreview />,
773
1982
  code: `import { ActivityFeed, ActivityFeedItem } from '@open-mercato/ui/primitives/activity-feed'
774
1983
  import { Avatar } from '@open-mercato/ui/primitives/avatar'
775
1984
 
@@ -784,21 +1993,7 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
784
1993
  {
785
1994
  id: 'with-attachment',
786
1995
  title: 'File attachment',
787
- render: () => (
788
- <ActivityFeed className="w-full max-w-md">
789
- <ActivityFeedItem
790
- avatar={<Avatar label="Omar Haddad" size="sm" />}
791
- title={
792
- <>
793
- Omar Haddad <span className="font-normal text-muted-foreground">uploaded</span> Q2 financial report
794
- </>
795
- }
796
- timestamp="2 days ago"
797
- >
798
- <ActivityFeedFileChip name="apex-report.pdf" size="4mb" onDownload={() => {}} />
799
- </ActivityFeedItem>
800
- </ActivityFeed>
801
- ),
1996
+ render: () => <ActivityFeedEntryWithAttachmentPreview />,
802
1997
  code: `import { ActivityFeed, ActivityFeedItem, ActivityFeedFileChip } from '@open-mercato/ui/primitives/activity-feed'
803
1998
  import { Avatar } from '@open-mercato/ui/primitives/avatar'
804
1999
 
@@ -813,23 +2008,7 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
813
2008
  {
814
2009
  id: 'with-comment',
815
2010
  title: 'Comment',
816
- render: () => (
817
- <ActivityFeed className="w-full max-w-md">
818
- <ActivityFeedItem
819
- avatar={<Avatar label="Ines Kowalska" size="sm" />}
820
- title={
821
- <>
822
- Ines Kowalska <span className="font-normal text-muted-foreground">commented</span>
823
- </>
824
- }
825
- timestamp="6 days ago"
826
- >
827
- <ActivityFeedComment onReply={() => {}}>
828
- Please revise the risk metrics before Friday.
829
- </ActivityFeedComment>
830
- </ActivityFeedItem>
831
- </ActivityFeed>
832
- ),
2011
+ render: () => <ActivityFeedEntryWithCommentPreview />,
833
2012
  code: `import { ActivityFeed, ActivityFeedItem, ActivityFeedComment } from '@open-mercato/ui/primitives/activity-feed'
834
2013
  import { Avatar } from '@open-mercato/ui/primitives/avatar'
835
2014
 
@@ -846,23 +2025,7 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
846
2025
  {
847
2026
  id: 'status-chips',
848
2027
  title: 'Status chips',
849
- render: () => (
850
- <ActivityFeed className="w-full max-w-md">
851
- <ActivityFeedItem
852
- avatar={<Avatar label="Ravi Patel" size="sm" />}
853
- title={
854
- <>
855
- Ravi Patel <span className="font-normal text-muted-foreground">moved 3 tasks</span>
856
- </>
857
- }
858
- timestamp="1 week ago"
859
- >
860
- <ActivityFeedStatusChip status="success">Approved</ActivityFeedStatusChip>
861
- <ActivityFeedStatusChip status="warning">Needs review</ActivityFeedStatusChip>
862
- <ActivityFeedStatusChip status="error">Blocked</ActivityFeedStatusChip>
863
- </ActivityFeedItem>
864
- </ActivityFeed>
865
- ),
2028
+ render: () => <ActivityFeedEntryStatusChipsPreview />,
866
2029
  code: `import { ActivityFeed, ActivityFeedItem, ActivityFeedStatusChip } from '@open-mercato/ui/primitives/activity-feed'
867
2030
  import { Avatar } from '@open-mercato/ui/primitives/avatar'
868
2031
 
@@ -878,8 +2041,217 @@ import { Avatar } from '@open-mercato/ui/primitives/avatar'
878
2041
  },
879
2042
  ],
880
2043
  }
881
-
2044
+ const content_labelEntry: GalleryEntry = {
2045
+ id: 'content-label',
2046
+ title: 'ContentLabel',
2047
+ importPath: '@open-mercato/ui/primitives/content-label',
2048
+ figmaNodeId: '2945:5539',
2049
+ descriptionKey: 'design_system.entries.content-label.description',
2050
+ variants: [
2051
+ {
2052
+ id: 'basic-40',
2053
+ title: 'basic-40',
2054
+ render: () => <ContentLabelExample kind="basic" size={40} />,
2055
+ code: keyComponentExampleCode('<ContentLabelExample kind="basic" size={40} />'),
2056
+ },
2057
+ {
2058
+ id: 'icon-40',
2059
+ title: 'icon-40',
2060
+ render: () => <ContentLabelExample kind="icon" size={40} />,
2061
+ code: keyComponentExampleCode('<ContentLabelExample kind="icon" size={40} />'),
2062
+ },
2063
+ {
2064
+ id: 'avatar-40',
2065
+ title: 'avatar-40',
2066
+ render: () => <ContentLabelExample kind="avatar" size={40} />,
2067
+ code: keyComponentExampleCode('<ContentLabelExample kind="avatar" size={40} />'),
2068
+ },
2069
+ {
2070
+ id: 'brand-40',
2071
+ title: 'brand-40',
2072
+ render: () => <ContentLabelExample kind="brand" size={40} />,
2073
+ code: keyComponentExampleCode('<ContentLabelExample kind="brand" size={40} />'),
2074
+ },
2075
+ {
2076
+ id: 'company-40',
2077
+ title: 'company-40',
2078
+ render: () => <ContentLabelExample kind="company" size={40} />,
2079
+ code: keyComponentExampleCode('<ContentLabelExample kind="company" size={40} />'),
2080
+ },
2081
+ {
2082
+ id: 'basic-48',
2083
+ title: 'basic-48',
2084
+ render: () => <ContentLabelExample kind="basic" size={48} />,
2085
+ code: keyComponentExampleCode('<ContentLabelExample kind="basic" size={48} />'),
2086
+ },
2087
+ {
2088
+ id: 'icon-48',
2089
+ title: 'icon-48',
2090
+ render: () => <ContentLabelExample kind="icon" size={48} />,
2091
+ code: keyComponentExampleCode('<ContentLabelExample kind="icon" size={48} />'),
2092
+ },
2093
+ {
2094
+ id: 'avatar-48',
2095
+ title: 'avatar-48',
2096
+ render: () => <ContentLabelExample kind="avatar" size={48} />,
2097
+ code: keyComponentExampleCode('<ContentLabelExample kind="avatar" size={48} />'),
2098
+ },
2099
+ {
2100
+ id: 'brand-48',
2101
+ title: 'brand-48',
2102
+ render: () => <ContentLabelExample kind="brand" size={48} />,
2103
+ code: keyComponentExampleCode('<ContentLabelExample kind="brand" size={48} />'),
2104
+ },
2105
+ {
2106
+ id: 'company-48',
2107
+ title: 'company-48',
2108
+ render: () => <ContentLabelExample kind="company" size={48} />,
2109
+ code: keyComponentExampleCode('<ContentLabelExample kind="company" size={48} />'),
2110
+ },
2111
+ {
2112
+ id: 'options',
2113
+ title: 'options',
2114
+ render: () => <ContentLabelExample kind="icon" size={48} configurable />,
2115
+ code: keyComponentExampleCode('<ContentLabelExample kind="icon" size={48} configurable />'),
2116
+ },
2117
+ ],
2118
+ }
2119
+ const content_cardEntry: GalleryEntry = {
2120
+ id: 'content-card',
2121
+ title: 'ContentCard',
2122
+ importPath: '@open-mercato/ui/primitives/content-card',
2123
+ figmaNodeId: '2942:9503',
2124
+ descriptionKey: 'design_system.entries.content-card.description',
2125
+ variants: [
2126
+ {
2127
+ id: 'basic',
2128
+ title: 'basic',
2129
+ render: () => <ContentCardExample kind="basic" />,
2130
+ code: keyComponentExampleCode('<ContentCardExample kind="basic" />'),
2131
+ },
2132
+ {
2133
+ id: 'icon',
2134
+ title: 'icon',
2135
+ render: () => <ContentCardExample kind="icon" />,
2136
+ code: keyComponentExampleCode('<ContentCardExample kind="icon" />'),
2137
+ },
2138
+ {
2139
+ id: 'avatar',
2140
+ title: 'avatar',
2141
+ render: () => <ContentCardExample kind="avatar" />,
2142
+ code: keyComponentExampleCode('<ContentCardExample kind="avatar" />'),
2143
+ },
2144
+ {
2145
+ id: 'provider',
2146
+ title: 'provider',
2147
+ render: () => <ContentCardExample kind="provider" />,
2148
+ code: keyComponentExampleCode('<ContentCardExample kind="provider" />'),
2149
+ },
2150
+ {
2151
+ id: 'brand',
2152
+ title: 'brand',
2153
+ render: () => <ContentCardExample kind="brand" />,
2154
+ code: keyComponentExampleCode('<ContentCardExample kind="brand" />'),
2155
+ },
2156
+ {
2157
+ id: 'company',
2158
+ title: 'company',
2159
+ render: () => <ContentCardExample kind="company" />,
2160
+ code: keyComponentExampleCode('<ContentCardExample kind="company" />'),
2161
+ },
2162
+ {
2163
+ id: 'disabled',
2164
+ title: 'disabled',
2165
+ render: () => <ContentCardExample kind="icon" disabled />,
2166
+ code: keyComponentExampleCode('<ContentCardExample kind="icon" disabled />'),
2167
+ },
2168
+ ],
2169
+ }
2170
+ const key_iconEntry: GalleryEntry = {
2171
+ id: 'key-icon',
2172
+ title: 'KeyIcon',
2173
+ importPath: '@open-mercato/ui/primitives/key-icon',
2174
+ figmaNodeId: '263:1850',
2175
+ descriptionKey: 'design_system.entries.key-icon.description',
2176
+ variants: [
2177
+ {
2178
+ id: 'stroke',
2179
+ title: 'stroke',
2180
+ render: () => <KeyIconExamples />,
2181
+ code: keyComponentExampleCode('<KeyIconExamples />'),
2182
+ },
2183
+ {
2184
+ id: 'lighter',
2185
+ title: 'lighter',
2186
+ render: () => <KeyIconExamples appearance="lighter" />,
2187
+ code: keyComponentExampleCode('<KeyIconExamples appearance="lighter" />'),
2188
+ },
2189
+ ],
2190
+ }
2191
+ const payment_iconEntry: GalleryEntry = {
2192
+ id: 'payment-icon',
2193
+ title: 'PaymentIcon',
2194
+ importPath: '@open-mercato/ui/primitives/payment-icon',
2195
+ figmaNodeId: '2942:9995',
2196
+ descriptionKey: 'design_system.entries.payment-icon.description',
2197
+ variants: [
2198
+ {
2199
+ id: 'categories',
2200
+ title: 'categories',
2201
+ render: () => <PaymentIconExamples />,
2202
+ code: keyComponentExampleCode('<PaymentIconExamples />'),
2203
+ },
2204
+ ],
2205
+ }
2206
+ const chart_legendEntry: GalleryEntry = {
2207
+ id: 'chart-legend',
2208
+ title: 'ChartLegend',
2209
+ importPath: '@open-mercato/ui/primitives/chart-legend',
2210
+ figmaNodeId: '2942:9934',
2211
+ descriptionKey: 'design_system.entries.chart-legend.description',
2212
+ variants: [
2213
+ {
2214
+ id: 'colors',
2215
+ title: 'colors',
2216
+ render: () => <ChartLegendExamples />,
2217
+ code: keyComponentExampleCode('<ChartLegendExamples />'),
2218
+ },
2219
+ {
2220
+ id: 'interactive',
2221
+ title: 'interactive',
2222
+ render: () => <ChartLegendExamples interactive />,
2223
+ code: keyComponentExampleCode('<ChartLegendExamples interactive />'),
2224
+ },
2225
+ ],
2226
+ }
2227
+ const chart_legend_dotEntry: GalleryEntry = {
2228
+ id: 'chart-legend-dot',
2229
+ title: 'ChartLegendDot',
2230
+ importPath: '@open-mercato/ui/primitives/chart-legend',
2231
+ figmaNodeId: '2942:9880',
2232
+ descriptionKey: 'design_system.entries.chart-legend-dot.description',
2233
+ variants: [
2234
+ {
2235
+ id: 'size-16',
2236
+ title: 'size-16',
2237
+ render: () => <ChartLegendDotExamples />,
2238
+ code: keyComponentExampleCode('<ChartLegendDotExamples />'),
2239
+ },
2240
+ {
2241
+ id: 'size-20',
2242
+ title: 'size-20',
2243
+ render: () => <ChartLegendDotExamples size={20} />,
2244
+ code: keyComponentExampleCode('<ChartLegendDotExamples size={20} />'),
2245
+ },
2246
+ ],
2247
+ }
882
2248
  export const entries: GalleryEntry[] = [
2249
+ content_labelEntry,
2250
+ content_cardEntry,
2251
+ key_iconEntry,
2252
+ payment_iconEntry,
2253
+ chart_legendEntry,
2254
+ chart_legend_dotEntry,
883
2255
  badgeEntry,
884
2256
  statusBadgeEntry,
885
2257
  tagEntry,