@flamingo-stack/openframe-frontend-core 0.0.703 → 0.0.704-snapshot.20261006133653

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 (336) hide show
  1. package/dist/{chunk-3L7KCOGO.cjs → chunk-2QEUFXNS.cjs} +30 -30
  2. package/dist/{chunk-BMJUKS6S.cjs → chunk-3256UJXS.cjs} +47 -47
  3. package/dist/{chunk-GZYLZ4MB.js → chunk-4S7TJYRQ.js} +3 -3
  4. package/dist/{chunk-ENGBNKUJ.js → chunk-5EFZO5EB.js} +675 -569
  5. package/dist/{chunk-TCZCMD5Q.js → chunk-5HBHO5TB.js} +1 -1
  6. package/dist/{chunk-BOUPNYUV.js → chunk-64HOMVYC.js} +5 -5
  7. package/dist/{chunk-YR6JPJF4.js → chunk-6XIF2Z7I.js} +4 -4
  8. package/dist/{chunk-NU724ZVN.cjs → chunk-7GHB2IK6.cjs} +121 -121
  9. package/dist/{chunk-GX3OUTFO.cjs → chunk-7ZYIC7NA.cjs} +69 -55
  10. package/dist/{chunk-53AC23ZN.js → chunk-A6WVQKOZ.js} +24 -24
  11. package/dist/{chunk-4OGAXAEG.cjs → chunk-ABU3TGXA.cjs} +3 -3
  12. package/dist/{chunk-RTXTGLGB.cjs → chunk-ACV4DFQ3.cjs} +4 -4
  13. package/dist/{chunk-RLDAYA2A.cjs → chunk-BH6PJP66.cjs} +29 -29
  14. package/dist/{chunk-BRXOGCH3.cjs → chunk-BIZNSF3U.cjs} +3 -3
  15. package/dist/{chunk-2A4XES7R.cjs → chunk-BM5MVGH3.cjs} +3 -3
  16. package/dist/{chunk-6YCXA7CN.js → chunk-CH5232HV.js} +20 -19
  17. package/dist/{chunk-UIBSSVON.cjs → chunk-D7BTSVMS.cjs} +2 -2
  18. package/dist/{chunk-YBGEPKC2.cjs → chunk-F7Y2ZS5U.cjs} +6 -6
  19. package/dist/{chunk-5V6O73EH.js → chunk-FLKJYMVB.js} +3 -3
  20. package/dist/{chunk-NMGX2ZTU.js → chunk-IFUQVZF4.js} +17 -17
  21. package/dist/{chunk-2NE3DNXY.js → chunk-IKCQK67U.js} +2 -2
  22. package/dist/{chunk-KFDP3DUL.cjs → chunk-IXPUM3AW.cjs} +98 -98
  23. package/dist/{chunk-QGTDWFT6.js → chunk-IZHZMBIX.js} +2469 -1928
  24. package/dist/{chunk-67CXGPTW.cjs → chunk-JKEEFQOX.cjs} +505 -72
  25. package/dist/{chunk-NYSYSKSH.cjs → chunk-M6HTJTFH.cjs} +15 -15
  26. package/dist/{chunk-OGLCD3UL.js → chunk-MFFCUVWG.js} +6 -6
  27. package/dist/{chunk-KJ5LWATV.js → chunk-MKXO4Q5P.js} +7 -7
  28. package/dist/{chunk-EMCQGFXD.cjs → chunk-MMOODW57.cjs} +28 -27
  29. package/dist/{chunk-Q76ZTHNV.js → chunk-MP2C3LJ4.js} +1 -1
  30. package/dist/{chunk-J4K5JOLI.js → chunk-MV4HYG3B.js} +25 -11
  31. package/dist/{chunk-2T6QWNXU.js → chunk-NDESEPW5.js} +99 -11
  32. package/dist/{chunk-HHFPQNP3.js → chunk-NJDHFC55.js} +15 -15
  33. package/dist/{chunk-HUOLB7ZN.cjs → chunk-OHFS7VOU.cjs} +9 -9
  34. package/dist/{chunk-7632TNE7.js → chunk-OSNIZNVH.js} +7 -7
  35. package/dist/{chunk-UTW4SQDI.js → chunk-OUHMD6EU.js} +10 -10
  36. package/dist/{chunk-MXHJROXJ.cjs → chunk-P23CRLU4.cjs} +1245 -1139
  37. package/dist/{chunk-64O4L7WN.js → chunk-PDWVPI3S.js} +11 -55
  38. package/dist/{chunk-DAW6TDZB.js → chunk-PFC2HWQA.js} +30 -16
  39. package/dist/{chunk-G55W76S6.js → chunk-POZ7F77D.js} +12 -13
  40. package/dist/{chunk-PJP5SMOU.js → chunk-PPEZGUL7.js} +500 -67
  41. package/dist/{chunk-SFGXIFYO.cjs → chunk-QC7Q3XCE.cjs} +24 -24
  42. package/dist/{chunk-MDBHZBW7.cjs → chunk-RKV5B7EU.cjs} +92 -4
  43. package/dist/{chunk-5VPIC5MD.cjs → chunk-SAAZEWUR.cjs} +12 -12
  44. package/dist/{chunk-IIMICN7L.cjs → chunk-TYWLNCNH.cjs} +4 -48
  45. package/dist/{chunk-HYLIQMZH.cjs → chunk-UBP5RNGK.cjs} +33 -33
  46. package/dist/{chunk-HUMWQMCU.js → chunk-UT4YHQZW.js} +3 -3
  47. package/dist/{chunk-BSEIEWM5.cjs → chunk-V3H26CNS.cjs} +28 -14
  48. package/dist/{chunk-NGJCWEYX.cjs → chunk-VHCACDKP.cjs} +46 -46
  49. package/dist/{chunk-SL2FOFT2.js → chunk-VMAZCLX4.js} +7 -7
  50. package/dist/{chunk-5FFNNJM7.js → chunk-VR2ZLFCP.js} +1 -1
  51. package/dist/{chunk-NCTYD7HL.js → chunk-VYWMEL5F.js} +14 -14
  52. package/dist/{chunk-HY5YL3U5.cjs → chunk-XBWE423R.cjs} +1994 -1453
  53. package/dist/{chunk-XCIFHW4E.cjs → chunk-XOYH2YQE.cjs} +2 -2
  54. package/dist/{chunk-S6V7A5FS.cjs → chunk-ZQZFIE2K.cjs} +32 -33
  55. package/dist/components/case-studies/index.cjs +24 -24
  56. package/dist/components/case-studies/index.js +10 -10
  57. package/dist/components/chat/chat-archive-page.d.ts +3 -3
  58. package/dist/components/chat/chat-archive-page.d.ts.map +1 -1
  59. package/dist/components/chat/chat-input.d.ts.map +1 -1
  60. package/dist/components/chat/chat-nav-sidebar.d.ts +4 -0
  61. package/dist/components/chat/chat-nav-sidebar.d.ts.map +1 -1
  62. package/dist/components/chat/chat-panel-header.d.ts +3 -2
  63. package/dist/components/chat/chat-panel-header.d.ts.map +1 -1
  64. package/dist/components/chat/embeddable-chat.d.ts +36 -2
  65. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  66. package/dist/components/chat/index.cjs +14 -6
  67. package/dist/components/chat/index.d.ts +4 -1
  68. package/dist/components/chat/index.d.ts.map +1 -1
  69. package/dist/components/chat/index.js +13 -5
  70. package/dist/components/chat/mingo-archive-list.d.ts +17 -0
  71. package/dist/components/chat/mingo-archive-list.d.ts.map +1 -0
  72. package/dist/components/chat/mingo-chat-header.d.ts +31 -0
  73. package/dist/components/chat/mingo-chat-header.d.ts.map +1 -0
  74. package/dist/components/chat/mingo-chat-rail.d.ts +54 -0
  75. package/dist/components/chat/mingo-chat-rail.d.ts.map +1 -0
  76. package/dist/components/chat/model-display.d.ts.map +1 -1
  77. package/dist/components/contact/contact-form.d.ts.map +1 -1
  78. package/dist/components/contact/index.cjs +11 -11
  79. package/dist/components/contact/index.js +10 -10
  80. package/dist/components/content-loading-container.d.ts +1 -1
  81. package/dist/components/content-loading-container.d.ts.map +1 -1
  82. package/dist/components/docs/index.cjs +14 -14
  83. package/dist/components/docs/index.js +13 -13
  84. package/dist/components/docs/skeletons.d.ts.map +1 -1
  85. package/dist/components/embeds/index.cjs +11 -11
  86. package/dist/components/embeds/index.js +10 -10
  87. package/dist/components/faq/index.cjs +12 -12
  88. package/dist/components/faq/index.js +11 -11
  89. package/dist/components/features/figma-prototype-viewer.d.ts.map +1 -1
  90. package/dist/components/features/index.cjs +10 -10
  91. package/dist/components/features/index.js +9 -9
  92. package/dist/components/features/media-gallery-manager.d.ts.map +1 -1
  93. package/dist/components/features/parallax-image-showcase.d.ts.map +1 -1
  94. package/dist/components/features/policy-configuration-panel.d.ts.map +1 -1
  95. package/dist/components/features/section-selector.d.ts.map +1 -1
  96. package/dist/components/help-center-pages/index.cjs +119 -119
  97. package/dist/components/help-center-pages/index.js +39 -39
  98. package/dist/components/help-center-pages/trust-center-sections.d.ts +2 -2
  99. package/dist/components/help-center-pages/trust-center-sections.d.ts.map +1 -1
  100. package/dist/components/index.cjs +94 -86
  101. package/dist/components/index.js +32 -24
  102. package/dist/components/layout/article-detail-layout.d.ts +1 -1
  103. package/dist/components/layout/article-detail-layout.d.ts.map +1 -1
  104. package/dist/components/layout/page-container.d.ts.map +1 -1
  105. package/dist/components/layout/title-block.d.ts +2 -2
  106. package/dist/components/layout/title-block.d.ts.map +1 -1
  107. package/dist/components/loading/page-layout-skeleton.d.ts.map +1 -1
  108. package/dist/components/loading/unified-skeleton.d.ts.map +1 -1
  109. package/dist/components/meeting-scheduler/booking-form.d.ts +4 -4
  110. package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
  111. package/dist/components/meeting-scheduler/context-panel.d.ts.map +1 -1
  112. package/dist/components/meeting-scheduler/index.cjs +127 -127
  113. package/dist/components/meeting-scheduler/index.d.ts +2 -2
  114. package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
  115. package/dist/components/meeting-scheduler/index.js +50 -50
  116. package/dist/components/navigation/app-header.d.ts +4 -0
  117. package/dist/components/navigation/app-header.d.ts.map +1 -1
  118. package/dist/components/navigation/app-layout-side-panel.d.ts +142 -0
  119. package/dist/components/navigation/app-layout-side-panel.d.ts.map +1 -0
  120. package/dist/components/navigation/app-layout.d.ts +11 -1
  121. package/dist/components/navigation/app-layout.d.ts.map +1 -1
  122. package/dist/components/navigation/header-mingo-button.d.ts +4 -1
  123. package/dist/components/navigation/header-mingo-button.d.ts.map +1 -1
  124. package/dist/components/navigation/index.cjs +13 -13
  125. package/dist/components/navigation/index.d.ts +1 -0
  126. package/dist/components/navigation/index.d.ts.map +1 -1
  127. package/dist/components/navigation/index.js +12 -12
  128. package/dist/components/navigation/navigation-sidebar.d.ts +8 -1
  129. package/dist/components/navigation/navigation-sidebar.d.ts.map +1 -1
  130. package/dist/components/navigation/sliding-sidebar.d.ts.map +1 -1
  131. package/dist/components/onboarding-guides/index.cjs +14 -14
  132. package/dist/components/onboarding-guides/index.js +13 -13
  133. package/dist/components/persistent-filter-controls.d.ts.map +1 -1
  134. package/dist/components/related-content/index.cjs +7 -7
  135. package/dist/components/related-content/index.js +6 -6
  136. package/dist/components/shared/detail-page-skeleton.d.ts.map +1 -1
  137. package/dist/components/tickets/help-center-create-form.d.ts +4 -4
  138. package/dist/components/tickets/index.cjs +15 -15
  139. package/dist/components/tickets/index.js +14 -14
  140. package/dist/components/ui/announcement-bar-view.d.ts.map +1 -1
  141. package/dist/components/ui/breadcrumb.d.ts.map +1 -1
  142. package/dist/components/ui/checkbox-block.d.ts.map +1 -1
  143. package/dist/components/ui/dashboard-info-card.d.ts +1 -1
  144. package/dist/components/ui/dashboard-info-card.d.ts.map +1 -1
  145. package/dist/components/ui/data-table/data-table-body.d.ts +2 -2
  146. package/dist/components/ui/data-table/data-table-skeleton.d.ts +2 -2
  147. package/dist/components/ui/data-table/data-table-skeleton.d.ts.map +1 -1
  148. package/dist/components/ui/data-table/utils.d.ts +2 -2
  149. package/dist/components/ui/dialog.d.ts.map +1 -1
  150. package/dist/components/ui/drawer.d.ts.map +1 -1
  151. package/dist/components/ui/entity-image.d.ts +2 -2
  152. package/dist/components/ui/file-manager/index.cjs +36 -36
  153. package/dist/components/ui/file-manager/index.js +3 -3
  154. package/dist/components/ui/filter-modal.d.ts.map +1 -1
  155. package/dist/components/ui/index.cjs +18 -10
  156. package/dist/components/ui/index.js +17 -9
  157. package/dist/components/ui/info-card-row.d.ts.map +1 -1
  158. package/dist/components/ui/menubar.d.ts +1 -1
  159. package/dist/components/ui/menubar.d.ts.map +1 -1
  160. package/dist/components/ui/modal-v2.d.ts.map +1 -1
  161. package/dist/components/ui/modal.d.ts.map +1 -1
  162. package/dist/components/ui/no-data/no-data-actions.d.ts.map +1 -1
  163. package/dist/components/ui/no-data/no-data-styles.d.ts +1 -1
  164. package/dist/components/ui/no-data/no-data-styles.d.ts.map +1 -1
  165. package/dist/components/ui/page-actions.d.ts.map +1 -1
  166. package/dist/components/ui/sheet.d.ts.map +1 -1
  167. package/dist/components/ui/table/table-skeleton.d.ts +1 -1
  168. package/dist/components/ui/table/table-skeleton.d.ts.map +1 -1
  169. package/dist/hooks/index.cjs +23 -9
  170. package/dist/hooks/index.js +24 -10
  171. package/dist/hooks/ui/index.d.ts +1 -0
  172. package/dist/hooks/ui/index.d.ts.map +1 -1
  173. package/dist/hooks/ui/use-content-breakpoint.d.ts +32 -0
  174. package/dist/hooks/ui/use-content-breakpoint.d.ts.map +1 -0
  175. package/dist/hooks/ui/use-isomorphic-layout-effect.d.ts +2 -2
  176. package/dist/hooks/ui/use-isomorphic-layout-effect.d.ts.map +1 -1
  177. package/dist/hooks/ui/use-media-query.d.ts.map +1 -1
  178. package/dist/index.cjs +39 -17
  179. package/dist/index.js +41 -19
  180. package/dist/styles/layout-steps.d.ts +30 -0
  181. package/dist/styles/layout-steps.d.ts.map +1 -0
  182. package/dist/tailwind.config.cjs +36 -11
  183. package/dist/tailwind.config.js +36 -11
  184. package/eslint-config/README.md +9 -0
  185. package/eslint-config/base.js +17 -1
  186. package/eslint-config/layout-variants.js +57 -0
  187. package/package.json +3 -1
  188. package/src/ODS_TOKEN_RULES.md +40 -0
  189. package/src/components/chat/chat-archive-page.tsx +9 -7
  190. package/src/components/chat/chat-input.tsx +5 -1
  191. package/src/components/chat/chat-nav-sidebar.tsx +10 -4
  192. package/src/components/chat/chat-panel-header.tsx +8 -5
  193. package/src/components/chat/embeddable-chat.tsx +675 -485
  194. package/src/components/chat/index.ts +4 -0
  195. package/src/components/chat/mingo-archive-list.tsx +108 -0
  196. package/src/components/chat/mingo-chat-header.tsx +104 -0
  197. package/src/components/chat/mingo-chat-rail.tsx +361 -0
  198. package/src/components/chat/model-display.tsx +8 -1
  199. package/src/components/contact/contact-form.tsx +11 -9
  200. package/src/components/content-loading-container.tsx +4 -2
  201. package/src/components/docs/doc-viewer.tsx +7 -7
  202. package/src/components/docs/skeletons.tsx +7 -4
  203. package/src/components/dynamic-skeleton.tsx +1 -1
  204. package/src/components/embeds/claude-embed.tsx +1 -1
  205. package/src/components/embeds/embed-viewer-frame.tsx +4 -4
  206. package/src/components/embeds/figma-embed.tsx +2 -2
  207. package/src/components/embeds/google-sheets-viewer.tsx +1 -1
  208. package/src/components/embeds/pdf-viewer.tsx +3 -3
  209. package/src/components/empty-state.tsx +6 -6
  210. package/src/components/faq/faq-section.tsx +2 -2
  211. package/src/components/faq-accordion.tsx +1 -1
  212. package/src/components/features/board/board-column-header.tsx +1 -1
  213. package/src/components/features/command-box.tsx +3 -3
  214. package/src/components/features/entity-video-section.tsx +2 -2
  215. package/src/components/features/figma-prototype-viewer.tsx +4 -1
  216. package/src/components/features/media-gallery-manager.tsx +3 -1
  217. package/src/components/features/parallax-image-showcase.tsx +9 -6
  218. package/src/components/features/policy-configuration-panel.tsx +9 -7
  219. package/src/components/features/provider-button.tsx +1 -1
  220. package/src/components/features/section-selector.tsx +11 -6
  221. package/src/components/features/select-button.tsx +4 -4
  222. package/src/components/features/seo-editor-preview.tsx +2 -2
  223. package/src/components/features/video-ratio-tabs.tsx +3 -3
  224. package/src/components/features/waitlist-form.tsx +1 -1
  225. package/src/components/help-center-pages/trust-center-page.tsx +1 -1
  226. package/src/components/help-center-pages/trust-center-sections.tsx +14 -14
  227. package/src/components/icon-display.tsx +1 -1
  228. package/src/components/layout/article-detail-layout.tsx +4 -2
  229. package/src/components/layout/list-page-layout.tsx +2 -2
  230. package/src/components/layout/page-container.tsx +26 -14
  231. package/src/components/layout/page-heading.tsx +1 -1
  232. package/src/components/layout/page-layout.tsx +1 -1
  233. package/src/components/layout/title-block.tsx +13 -13
  234. package/src/components/loading/card-skeleton.tsx +11 -11
  235. package/src/components/loading/category-vendor-selector-skeleton.tsx +1 -1
  236. package/src/components/loading/content-skeleton.tsx +6 -6
  237. package/src/components/loading/device-card-skeleton.tsx +1 -1
  238. package/src/components/loading/margin-report-skeleton.tsx +7 -7
  239. package/src/components/loading/msp-profile-form-skeleton.tsx +3 -3
  240. package/src/components/loading/organization-card-skeleton.tsx +2 -2
  241. package/src/components/loading/page-layout-skeleton.tsx +80 -68
  242. package/src/components/loading/unified-skeleton.tsx +16 -6
  243. package/src/components/media-carousel.tsx +3 -3
  244. package/src/components/meeting-scheduler/booking-form.tsx +9 -8
  245. package/src/components/meeting-scheduler/context-panel.tsx +8 -6
  246. package/src/components/meeting-scheduler/directory.tsx +4 -4
  247. package/src/components/meeting-scheduler/index.tsx +15 -15
  248. package/src/components/meeting-scheduler/slot-picker.tsx +12 -12
  249. package/src/components/navigation/app-header.tsx +6 -0
  250. package/src/components/navigation/app-layout-side-panel.tsx +594 -0
  251. package/src/components/navigation/app-layout.tsx +69 -4
  252. package/src/components/navigation/header-mingo-button.tsx +13 -3
  253. package/src/components/navigation/index.ts +5 -0
  254. package/src/components/navigation/navigation-sidebar.tsx +17 -3
  255. package/src/components/navigation/sliding-sidebar.tsx +2 -1
  256. package/src/components/pagination.tsx +3 -3
  257. package/src/components/persistent-filter-controls.tsx +6 -2
  258. package/src/components/platform/ScriptArguments.tsx +1 -1
  259. package/src/components/platform/ScriptInfoSection.tsx +4 -4
  260. package/src/components/platform/SoftwareSourceBadge.tsx +1 -1
  261. package/src/components/shared/article-author-byline.tsx +1 -1
  262. package/src/components/shared/delivery/delivery-lists.tsx +2 -2
  263. package/src/components/shared/delivery/delivery-row.tsx +7 -7
  264. package/src/components/shared/delivery/delivery-table.tsx +3 -3
  265. package/src/components/shared/detail-page-skeleton.tsx +11 -5
  266. package/src/components/shared/dev-section/dev-card-row.tsx +6 -6
  267. package/src/components/shared/dev-section/dev-section-view.tsx +1 -1
  268. package/src/components/shared/product-release/product-release-card-skeleton.tsx +8 -8
  269. package/src/components/shared/product-release/product-release-card.tsx +9 -9
  270. package/src/components/shared/product-release/product-releases-view.tsx +1 -1
  271. package/src/components/shared/product-release/release-detail-page.tsx +5 -5
  272. package/src/components/shared/roadmap/roadmap-grid-skeleton.tsx +1 -1
  273. package/src/components/shared/roadmap/roadmap-grid.tsx +3 -3
  274. package/src/components/tickets/help-center-card.tsx +1 -1
  275. package/src/components/tickets/help-center-create-form.tsx +12 -12
  276. package/src/components/ui/announcement-bar-view.tsx +2 -10
  277. package/src/components/ui/benefit-card.tsx +18 -18
  278. package/src/components/ui/brand-association-grid.tsx +4 -4
  279. package/src/components/ui/breadcrumb.tsx +4 -1
  280. package/src/components/ui/card.tsx +1 -1
  281. package/src/components/ui/checkbox-block.tsx +9 -7
  282. package/src/components/ui/content-loader.tsx +3 -3
  283. package/src/components/ui/cursor-pagination.tsx +3 -3
  284. package/src/components/ui/dashboard-info-card.tsx +13 -9
  285. package/src/components/ui/data-attribution.tsx +2 -2
  286. package/src/components/ui/data-table/data-table-body.tsx +2 -2
  287. package/src/components/ui/data-table/data-table-header.tsx +15 -15
  288. package/src/components/ui/data-table/data-table-skeleton.tsx +6 -6
  289. package/src/components/ui/data-table/utils.ts +5 -5
  290. package/src/components/ui/dialog.tsx +4 -1
  291. package/src/components/ui/drawer.tsx +2 -1
  292. package/src/components/ui/duration-input.tsx +1 -1
  293. package/src/components/ui/entity-image.tsx +3 -3
  294. package/src/components/ui/feature-card.tsx +10 -10
  295. package/src/components/ui/file-manager/file-manager-action-bar.tsx +1 -1
  296. package/src/components/ui/file-manager/file-manager.tsx +1 -1
  297. package/src/components/ui/filter-modal.tsx +8 -1
  298. package/src/components/ui/highlight-card.tsx +7 -7
  299. package/src/components/ui/info-card-row.tsx +10 -6
  300. package/src/components/ui/modal-v2.tsx +7 -2
  301. package/src/components/ui/modal.tsx +3 -2
  302. package/src/components/ui/no-data/no-data-actions.tsx +10 -4
  303. package/src/components/ui/no-data/no-data-styles.ts +1 -1
  304. package/src/components/ui/no-data/no-data.tsx +1 -1
  305. package/src/components/ui/organization-card.tsx +1 -1
  306. package/src/components/ui/page-actions.tsx +34 -5
  307. package/src/components/ui/progress-bar.tsx +2 -2
  308. package/src/components/ui/query-report-table/query-report-table.tsx +1 -1
  309. package/src/components/ui/search-input.tsx +2 -2
  310. package/src/components/ui/service-card.tsx +2 -2
  311. package/src/components/ui/sheet.tsx +2 -1
  312. package/src/components/ui/skeleton.tsx +3 -3
  313. package/src/components/ui/stacked-rows-panel.tsx +4 -4
  314. package/src/components/ui/tab-navigation.tsx +2 -2
  315. package/src/components/ui/tab-selector.tsx +2 -2
  316. package/src/components/ui/table/table-header.tsx +3 -3
  317. package/src/components/ui/table/table-skeleton.tsx +3 -3
  318. package/src/components/ui/table/utils.ts +5 -5
  319. package/src/components/ui/tag-search-input.tsx +3 -3
  320. package/src/components/ui/tags-manager.tsx +5 -5
  321. package/src/components/ui/test-run.tsx +2 -2
  322. package/src/components/ui/ticket-info-section.tsx +1 -1
  323. package/src/components/ui/ticket-notes-section.tsx +1 -1
  324. package/src/components/ui/ticket-status-config-row.tsx +15 -15
  325. package/src/hooks/ui/index.ts +1 -0
  326. package/src/hooks/ui/use-content-breakpoint.ts +58 -0
  327. package/src/hooks/ui/use-media-query.ts +3 -2
  328. package/src/styles/app-globals.css +13 -0
  329. package/src/styles/index.css +2 -0
  330. package/src/styles/layout-steps.ts +14 -0
  331. package/src/styles/ods-colors.css +15 -0
  332. package/src/styles/ods-content-area-tokens.css +27 -0
  333. package/src/styles/ods-content-area.css +31 -0
  334. package/src/styles/ods-effects.css +4 -2
  335. package/src/styles/ods-responsive-tokens.css +14 -4
  336. package/tailwind.config.ts +42 -7
