@flamingo-stack/openframe-frontend-core 0.0.702 → 0.0.703-snapshot.20261006080901
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.
- package/dist/{chunk-CYYTD5ZK.cjs → chunk-262YQFOS.cjs} +47 -47
- package/dist/{chunk-SAA7B3DA.js → chunk-2G546OND.js} +500 -67
- package/dist/{chunk-6JPQDYYY.js → chunk-2JDVL7UV.js} +2614 -2001
- package/dist/{chunk-ASN65P3F.cjs → chunk-4DQMTBMK.cjs} +15 -15
- package/dist/{chunk-CZ34HXDW.js → chunk-4KGXLVCF.js} +686 -725
- package/dist/{chunk-TCZCMD5Q.js → chunk-5HBHO5TB.js} +1 -1
- package/dist/{chunk-446KS5BG.js → chunk-5QJDM6UV.js} +5 -5
- package/dist/{chunk-UJJWTJ6S.js → chunk-6WQIUQUC.js} +30 -16
- package/dist/{chunk-YR6JPJF4.js → chunk-6XIF2Z7I.js} +4 -4
- package/dist/{chunk-YGRHITPY.cjs → chunk-7JIL3WOH.cjs} +24 -24
- package/dist/{chunk-RS7HWAYX.js → chunk-7LFIKJX2.js} +3 -3
- package/dist/{chunk-4OGAXAEG.cjs → chunk-ABU3TGXA.cjs} +3 -3
- package/dist/{chunk-3WSFIV5G.cjs → chunk-AMYY3PNL.cjs} +69 -55
- package/dist/{chunk-BRXOGCH3.cjs → chunk-BIZNSF3U.cjs} +3 -3
- package/dist/{chunk-2A4XES7R.cjs → chunk-BM5MVGH3.cjs} +3 -3
- package/dist/{chunk-IIMICN7L.cjs → chunk-C3BWIU7R.cjs} +4 -44
- package/dist/{chunk-LZNJH23A.cjs → chunk-C7XGRLT5.cjs} +12 -12
- package/dist/{chunk-6YCXA7CN.js → chunk-CH5232HV.js} +20 -19
- package/dist/{chunk-UIBSSVON.cjs → chunk-D7BTSVMS.cjs} +2 -2
- package/dist/{chunk-BO5ZHDA4.js → chunk-ERCV6HHJ.js} +7 -7
- package/dist/{chunk-5V6O73EH.js → chunk-FLKJYMVB.js} +3 -3
- package/dist/{chunk-Z5HDCZAS.js → chunk-FXENTYE5.js} +15 -15
- package/dist/{chunk-HIXGAY2L.cjs → chunk-HFJW24JJ.cjs} +121 -121
- package/dist/{chunk-HPJ4XS2L.js → chunk-HJAYVKWQ.js} +24 -24
- package/dist/{chunk-PLK6GHN7.js → chunk-I7DFUQMN.js} +10 -10
- package/dist/{chunk-KJ5LWATV.js → chunk-IHU5ANUY.js} +7 -7
- package/dist/{chunk-AEQANLBW.cjs → chunk-IZGDG5X6.cjs} +505 -72
- package/dist/{chunk-2V4Z44G6.js → chunk-JEYRXT5L.js} +17 -17
- package/dist/{chunk-B3LZJ6J3.cjs → chunk-L3IC42IF.cjs} +32 -32
- package/dist/{chunk-RTGPIHVO.cjs → chunk-LDPEQGKT.cjs} +2243 -1630
- package/dist/{chunk-FD4DBTFO.cjs → chunk-LTSTC3N5.cjs} +1253 -1292
- package/dist/{chunk-OGLCD3UL.js → chunk-MFFCUVWG.js} +6 -6
- package/dist/{chunk-3L7KCOGO.cjs → chunk-MGGGBHYD.cjs} +30 -30
- package/dist/{chunk-QFW3RUZS.cjs → chunk-MI3JUJ75.cjs} +33 -33
- package/dist/{chunk-EMCQGFXD.cjs → chunk-MMOODW57.cjs} +28 -27
- package/dist/{chunk-Q76ZTHNV.js → chunk-MP2C3LJ4.js} +1 -1
- package/dist/{chunk-E3DH543A.cjs → chunk-N3TO7JV3.cjs} +98 -98
- package/dist/{chunk-2T6QWNXU.js → chunk-NDESEPW5.js} +99 -11
- package/dist/{chunk-ETFFEA3J.js → chunk-NRLJUBCS.js} +7 -7
- package/dist/{chunk-HUOLB7ZN.cjs → chunk-OHFS7VOU.cjs} +9 -9
- package/dist/{chunk-MWUBBBWZ.js → chunk-QVSFBSWV.js} +10 -10
- package/dist/{chunk-MDBHZBW7.cjs → chunk-RKV5B7EU.cjs} +92 -4
- package/dist/{chunk-3G76LRGL.cjs → chunk-SYXQLETR.cjs} +29 -29
- package/dist/{chunk-FHM7GD5B.cjs → chunk-UK62YTH6.cjs} +28 -14
- package/dist/{chunk-HUMWQMCU.js → chunk-UT4YHQZW.js} +3 -3
- package/dist/{chunk-NGJCWEYX.cjs → chunk-VHCACDKP.cjs} +46 -46
- package/dist/{chunk-5FFNNJM7.js → chunk-VR2ZLFCP.js} +1 -1
- package/dist/{chunk-IZKOQVXO.js → chunk-VTASHWER.js} +14 -14
- package/dist/{chunk-64O4L7WN.js → chunk-WUJNYGO2.js} +11 -51
- package/dist/{chunk-JOY6HVPV.js → chunk-XATTBO5X.js} +25 -11
- package/dist/{chunk-L7KZA7ZD.cjs → chunk-XIFOBQRQ.cjs} +6 -6
- package/dist/{chunk-CXDJUKC6.cjs → chunk-XJKZ4IKT.cjs} +4 -4
- package/dist/{chunk-XCIFHW4E.cjs → chunk-XOYH2YQE.cjs} +2 -2
- package/dist/{chunk-HYFLTFFB.js → chunk-ZQFZSFQI.js} +2 -2
- package/dist/components/case-studies/index.cjs +24 -24
- package/dist/components/case-studies/index.js +10 -10
- package/dist/components/chat/chat-archive-page.d.ts +3 -3
- package/dist/components/chat/chat-archive-page.d.ts.map +1 -1
- package/dist/components/chat/chat-nav-sidebar.d.ts +4 -0
- package/dist/components/chat/chat-nav-sidebar.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-header.d.ts +3 -2
- package/dist/components/chat/chat-panel-header.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +36 -2
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +14 -6
- package/dist/components/chat/index.d.ts +4 -1
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +13 -5
- package/dist/components/chat/mingo-archive-list.d.ts +17 -0
- package/dist/components/chat/mingo-archive-list.d.ts.map +1 -0
- package/dist/components/chat/mingo-chat-header.d.ts +31 -0
- package/dist/components/chat/mingo-chat-header.d.ts.map +1 -0
- package/dist/components/chat/mingo-chat-rail.d.ts +54 -0
- package/dist/components/chat/mingo-chat-rail.d.ts.map +1 -0
- package/dist/components/chat/model-display.d.ts.map +1 -1
- package/dist/components/contact/contact-form.d.ts.map +1 -1
- package/dist/components/contact/index.cjs +11 -11
- package/dist/components/contact/index.js +10 -10
- package/dist/components/content-loading-container.d.ts +1 -1
- package/dist/components/content-loading-container.d.ts.map +1 -1
- package/dist/components/docs/index.cjs +14 -14
- package/dist/components/docs/index.js +13 -13
- package/dist/components/docs/skeletons.d.ts.map +1 -1
- package/dist/components/embeds/index.cjs +11 -11
- package/dist/components/embeds/index.js +10 -10
- package/dist/components/faq/index.cjs +12 -12
- package/dist/components/faq/index.js +11 -11
- package/dist/components/features/figma-prototype-viewer.d.ts.map +1 -1
- package/dist/components/features/index.cjs +10 -10
- package/dist/components/features/index.js +9 -9
- package/dist/components/features/media-gallery-manager.d.ts.map +1 -1
- package/dist/components/features/parallax-image-showcase.d.ts.map +1 -1
- package/dist/components/features/policy-configuration-panel.d.ts.map +1 -1
- package/dist/components/features/section-selector.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.cjs +119 -119
- package/dist/components/help-center-pages/index.js +39 -39
- package/dist/components/help-center-pages/trust-center-sections.d.ts +2 -2
- package/dist/components/help-center-pages/trust-center-sections.d.ts.map +1 -1
- package/dist/components/index.cjs +94 -86
- package/dist/components/index.js +32 -24
- package/dist/components/layout/article-detail-layout.d.ts +1 -1
- package/dist/components/layout/article-detail-layout.d.ts.map +1 -1
- package/dist/components/layout/page-container.d.ts.map +1 -1
- package/dist/components/layout/title-block.d.ts +2 -2
- package/dist/components/layout/title-block.d.ts.map +1 -1
- package/dist/components/loading/page-layout-skeleton.d.ts.map +1 -1
- package/dist/components/loading/unified-skeleton.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/booking-form.d.ts +4 -4
- package/dist/components/meeting-scheduler/booking-form.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/context-panel.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +127 -127
- package/dist/components/meeting-scheduler/index.d.ts +2 -2
- package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.js +50 -50
- package/dist/components/navigation/app-header.d.ts +4 -0
- package/dist/components/navigation/app-header.d.ts.map +1 -1
- package/dist/components/navigation/app-layout-drawer.d.ts.map +1 -1
- package/dist/components/navigation/app-layout-side-panel.d.ts +142 -0
- package/dist/components/navigation/app-layout-side-panel.d.ts.map +1 -0
- package/dist/components/navigation/app-layout.d.ts +11 -1
- package/dist/components/navigation/app-layout.d.ts.map +1 -1
- package/dist/components/navigation/header-mingo-button.d.ts +4 -1
- package/dist/components/navigation/header-mingo-button.d.ts.map +1 -1
- package/dist/components/navigation/index.cjs +13 -13
- package/dist/components/navigation/index.d.ts +1 -0
- package/dist/components/navigation/index.d.ts.map +1 -1
- package/dist/components/navigation/index.js +12 -12
- package/dist/components/navigation/navigation-sidebar.d.ts +8 -1
- package/dist/components/navigation/navigation-sidebar.d.ts.map +1 -1
- package/dist/components/navigation/sliding-sidebar.d.ts.map +1 -1
- package/dist/components/onboarding-guides/index.cjs +14 -14
- package/dist/components/onboarding-guides/index.js +13 -13
- package/dist/components/persistent-filter-controls.d.ts.map +1 -1
- package/dist/components/related-content/index.cjs +7 -7
- package/dist/components/related-content/index.js +6 -6
- package/dist/components/shared/detail-page-skeleton.d.ts.map +1 -1
- package/dist/components/tickets/help-center-create-form.d.ts +4 -4
- package/dist/components/tickets/index.cjs +15 -15
- package/dist/components/tickets/index.js +14 -14
- package/dist/components/ui/announcement-bar-view.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/checkbox-block.d.ts.map +1 -1
- package/dist/components/ui/dashboard-info-card.d.ts +1 -1
- package/dist/components/ui/dashboard-info-card.d.ts.map +1 -1
- package/dist/components/ui/data-table/data-table-body.d.ts +2 -2
- package/dist/components/ui/data-table/data-table-skeleton.d.ts +2 -2
- package/dist/components/ui/data-table/data-table-skeleton.d.ts.map +1 -1
- package/dist/components/ui/data-table/utils.d.ts +2 -2
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/drawer.d.ts +7 -3
- package/dist/components/ui/drawer.d.ts.map +1 -1
- package/dist/components/ui/entity-image.d.ts +2 -2
- package/dist/components/ui/file-manager/index.cjs +36 -36
- package/dist/components/ui/file-manager/index.js +3 -3
- package/dist/components/ui/filter-modal.d.ts.map +1 -1
- package/dist/components/ui/index.cjs +18 -10
- package/dist/components/ui/index.js +17 -9
- package/dist/components/ui/info-card-row.d.ts.map +1 -1
- package/dist/components/ui/menubar.d.ts +1 -1
- package/dist/components/ui/menubar.d.ts.map +1 -1
- package/dist/components/ui/modal-v2.d.ts.map +1 -1
- package/dist/components/ui/modal.d.ts.map +1 -1
- package/dist/components/ui/no-data/no-data-actions.d.ts.map +1 -1
- package/dist/components/ui/no-data/no-data-styles.d.ts +1 -1
- package/dist/components/ui/no-data/no-data-styles.d.ts.map +1 -1
- package/dist/components/ui/page-actions.d.ts.map +1 -1
- package/dist/components/ui/panel-resize-handle.d.ts +25 -0
- package/dist/components/ui/panel-resize-handle.d.ts.map +1 -0
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/table/table-skeleton.d.ts +1 -1
- package/dist/components/ui/table/table-skeleton.d.ts.map +1 -1
- package/dist/hooks/index.cjs +23 -9
- package/dist/hooks/index.js +24 -10
- package/dist/hooks/ui/index.d.ts +1 -0
- package/dist/hooks/ui/index.d.ts.map +1 -1
- package/dist/hooks/ui/use-content-breakpoint.d.ts +32 -0
- package/dist/hooks/ui/use-content-breakpoint.d.ts.map +1 -0
- package/dist/hooks/ui/use-isomorphic-layout-effect.d.ts +2 -2
- package/dist/hooks/ui/use-isomorphic-layout-effect.d.ts.map +1 -1
- package/dist/hooks/ui/use-media-query.d.ts.map +1 -1
- package/dist/hooks/ui/use-resizable-panel-size.d.ts +46 -0
- package/dist/hooks/ui/use-resizable-panel-size.d.ts.map +1 -0
- package/dist/index.cjs +39 -17
- package/dist/index.js +41 -19
- package/dist/styles/layout-steps.d.ts +30 -0
- package/dist/styles/layout-steps.d.ts.map +1 -0
- package/dist/tailwind.config.cjs +36 -11
- package/dist/tailwind.config.js +36 -11
- package/eslint-config/README.md +9 -0
- package/eslint-config/base.js +17 -1
- package/eslint-config/layout-variants.js +57 -0
- package/package.json +3 -1
- package/src/ODS_TOKEN_RULES.md +40 -0
- package/src/components/chat/chat-archive-page.tsx +9 -7
- package/src/components/chat/chat-nav-sidebar.tsx +10 -4
- package/src/components/chat/chat-panel-header.tsx +8 -5
- package/src/components/chat/embeddable-chat.tsx +686 -494
- package/src/components/chat/index.ts +4 -0
- package/src/components/chat/mingo-archive-list.tsx +108 -0
- package/src/components/chat/mingo-chat-header.tsx +104 -0
- package/src/components/chat/mingo-chat-rail.tsx +361 -0
- package/src/components/chat/model-display.tsx +8 -1
- package/src/components/contact/contact-form.tsx +11 -9
- package/src/components/content-loading-container.tsx +4 -2
- package/src/components/docs/doc-viewer.tsx +7 -7
- package/src/components/docs/skeletons.tsx +7 -4
- package/src/components/dynamic-skeleton.tsx +1 -1
- package/src/components/embeds/claude-embed.tsx +1 -1
- package/src/components/embeds/embed-viewer-frame.tsx +4 -4
- package/src/components/embeds/figma-embed.tsx +2 -2
- package/src/components/embeds/google-sheets-viewer.tsx +1 -1
- package/src/components/embeds/pdf-viewer.tsx +3 -3
- package/src/components/empty-state.tsx +6 -6
- package/src/components/faq/faq-section.tsx +2 -2
- package/src/components/faq-accordion.tsx +1 -1
- package/src/components/features/board/board-column-header.tsx +1 -1
- package/src/components/features/command-box.tsx +3 -3
- package/src/components/features/entity-video-section.tsx +2 -2
- package/src/components/features/figma-prototype-viewer.tsx +4 -1
- package/src/components/features/media-gallery-manager.tsx +3 -1
- package/src/components/features/parallax-image-showcase.tsx +9 -6
- package/src/components/features/policy-configuration-panel.tsx +9 -7
- package/src/components/features/provider-button.tsx +1 -1
- package/src/components/features/section-selector.tsx +11 -6
- package/src/components/features/select-button.tsx +4 -4
- package/src/components/features/seo-editor-preview.tsx +2 -2
- package/src/components/features/video-ratio-tabs.tsx +3 -3
- package/src/components/features/waitlist-form.tsx +1 -1
- package/src/components/help-center-pages/trust-center-page.tsx +1 -1
- package/src/components/help-center-pages/trust-center-sections.tsx +14 -14
- package/src/components/icon-display.tsx +1 -1
- package/src/components/layout/article-detail-layout.tsx +4 -2
- package/src/components/layout/list-page-layout.tsx +2 -2
- package/src/components/layout/page-container.tsx +26 -14
- package/src/components/layout/page-heading.tsx +1 -1
- package/src/components/layout/page-layout.tsx +1 -1
- package/src/components/layout/title-block.tsx +13 -13
- package/src/components/loading/card-skeleton.tsx +11 -11
- package/src/components/loading/category-vendor-selector-skeleton.tsx +1 -1
- package/src/components/loading/content-skeleton.tsx +6 -6
- package/src/components/loading/device-card-skeleton.tsx +1 -1
- package/src/components/loading/margin-report-skeleton.tsx +7 -7
- package/src/components/loading/msp-profile-form-skeleton.tsx +3 -3
- package/src/components/loading/organization-card-skeleton.tsx +2 -2
- package/src/components/loading/page-layout-skeleton.tsx +80 -68
- package/src/components/loading/unified-skeleton.tsx +16 -6
- package/src/components/media-carousel.tsx +3 -3
- package/src/components/meeting-scheduler/booking-form.tsx +9 -8
- package/src/components/meeting-scheduler/context-panel.tsx +8 -6
- package/src/components/meeting-scheduler/directory.tsx +4 -4
- package/src/components/meeting-scheduler/index.tsx +15 -15
- package/src/components/meeting-scheduler/slot-picker.tsx +12 -12
- package/src/components/navigation/app-header.tsx +6 -0
- package/src/components/navigation/app-layout-drawer.tsx +14 -237
- package/src/components/navigation/app-layout-side-panel.tsx +594 -0
- package/src/components/navigation/app-layout.tsx +69 -4
- package/src/components/navigation/header-mingo-button.tsx +13 -3
- package/src/components/navigation/index.ts +5 -0
- package/src/components/navigation/navigation-sidebar.tsx +17 -3
- package/src/components/navigation/sliding-sidebar.tsx +2 -1
- package/src/components/pagination.tsx +3 -3
- package/src/components/persistent-filter-controls.tsx +6 -2
- package/src/components/platform/ScriptArguments.tsx +1 -1
- package/src/components/platform/ScriptInfoSection.tsx +4 -4
- package/src/components/shared/article-author-byline.tsx +1 -1
- package/src/components/shared/delivery/delivery-lists.tsx +2 -2
- package/src/components/shared/delivery/delivery-row.tsx +7 -7
- package/src/components/shared/delivery/delivery-table.tsx +3 -3
- package/src/components/shared/detail-page-skeleton.tsx +11 -5
- package/src/components/shared/dev-section/dev-card-row.tsx +6 -6
- package/src/components/shared/dev-section/dev-section-view.tsx +1 -1
- package/src/components/shared/product-release/product-release-card-skeleton.tsx +8 -8
- package/src/components/shared/product-release/product-release-card.tsx +9 -9
- package/src/components/shared/product-release/product-releases-view.tsx +1 -1
- package/src/components/shared/product-release/release-detail-page.tsx +5 -5
- package/src/components/shared/roadmap/roadmap-grid-skeleton.tsx +1 -1
- package/src/components/shared/roadmap/roadmap-grid.tsx +3 -3
- package/src/components/tickets/help-center-card.tsx +1 -1
- package/src/components/tickets/help-center-create-form.tsx +12 -12
- package/src/components/ui/announcement-bar-view.tsx +2 -10
- package/src/components/ui/benefit-card.tsx +18 -18
- package/src/components/ui/brand-association-grid.tsx +4 -4
- package/src/components/ui/breadcrumb.tsx +4 -1
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/checkbox-block.tsx +9 -7
- package/src/components/ui/content-loader.tsx +3 -3
- package/src/components/ui/cursor-pagination.tsx +3 -3
- package/src/components/ui/dashboard-info-card.tsx +13 -9
- package/src/components/ui/data-attribution.tsx +2 -2
- package/src/components/ui/data-table/data-table-body.tsx +2 -2
- package/src/components/ui/data-table/data-table-header.tsx +15 -15
- package/src/components/ui/data-table/data-table-skeleton.tsx +6 -6
- package/src/components/ui/data-table/utils.ts +5 -5
- package/src/components/ui/dialog.tsx +4 -1
- package/src/components/ui/drawer.tsx +43 -189
- package/src/components/ui/duration-input.tsx +1 -1
- package/src/components/ui/entity-image.tsx +3 -3
- package/src/components/ui/feature-card.tsx +10 -10
- package/src/components/ui/file-manager/file-manager-action-bar.tsx +1 -1
- package/src/components/ui/file-manager/file-manager.tsx +1 -1
- package/src/components/ui/filter-modal.tsx +8 -1
- package/src/components/ui/highlight-card.tsx +7 -7
- package/src/components/ui/info-card-row.tsx +10 -6
- package/src/components/ui/modal-v2.tsx +7 -2
- package/src/components/ui/modal.tsx +3 -2
- package/src/components/ui/no-data/no-data-actions.tsx +10 -4
- package/src/components/ui/no-data/no-data-styles.ts +1 -1
- package/src/components/ui/no-data/no-data.tsx +1 -1
- package/src/components/ui/organization-card.tsx +1 -1
- package/src/components/ui/page-actions.tsx +34 -5
- package/src/components/ui/panel-resize-handle.tsx +184 -0
- package/src/components/ui/progress-bar.tsx +2 -2
- package/src/components/ui/query-report-table/query-report-table.tsx +1 -1
- package/src/components/ui/search-input.tsx +2 -2
- package/src/components/ui/service-card.tsx +2 -2
- package/src/components/ui/sheet.tsx +2 -1
- package/src/components/ui/skeleton.tsx +3 -3
- package/src/components/ui/stacked-rows-panel.tsx +4 -4
- package/src/components/ui/tab-navigation.tsx +2 -2
- package/src/components/ui/tab-selector.tsx +2 -2
- package/src/components/ui/table/table-header.tsx +3 -3
- package/src/components/ui/table/table-skeleton.tsx +3 -3
- package/src/components/ui/table/utils.ts +5 -5
- package/src/components/ui/tag-search-input.tsx +3 -3
- package/src/components/ui/tags-manager.tsx +5 -5
- package/src/components/ui/test-run.tsx +2 -2
- package/src/components/ui/ticket-info-section.tsx +1 -1
- package/src/components/ui/ticket-notes-section.tsx +1 -1
- package/src/components/ui/ticket-status-config-row.tsx +15 -15
- package/src/hooks/ui/index.ts +1 -0
- package/src/hooks/ui/use-content-breakpoint.ts +58 -0
- package/src/hooks/ui/use-media-query.ts +3 -2
- package/src/hooks/ui/use-resizable-panel-size.ts +114 -0
- package/src/styles/index.css +2 -0
- package/src/styles/layout-steps.ts +14 -0
- package/src/styles/ods-colors.css +15 -0
- package/src/styles/ods-content-area-tokens.css +27 -0
- package/src/styles/ods-content-area.css +31 -0
- package/src/styles/ods-effects.css +4 -2
- package/src/styles/ods-responsive-tokens.css +14 -4
- package/tailwind.config.ts +42 -7
|
@@ -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(
|
|
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(
|
|
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 &&
|
|
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
|
-
{
|
|
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
|
·
|
|
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
|
|
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 =>
|
|
24
|
+
const hideClasses = breakpoints.map(bp => `content-${bp}:hidden`).join(' ');
|
|
25
25
|
const showBreakpoint = BREAKPOINT_ORDER[maxIdx + 1];
|
|
26
|
-
return showBreakpoint ? `${hideClasses}
|
|
26
|
+
return showBreakpoint ? `${hideClasses} content-${showBreakpoint}:flex` : hideClasses;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -4,6 +4,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
|
4
4
|
import { X } from 'lucide-react';
|
|
5
5
|
import { type ComponentPropsWithoutRef, type ElementRef, type HTMLAttributes, forwardRef } from 'react';
|
|
6
6
|
|
|
7
|
+
import { ViewportBreakpoints } from '../../hooks/ui/use-content-breakpoint';
|
|
7
8
|
import { cn } from '../../utils/cn';
|
|
8
9
|
|
|
9
10
|
const Dialog = DialogPrimitive.Root;
|
|
@@ -65,7 +66,9 @@ const DialogContent = forwardRef<
|
|
|
65
66
|
{/* min-h-0 is load-bearing: a grid item defaults to min-height:auto and
|
|
66
67
|
would refuse to shrink below its content, so the cap above would push
|
|
67
68
|
past the viewport instead of handing this box a scrollbar. */}
|
|
68
|
-
<div className="grid min-h-0 gap-[var(--spacing-system-mf)] overflow-y-auto">
|
|
69
|
+
<div className="grid min-h-0 gap-[var(--spacing-system-mf)] overflow-y-auto">
|
|
70
|
+
<ViewportBreakpoints>{children}</ViewportBreakpoints>
|
|
71
|
+
</div>
|
|
69
72
|
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
|
70
73
|
<X className="h-4 w-4" />
|
|
71
74
|
<span className="sr-only">Close</span>
|