@@ -65,7 +65,7 @@ export interface RoadmapGridSkeletonProps {
65
65
 
66
66
  export function RoadmapGridSkeleton({ count = 4, showLeftMargin = true }: RoadmapGridSkeletonProps) {
67
67
  return (
68
- <div className={`grid grid-cols-1 gap-6 md:grid-cols-2 ${showLeftMargin ? 'md:ml-[120px]' : ''}`}>
68
+ <div className={`grid grid-cols-1 gap-6 content-md:grid-cols-2 ${showLeftMargin ? 'content-md:ml-[120px]' : ''}`}>
69
69
  {Array.from({ length: count }).map((_, i) => (
70
70
  <RoadmapCardSkeleton key={i} />
71
71
  ))}
@@ -141,11 +141,11 @@ function RoadmapGridSingle({
141
141
  votingTasks: Set<string>;
142
142
  }) {
143
143
  return (
144
- // LITERAL class strings: an interpolated `md:grid-cols-${n}` is invisible
144
+ // LITERAL class strings: an interpolated `content-md:grid-cols-${n}` is invisible
145
145
  // to Tailwind's scanner and is never generated.
146
146
  <div
147
- className={`grid grid-cols-1 gap-6 ${columns === 2 ? 'md:grid-cols-2' : ''} ${
148
- showLeftMargin ? 'md:ml-[120px]' : ''
147
+ className={`grid grid-cols-1 gap-6 ${columns === 2 ? 'content-md:grid-cols-2' : ''} ${
148
+ showLeftMargin ? 'content-md:ml-[120px]' : ''
149
149
  }`}
150
150
  >
151
151
  {items.map(item => (
@@ -161,7 +161,7 @@ export function HelpCenterCard({
161
161
  disabled={!isExpandable}
162
162
  aria-expanded={isExpandable ? isExpanded : undefined}
163
163
  aria-controls={isExpanded ? `help-center-drawer-${ticket.id}` : undefined}
164
- className="w-full p-[12px] text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-accent disabled:cursor-default md:p-[16px]"
164
+ className="w-full p-[12px] text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-accent disabled:cursor-default content-md:p-[16px]"
165
165
  >
166
166
  <DevCardRowContent
167
167
  title={title}
@@ -71,16 +71,16 @@ export interface HelpCenterCreateFormProps {
71
71
  * content swaps an `<Input>` / `<Textarea>` / `<Button>` for a
72
72
  * same-sized animated `bg-ods-border` bar.
73
73
  *
74
- * wrapper → `p-6 md:p-8 lg:p-10` + border + rounded-3xl
75
- * heading area → 56px (`mb-6 md:mb-8` container, h-10 inner bar
76
- * + `mb-3 md:mb-4` = 40 + 16)
74
+ * wrapper → `p-6 content-md:p-8 content-lg:p-10` + border + rounded-3xl
75
+ * heading area → 56px (`mb-6 content-md:mb-8` container, h-10 inner bar
76
+ * + `mb-3 content-md:mb-4` = 40 + 16)
77
77
  * subject section → 79px (`h-[27px]` label + `mb-1` (4px) + h-12
78
78
  * input = 27 + 4 + 48)
79
79
  * message section → 127px (`h-[27px]` label + `mb-1` + h-24
80
80
  * textarea = 27 + 4 + 96)
81
81
  * attachments row → 28px (h-7 add button + helper label)
82
82
  * footer → 56px (h-12 button + `pt-2 mt-auto`)
83
- * between sections → `space-y-4 md:space-y-6` (16/24px)
83
+ * between sections → `space-y-4 content-md:space-y-6` (16/24px)
84
84
  *
85
85
  * One non-obvious detail: the real `<ContactForm>` renders 4
86
86
  * `<input type="hidden">` registrations BEFORE the visible Subject
@@ -93,15 +93,15 @@ export interface HelpCenterCreateFormProps {
93
93
  */
94
94
  export function HelpCenterCreateFormSkeleton() {
95
95
  return (
96
- <div className="flex h-full flex-col rounded-2xl border border-ods-border p-6 md:rounded-3xl md:p-8 lg:p-10">
97
- {/* Heading container — mirrors `mb-6 md:mb-8` + h2 with its own
98
- `mb-3 md:mb-4` and `text-h2` height (32px font, line-height
96
+ <div className="flex h-full flex-col rounded-2xl border border-ods-border p-6 content-md:rounded-3xl content-md:p-8 content-lg:p-10">
97
+ {/* Heading container — mirrors `mb-6 content-md:mb-8` + h2 with its own
98
+ `mb-3 content-md:mb-4` and `text-h2` height (32px font, line-height
99
99
  ~1.25 → 40px). h-10 bar matches the rendered h2 height. */}
100
- <div className="mb-6 md:mb-8">
101
- <div className="mb-3 h-10 w-72 animate-pulse rounded bg-ods-border md:mb-4" />
100
+ <div className="mb-6 content-md:mb-8">
101
+ <div className="mb-3 h-10 w-72 animate-pulse rounded bg-ods-border content-md:mb-4" />
102
102
  </div>
103
103
 
104
- {/* Form body — same `space-y-4 md:space-y-6` gap stack.
104
+ {/* Form body — same `space-y-4 content-md:space-y-6` gap stack.
105
105
  IMPORTANT: the real `<ContactForm>` prepends 4
106
106
  `<input type="hidden">` registrations for the hidden
107
107
  name/email/helpCategory/message fields (see contact-form.tsx).
@@ -112,7 +112,7 @@ export function HelpCenterCreateFormSkeleton() {
112
112
  same 4 hidden inputs so the Subject placeholder lands at the
113
113
  same Y as the real Subject input. Removing them would shift
114
114
  the whole stack up by 24px on every page load. */}
115
- <div className="flex flex-grow flex-col space-y-4 md:space-y-6">
115
+ <div className="flex flex-grow flex-col space-y-4 content-md:space-y-6">
116
116
  <input type="hidden" aria-hidden />
117
117
  <input type="hidden" aria-hidden />
118
118
  <input type="hidden" aria-hidden />
@@ -152,7 +152,7 @@ export function HelpCenterCreateFormSkeleton() {
152
152
  {/* Footer — same `pt-2 mt-auto` so it sticks to the bottom.
153
153
  Button bar is h-12 to match the real `<Button>` height
154
154
  (48px). */}
155
- <div className="mt-auto flex w-full flex-col items-center justify-end gap-4 pt-2 md:flex-row md:gap-6">
155
+ <div className="mt-auto flex w-full flex-col items-center justify-end gap-4 pt-2 content-md:flex-row content-md:gap-6">
156
156
  <div className="h-4 w-72 animate-pulse rounded bg-ods-border" />
157
157
  <div className="h-12 w-32 animate-pulse rounded bg-ods-border" />
158
158
  </div>
@@ -1,17 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import type { CSSProperties, ReactElement, ReactNode } from 'react';
4
+ import { breakpoints } from '../../hooks/ui/use-media-query';
4
5
  import { cn } from '../../utils/cn';
5
6
 
6
- /**
7
- * Mirrors `screens.md` in tailwind.config.ts (800px), which is also where the
8
- * ODS responsive tokens step up (ods-responsive-tokens.css). ONE breakpoint
9
- * for the whole bar: the `md:` variants below and the `onContentClick` guard
10
- * must never disagree (they did before — the guard read a stale 768px while
11
- * the CSS switched at 800px).
12
- */
13
- const MD_QUERY = '(min-width: 800px)';
14
-
15
7
  export interface AnnouncementBarViewProps {
16
8
  /**
17
9
  * Leading slot — typically an icon, at content width before the title. Size
@@ -92,7 +84,7 @@ export function AnnouncementBarView({
92
84
  }: AnnouncementBarViewProps) {
93
85
  const handleContentClick = onContentClick
94
86
  ? () => {
95
- if (!window.matchMedia(MD_QUERY).matches) onContentClick();
87
+ if (!window.matchMedia(breakpoints.md).matches) onContentClick();
96
88
  }
97
89
  : undefined;
98
90
 
@@ -26,9 +26,9 @@ export const BenefitCard: React.FC<BenefitCardProps> = ({
26
26
  const variantStyles = {
27
27
  default: {
28
28
  container:
29
- 'gap-[var(--spacing-system-xsf)] bg-ods-bg p-[var(--spacing-system-xsf)] md:p-[var(--spacing-system-mf)]',
30
- title: 'font-body font-bold text-body-md md:text-body-lg text-ods-text-primary',
31
- description: 'font-body font-medium text-body-sm md:text-body-md text-ods-text-secondary',
29
+ 'gap-[var(--spacing-system-xsf)] bg-ods-bg p-[var(--spacing-system-xsf)] content-md:p-[var(--spacing-system-mf)]',
30
+ title: 'font-body font-bold text-body-md content-md:text-body-lg text-ods-text-primary',
31
+ description: 'font-body font-medium text-body-sm content-md:text-body-md text-ods-text-secondary',
32
32
  },
33
33
  dark: {
34
34
  container: 'gap-[var(--spacing-system-xsf)] bg-transparent p-0 shadow-[0px_48px_80px_0px_rgba(0,0,0,0.24)]',
@@ -78,15 +78,15 @@ export function benefitCardBorderClass(
78
78
  const isLastInRow = (index + 1) % 4 === 0;
79
79
  const isInLastRow = index >= totalItems - 4;
80
80
  return cn(
81
- !isLastInRow && 'border-ods-border md:border-r',
82
- !isInLastRow && 'border-b md:border-b lg:border-b-0',
83
- index < 2 && 'lg:border-b-0',
81
+ !isLastInRow && 'border-ods-border content-md:border-r',
82
+ !isInLastRow && 'border-b content-md:border-b content-lg:border-b-0',
83
+ index < 2 && 'content-lg:border-b-0',
84
84
  );
85
85
  } else if (columns === 3) {
86
86
  // 3 columns lay out 1-up / 2-up / 3-up, so the row a card sits in
87
87
  // differs per breakpoint and a single rule cannot describe it. The
88
88
  // old shared 2-3 branch assumed one row and, at `md` (grid-cols-2),
89
- // gave card 1 a trailing `md:border-r` while suppressing the divider
89
+ // gave card 1 a trailing `content-md:border-r` while suppressing the divider
90
90
  // between the two rows.
91
91
  const isLastInMdRow = (index + 1) % 2 === 0;
92
92
  const isInLastMdRow = index >= totalItems - (totalItems % 2 === 0 ? 2 : 1);
@@ -95,17 +95,17 @@ export function benefitCardBorderClass(
95
95
  return cn(
96
96
  'border-ods-border',
97
97
  !isLastItem && 'border-b',
98
- isInLastMdRow && 'md:border-b-0',
99
- !isLastInMdRow && !isLastItem && 'md:border-r',
100
- isLastInMdRow && 'md:border-r-0',
101
- isInLastLgRow && 'lg:border-b-0',
102
- !isInLastMdRow && !isInLastLgRow && 'lg:border-b',
103
- !isLastInLgRow && !isLastItem && 'lg:border-r',
104
- isLastInLgRow && 'lg:border-r-0',
98
+ isInLastMdRow && 'content-md:border-b-0',
99
+ !isLastInMdRow && !isLastItem && 'content-md:border-r',
100
+ isLastInMdRow && 'content-md:border-r-0',
101
+ isInLastLgRow && 'content-lg:border-b-0',
102
+ !isInLastMdRow && !isInLastLgRow && 'content-lg:border-b',
103
+ !isLastInLgRow && !isLastItem && 'content-lg:border-r',
104
+ isLastInLgRow && 'content-lg:border-r-0',
105
105
  );
106
106
  } else {
107
107
  // 2 columns: a flex row, so one rule genuinely does describe it.
108
- return isLastItem ? 'border-b-0' : 'border-b md:border-b-0 md:border-r border-ods-border';
108
+ return isLastItem ? 'border-b-0' : 'border-b content-md:border-b-0 content-md:border-r border-ods-border';
109
109
  }
110
110
  }
111
111
 
@@ -114,10 +114,10 @@ export const BenefitCardGrid: React.FC<BenefitCardGridProps> = ({ children, clas
114
114
 
115
115
  const gridClass =
116
116
  columns === 4
117
- ? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4'
117
+ ? 'grid grid-cols-1 content-md:grid-cols-2 content-lg:grid-cols-4'
118
118
  : columns === 3
119
- ? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
120
- : 'flex flex-col md:flex-row';
119
+ ? 'grid grid-cols-1 content-md:grid-cols-2 content-lg:grid-cols-3'
120
+ : 'flex flex-col content-md:flex-row';
121
121
 
122
122
  return (
123
123
  <div
@@ -15,7 +15,7 @@ export function BrandAssociationGrid({
15
15
  className = '',
16
16
  cardClassName = 'bg-ods-card border border-ods-border rounded-lg p-0 overflow-hidden',
17
17
  }: BrandAssociationGridProps) {
18
- const gridCols = columns === 2 ? 'grid-cols-1 md:grid-cols-2' : 'grid-cols-1 md:grid-cols-3';
18
+ const gridCols = columns === 2 ? 'grid-cols-1 content-md:grid-cols-2' : 'grid-cols-1 content-md:grid-cols-3';
19
19
  const itemsPerRow = columns;
20
20
  const rows = Math.ceil(items.length / itemsPerRow);
21
21
 
@@ -26,7 +26,7 @@ export function BrandAssociationGrid({
26
26
  if (!isLastInRow) {
27
27
  // On mobile (1 column), never show right border
28
28
  // On desktop (2/3 columns), show right border except for last in row
29
- classes += ' md:border-r border-ods-border';
29
+ classes += ' content-md:border-r border-ods-border';
30
30
  }
31
31
 
32
32
  // Bottom border logic
@@ -39,10 +39,10 @@ export function BrandAssociationGrid({
39
39
 
40
40
  // Desktop: override mobile border, show bottom border for all rows except last
41
41
  if (!isLastRow) {
42
- classes += ' md:border-b border-ods-border';
42
+ classes += ' content-md:border-b border-ods-border';
43
43
  } else {
44
44
  // Last row on desktop - remove bottom border
45
- classes += ' md:border-b-0';
45
+ classes += ' content-md:border-b-0';
46
46
  }
47
47
 
48
48
  return classes;
@@ -17,7 +17,10 @@ Breadcrumb.displayName = 'Breadcrumb';
17
17
  const BreadcrumbList = forwardRef<HTMLOListElement, ComponentPropsWithoutRef<'ol'>>(({ className, ...props }, ref) => (
18
18
  <ol
19
19
  ref={ref}
20
- className={cn('flex flex-wrap items-center gap-1.5 break-words text-ods-text-muted text-h6 md:gap-2.5', className)}
20
+ className={cn(
21
+ 'flex flex-wrap items-center gap-1.5 break-words text-ods-text-muted text-h6 content-md:gap-2.5',
22
+ className,
23
+ )}
21
24
  {...props}
22
25
  />
23
26
  ));
@@ -57,7 +57,7 @@ export function CardHorizontal({ icon, title, description, className = '', borde
57
57
  return (
58
58
  <div
59
59
  className={cn(
60
- 'flex min-h-[80px] w-full flex-row items-center gap-3 bg-ods-card p-4 md:gap-4 md:p-6',
60
+ 'flex min-h-[80px] w-full flex-row items-center gap-3 bg-ods-card p-4 content-md:gap-4 content-md:p-6',
61
61
  borderLeft ? 'border-l border-ods-border' : '',
62
62
  className,
63
63
  )}
@@ -59,10 +59,10 @@ const CheckboxBlock = forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, Ch
59
59
  className={cn(
60
60
  'flex w-full items-center gap-[var(--spacing-system-s)] rounded-md ring-1 ring-inset',
61
61
  // Trailing content stacks full-width below the text on mobile.
62
- trailing && 'flex-wrap md:flex-nowrap',
62
+ trailing && 'flex-wrap content-md:flex-nowrap',
63
63
  'p-[var(--spacing-system-sf)]',
64
- !description && 'min-h-[44px] md:min-h-[48px]',
65
- description && 'min-h-[60px] md:min-h-[64px]',
64
+ !description && 'min-h-[44px] content-md:min-h-[48px]',
65
+ description && 'min-h-[60px] content-md:min-h-[64px]',
66
66
  'bg-ods-card ring-ods-border',
67
67
  'cursor-pointer transition-colors duration-200',
68
68
  // States mirror Input: hover / active move the BACKGROUND, the ring
@@ -89,7 +89,7 @@ const CheckboxBlock = forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, Ch
89
89
  aria-required={required || undefined}
90
90
  aria-invalid={error ? true : undefined}
91
91
  className={cn(
92
- 'h-4 w-4 shrink-0 md:h-6 md:w-6',
92
+ 'h-4 w-4 shrink-0 content-md:h-6 content-md:w-6',
93
93
  'rounded-[6px] border-2',
94
94
  error ? 'border-ods-error' : 'border-[var(--color-border-strong)]',
95
95
  'bg-ods-card',
@@ -103,7 +103,7 @@ const CheckboxBlock = forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, Ch
103
103
  )}
104
104
  >
105
105
  <CheckboxPrimitive.Indicator className="flex items-center justify-center text-ods-text-on-accent">
106
- <CheckboxCheckmarkIcon className="h-2 w-2 md:h-2.5 md:w-2.5" />
106
+ <CheckboxCheckmarkIcon className="h-2 w-2 content-md:h-2.5 content-md:w-2.5" />
107
107
  </CheckboxPrimitive.Indicator>
108
108
  </CheckboxPrimitive.Root>
109
109
  <div
@@ -117,7 +117,7 @@ const CheckboxBlock = forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, Ch
117
117
  >
118
118
  <span
119
119
  className={cn(
120
- '!leading-5 text-h4 md:!leading-6',
120
+ '!leading-5 text-h4 content-md:!leading-6',
121
121
  'select-none text-ods-text-primary',
122
122
  truncateLabel ? 'block truncate' : 'break-words',
123
123
  )}
@@ -131,7 +131,9 @@ const CheckboxBlock = forwardRef<ComponentRef<typeof CheckboxPrimitive.Root>, Ch
131
131
  </span>
132
132
  )}
133
133
  </div>
134
- {trailing && <div className="flex w-full shrink-0 items-center md:ml-auto md:w-auto">{trailing}</div>}
134
+ {trailing && (
135
+ <div className="flex w-full shrink-0 items-center content-md:ml-auto content-md:w-auto">{trailing}</div>
136
+ )}
135
137
  </label>
136
138
  {error && (
137
139
  <p className="absolute bottom-0 left-0 right-0 translate-y-full truncate text-ods-error text-h6" title={error}>
@@ -40,7 +40,7 @@ export function ContentLoader({
40
40
  <div className="animate-pulse">
41
41
  {showTitle && <div className="mb-6 h-8 w-64 rounded bg-ods-skeleton" />}
42
42
  <div className="rounded-lg border border-ods-border bg-ods-card p-6">
43
- <div className="mb-6 grid grid-cols-1 gap-6 md:grid-cols-4">
43
+ <div className="mb-6 grid grid-cols-1 gap-6 content-md:grid-cols-4">
44
44
  {Array.from({ length: items }).map((_, i) => (
45
45
  <div key={i}>
46
46
  <div className="mb-2 h-4 w-20 rounded bg-ods-skeleton" />
@@ -75,8 +75,8 @@ export function ContentLoader({
75
75
  <div className="animate-pulse">
76
76
  {showTitle && <div className="mb-6 h-8 w-64 rounded bg-ods-skeleton" />}
77
77
  <div className="rounded-lg border border-ods-border bg-ods-card p-6">
78
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
79
- <div className="lg:col-span-2">
78
+ <div className="grid grid-cols-1 gap-6 content-lg:grid-cols-3">
79
+ <div className="content-lg:col-span-2">
80
80
  <div className="mb-4 h-64 rounded bg-ods-skeleton" />
81
81
  <div className="space-y-2">
82
82
  {Array.from({ length: 3 }).map((_, i) => (
@@ -98,7 +98,7 @@ export function CursorPagination({
98
98
  leftIcon={<ResetIcon className="h-4 w-4" />}
99
99
  aria-label="Go to first page"
100
100
  >
101
- <span className={compact ? 'hidden md:inline' : ''}>{resetButtonLabel}</span>
101
+ <span className={compact ? 'hidden content-md:inline' : ''}>{resetButtonLabel}</span>
102
102
  </Button>
103
103
  ) : (
104
104
  hasPreviousPage !== undefined &&
@@ -112,7 +112,7 @@ export function CursorPagination({
112
112
  leftIcon={<ChevronLeft className="h-4 w-4" />}
113
113
  aria-label="Go to previous page"
114
114
  >
115
- <span className={compact ? 'hidden md:inline' : ''}>Previous</span>
115
+ <span className={compact ? 'hidden content-md:inline' : ''}>Previous</span>
116
116
  </Button>
117
117
  )
118
118
  )}
@@ -126,7 +126,7 @@ export function CursorPagination({
126
126
  rightIcon={<ChevronRight className="h-4 w-4" />}
127
127
  aria-label="Go to next page"
128
128
  >
129
- <span className={compact ? 'hidden md:inline' : ''}>Next</span>
129
+ <span className={compact ? 'hidden content-md:inline' : ''}>Next</span>
130
130
  </Button>
131
131
  </div>
132
132
  </div>
@@ -74,7 +74,7 @@ export interface DashboardInfoCardProps {
74
74
  href?: string;
75
75
  /** Tooltip content shown on a question-mark icon next to the value */
76
76
  tooltip?: ReactNode;
77
- /** Override the value text className (default: `text-h3 md:text-h2` per Figma) */
77
+ /** Override the value text className (default: `text-h3 content-md:text-h2` per Figma) */
78
78
  valueClassName?: string;
79
79
  /** Secondary text rendered beside the value (e.g. an entry/item count). */
80
80
  subValue?: ReactNode;
@@ -157,17 +157,21 @@ export function DashboardInfoCard({
157
157
  const { base, md, lg } = size;
158
158
 
159
159
  const rings: Array<{ key: string; size: number; className: string }> = [
160
- { key: 'base', size: base, className: md !== undefined ? 'md:hidden' : lg !== undefined ? 'lg:hidden' : '' },
160
+ {
161
+ key: 'base',
162
+ size: base,
163
+ className: md !== undefined ? 'content-md:hidden' : lg !== undefined ? 'content-lg:hidden' : '',
164
+ },
161
165
  ];
162
166
  if (md !== undefined) {
163
167
  rings.push({
164
168
  key: 'md',
165
169
  size: md,
166
- className: lg !== undefined ? 'hidden md:block lg:hidden' : 'hidden md:block',
170
+ className: lg !== undefined ? 'hidden content-md:block content-lg:hidden' : 'hidden content-md:block',
167
171
  });
168
172
  }
169
173
  if (lg !== undefined) {
170
- rings.push({ key: 'lg', size: lg, className: 'hidden lg:block' });
174
+ rings.push({ key: 'lg', size: lg, className: 'hidden content-lg:block' });
171
175
  }
172
176
 
173
177
  return (
@@ -190,8 +194,8 @@ export function DashboardInfoCard({
190
194
  {/* Icon slot (Figma "icon" variant): 32px box / 16px content on mobile,
191
195
  56px box / 24px content from `md` up. */}
192
196
  {icon && (
193
- <div className="flex size-8 shrink-0 items-center justify-center rounded-sm border border-ods-border bg-ods-bg p-[var(--spacing-system-xxs)] text-ods-text-primary md:size-14">
194
- <span className="flex size-4 items-center justify-center md:size-6 [&>*]:size-full">{icon}</span>
197
+ <div className="flex size-8 shrink-0 items-center justify-center rounded-sm border border-ods-border bg-ods-bg p-[var(--spacing-system-xxs)] text-ods-text-primary content-md:size-14">
198
+ <span className="flex size-4 items-center justify-center content-md:size-6 [&>*]:size-full">{icon}</span>
195
199
  </div>
196
200
  )}
197
201
 
@@ -211,7 +215,7 @@ export function DashboardInfoCard({
211
215
 
212
216
  {/* Value and percentage */}
213
217
  <div className="flex items-center gap-[var(--spacing-system-xs)]">
214
- <p className={cn('truncate text-ods-text-primary text-h3 md:text-h2', valueClassName)}>
218
+ <p className={cn('truncate text-ods-text-primary text-h3 content-md:text-h2', valueClassName)}>
215
219
  {loading ? <span className="block h-[1lh] w-24 animate-pulse rounded bg-ods-border" /> : formattedValue}
216
220
  </p>
217
221
  {subValue && <p className="text-ods-text-secondary text-h6">{subValue}</p>}
@@ -243,10 +247,10 @@ export function DashboardInfoCard({
243
247
  // min-h) — with a 32px titleTag the natural content height slightly exceeds
244
248
  // the spec, and Figma's frame is fixed; items-center absorbs the difference.
245
249
  const baseClassName =
246
- 'bg-ods-card border border-ods-border rounded-md p-[var(--spacing-system-xsf)] md:p-[var(--spacing-system-m)] h-16 md:h-[104px] flex gap-[var(--spacing-system-s)] md:gap-[var(--spacing-system-m)] items-center transition-all';
250
+ 'bg-ods-card border border-ods-border rounded-md p-[var(--spacing-system-xsf)] content-md:p-[var(--spacing-system-m)] h-16 content-md:h-[104px] flex gap-[var(--spacing-system-s)] content-md:gap-[var(--spacing-system-m)] items-center transition-all';
247
251
 
248
252
  // A caption is a third line: the fixed stat-tile height would clip it.
249
- const captionClassName = caption ? 'h-auto md:h-auto' : undefined;
253
+ const captionClassName = caption ? 'h-auto content-md:h-auto' : undefined;
250
254
 
251
255
  if (href) {
252
256
  return (
@@ -18,12 +18,12 @@ export interface DataAttributionProps {
18
18
  */
19
19
  export function DataAttribution({ icon, source, lastUpdated }: DataAttributionProps) {
20
20
  return (
21
- <div className="flex shrink-0 flex-col gap-[var(--spacing-system-xxs)] text-ods-text-primary text-h6 sm:flex-row sm:items-center sm:gap-[var(--spacing-system-sf)]">
21
+ <div className="flex shrink-0 flex-col gap-[var(--spacing-system-xxs)] text-ods-text-primary text-h6 content-sm:flex-row content-sm:items-center content-sm:gap-[var(--spacing-system-sf)]">
22
22
  <div className="flex items-center gap-[var(--spacing-system-xsf)]">
23
23
  {icon}
24
24
  <span>Data synced from {source}</span>
25
25
  </div>
26
- <span className="hidden text-ods-text-secondary sm:inline" aria-hidden="true">
26
+ <span className="hidden text-ods-text-secondary content-sm:inline" aria-hidden="true">
27
27
  &middot;
28
28
  </span>
29
29
  <span className="text-ods-text-secondary">Last updated: {lastUpdated ? formatDate(lastUpdated) : 'Never'}</span>
@@ -52,10 +52,10 @@ export interface DataTableBodyProps<T = unknown> {
52
52
  * 34px per missing row too short — on a 15-row page with 5 results, 340px of
53
53
  * jump against every other page. Appending a height through `rowClassName`
54
54
  * cannot fix it either: tailwind-merge drops the plain `h-[66px]` but keeps
55
- * the `md:h-[78px]` beside it, so the override holds on a phone and loses on
55
+ * the `content-md:h-[78px]` beside it, so the override holds on a phone and loses on
56
56
  * a desktop. Pass it here and every row slot in the table agrees.
57
57
  *
58
- * Responsive values belong in the string itself, e.g. `'h-[200px] md:h-[112px]'`.
58
+ * Responsive values belong in the string itself, e.g. `'h-[200px] content-md:h-[112px]'`.
59
59
  */
60
60
  rowHeightClassName?: string;
61
61
  /**
@@ -72,7 +72,7 @@ export function DataTableHeader({
72
72
  return (
73
73
  <div
74
74
  className={cn(
75
- 'hidden md:flex md:flex-col',
75
+ 'hidden content-md:flex content-md:flex-col',
76
76
  stickyHeader && `sticky z-10 bg-ods-bg ${stickyHeaderOffset ?? 'top-0'}`,
77
77
  className,
78
78
  )}
@@ -93,7 +93,7 @@ export function DataTableHeader({
93
93
  // the absolute placement. Safe as a `max-lg:` override: nothing
94
94
  // else in this string sets margin or height, so it competes only
95
95
  // with unprefixed defaults, never with a `md:`/`lg:` class.
96
- 'max-lg:ml-auto max-lg:h-12 lg:absolute lg:inset-y-0 lg:right-[var(--spacing-system-mf)]',
96
+ 'content-max-lg:ml-auto content-max-lg:h-12 content-lg:absolute content-lg:inset-y-0 content-lg:right-[var(--spacing-system-mf)]',
97
97
  )}
98
98
  >
99
99
  {rightSlot}
@@ -128,7 +128,7 @@ type ColumnMeta = AnyHeader['column']['columnDef']['meta'];
128
128
  * every screen narrower than a desktop. A consumer wanting it back had no legal
129
129
  * move: `meta.width` is neutralized here by a doubled-class rule, so the escape
130
130
  * was a specificity fight, and the one consumer who tried it ended up
131
- * re-implementing this whole decision in `max-lg:[&&&]:` classes.
131
+ * re-implementing this whole decision in `content-max-lg:[&&&]:` classes.
132
132
  *
133
133
  * A sortable column whose CELLS are hidden below `lg` (`meta.hideAt`) still
134
134
  * keeps its toggle, exactly as a filterable one does: reordering by a column
@@ -142,16 +142,16 @@ function keepsCellOnTablet(meta: ColumnMeta): boolean {
142
142
  // Literal class maps — Tailwind's scanner needs the full class strings, which a
143
143
  // `${bp}:flex` template would not give it.
144
144
  const SHOW_FROM: Record<TailwindBreakpoint, string> = {
145
- md: 'md:flex',
146
- lg: 'lg:flex',
147
- xl: 'xl:flex',
148
- '2xl': '2xl:flex',
145
+ md: 'content-md:flex',
146
+ lg: 'content-lg:flex',
147
+ xl: 'content-xl:flex',
148
+ '2xl': 'content-2xl:flex',
149
149
  };
150
150
  const HIDE_FROM: Record<TailwindBreakpoint, string> = {
151
- md: 'md:hidden',
152
- lg: 'lg:hidden',
153
- xl: 'xl:hidden',
154
- '2xl': '2xl:hidden',
151
+ md: 'content-md:hidden',
152
+ lg: 'content-lg:hidden',
153
+ xl: 'content-xl:hidden',
154
+ '2xl': 'content-2xl:hidden',
155
155
  };
156
156
  /** Index of `lg` in the `[base, md, lg, xl, 2xl]` visibility array. */
157
157
  const LG_STEP = BREAKPOINT_ORDER.indexOf('lg') + 1;
@@ -161,7 +161,7 @@ const LG_STEP = BREAKPOINT_ORDER.indexOf('lg') + 1;
161
161
  *
162
162
  * Two rules stack here: the column's own `hideAt`, and "below `lg` only the
163
163
  * cells a user can act on". Layering them as classes does not work — a
164
- * `max-lg:` override cannot cancel a `md:hidden` from `hideAt`, because Tailwind
164
+ * `max-lg:` override cannot cancel a `content-md:hidden` from `hideAt`, because Tailwind
165
165
  * emits the `max-lg` block BEFORE the `md` one and equal-specificity rules are
166
166
  * decided by source order. So both rules are resolved on booleans first, and only
167
167
  * the result is turned into classes: at most one utility per breakpoint, each a
@@ -244,7 +244,7 @@ function HeaderCell({ header, sort, onSortChange }: HeaderCellProps) {
244
244
  //
245
245
  // `[&&]` doubles the class in the selector (`.cls.cls`, specificity 0-2-0),
246
246
  // and it is load-bearing: consumers routinely write a RESPONSIVE width
247
- // (`w-[80px] md:w-1/5` is the common shape), and between md and lg that
247
+ // (`w-[80px] content-md:w-1/5` is the common shape), and between md and lg that
248
248
  // `md:` rule and this `max-lg:` one both match. At equal specificity source
249
249
  // order decides, and Tailwind emits the `max-lg` block BEFORE the `md` one
250
250
  // — the same ordering documented for visibility above — so the tablet would
@@ -255,7 +255,7 @@ function HeaderCell({ header, sort, onSortChange }: HeaderCellProps) {
255
255
  // consumer that genuinely needs a tablet width can still take it back with a
256
256
  // more specific rule — `!important` could only be answered with another one.
257
257
  meta?.width || 'min-w-0 flex-1',
258
- keepOnTablet && 'max-lg:[&&]:w-auto max-lg:[&&]:flex-none max-lg:[&&]:basis-auto',
258
+ keepOnTablet && 'content-max-lg:[&&]:w-auto content-max-lg:[&&]:flex-none content-max-lg:[&&]:basis-auto',
259
259
  meta?.headerClassName,
260
260
  )}
261
261
  >
@@ -279,7 +279,7 @@ function HeaderCell({ header, sort, onSortChange }: HeaderCellProps) {
279
279
  'flex h-12 w-full select-none items-center gap-[var(--spacing-system-xsf)] rounded-sm transition-colors duration-200',
280
280
  // Same "always, neutralized below lg" shape as the width above.
281
281
  alignJustify(align),
282
- keepOnTablet && 'max-lg:justify-start',
282
+ keepOnTablet && 'content-max-lg:justify-start',
283
283
  canSort && 'group cursor-pointer',
284
284
  )}
285
285
  onClick={canSort ? () => onSortChange?.(column.id) : undefined}
@@ -10,7 +10,7 @@ import { getHideClasses } from './utils';
10
10
  * each side, so the outer block lands on the designed 68px / 80px total —
11
11
  * hence the 66/78 values here.
12
12
  */
13
- export const ROW_HEIGHT_DESKTOP = 'h-[66px] md:h-[78px]';
13
+ export const ROW_HEIGHT_DESKTOP = 'h-[66px] content-md:h-[78px]';
14
14
  export const ROW_HEIGHT_MOBILE = 'h-[66px]';
15
15
 
16
16
  /**
@@ -44,7 +44,7 @@ export interface DataTableSkeletonProps {
44
44
  * REPLACES the design row height, for a table whose rows are not that tall.
45
45
  * Sizes the CARD, as a real row does.
46
46
  * Appending a height through `rowClassName` cannot do this: tailwind-merge
47
- * drops the plain `h-[66px]` but keeps `md:h-[78px]`, so the override held
47
+ * drops the plain `h-[66px]` but keeps `content-md:h-[78px]`, so the override held
48
48
  * on a phone and lost on a desktop. See `DataTableBodyProps.rowHeightClassName`.
49
49
  */
50
50
  rowHeightClassName?: string;
@@ -69,7 +69,7 @@ export function DataTableSkeleton({ rows = 10, className, rowClassName, rowHeigh
69
69
  >
70
70
  <div
71
71
  className={cn(
72
- 'hidden py-0 md:flex',
72
+ 'hidden py-0 content-md:flex',
73
73
  ROW_SHELL_CLASSES,
74
74
  rowHeightClassName ? 'h-full' : ROW_HEIGHT_DESKTOP,
75
75
  rowClassName,
@@ -101,7 +101,7 @@ export function DataTableSkeleton({ rows = 10, className, rowClassName, rowHeigh
101
101
  </div>
102
102
  <div
103
103
  className={cn(
104
- 'flex justify-start py-0 md:hidden',
104
+ 'flex justify-start py-0 content-md:hidden',
105
105
  ROW_SHELL_CLASSES,
106
106
  rowHeightClassName ? 'h-full' : ROW_HEIGHT_MOBILE,
107
107
  rowClassName,
@@ -207,14 +207,14 @@ export function PlaceholderRows({
207
207
  >
208
208
  <div
209
209
  className={cn(
210
- 'hidden py-0 md:flex',
210
+ 'hidden py-0 content-md:flex',
211
211
  ROW_SHELL_CLASSES,
212
212
  innerHeightClassName ?? (rowHeightClassName ? 'h-full' : ROW_HEIGHT_DESKTOP),
213
213
  )}
214
214
  />
215
215
  <div
216
216
  className={cn(
217
- 'flex justify-start py-0 md:hidden',
217
+ 'flex justify-start py-0 content-md:hidden',
218
218
  ROW_SHELL_CLASSES,
219
219
  innerHeightClassName ?? (rowHeightClassName ? 'h-full' : ROW_HEIGHT_MOBILE),
220
220
  )}
@@ -8,8 +8,8 @@ export const BREAKPOINT_ORDER: TailwindBreakpoint[] = ['md', 'lg', 'xl', '2xl'];
8
8
  * Generates Tailwind hide classes based on breakpoint configuration.
9
9
  *
10
10
  * @example
11
- * getHideClasses('md') // 'hidden md:flex'
12
- * getHideClasses(['md', 'lg']) // 'md:hidden lg:hidden xl:flex'
11
+ * getHideClasses('md') // 'hidden content-md:flex'
12
+ * getHideClasses(['md', 'lg']) // 'content-md:hidden content-lg:hidden content-xl:flex'
13
13
  */
14
14
  export function getHideClasses(hideAt?: TailwindBreakpoint | TailwindBreakpoint[]): string {
15
15
  if (!hideAt) return '';
@@ -17,13 +17,13 @@ export function getHideClasses(hideAt?: TailwindBreakpoint | TailwindBreakpoint[
17
17
  const breakpoints = Array.isArray(hideAt) ? hideAt : [hideAt];
18
18
 
19
19
  if (breakpoints.length === 1) {
20
- return `hidden ${breakpoints[0]}:flex`;
20
+ return `hidden content-${breakpoints[0]}:flex`;
21
21
  }
22
22
 
23
23
  const maxIdx = Math.max(...breakpoints.map(bp => BREAKPOINT_ORDER.indexOf(bp)));
24
- const hideClasses = breakpoints.map(bp => `${bp}:hidden`).join(' ');
24
+ const hideClasses = breakpoints.map(bp => `content-${bp}:hidden`).join(' ');
25
25
  const showBreakpoint = BREAKPOINT_ORDER[maxIdx + 1];
26
- return showBreakpoint ? `${hideClasses} ${showBreakpoint}:flex` : hideClasses;
26
+ return showBreakpoint ? `${hideClasses} content-${showBreakpoint}:flex` : hideClasses;
27
27
  }
28
28
 
29
29
  /**