@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
|
@@ -93,7 +93,7 @@ export function TicketStatusConfigRow({
|
|
|
93
93
|
<div
|
|
94
94
|
className={cn(
|
|
95
95
|
// Transparent background — only the border outlines the row.
|
|
96
|
-
'flex w-full items-start gap-3 rounded-md border border-ods-border md:gap-[var(--spacing-system-m)]',
|
|
96
|
+
'flex w-full items-start gap-3 rounded-md border border-ods-border content-md:gap-[var(--spacing-system-m)]',
|
|
97
97
|
'p-[var(--spacing-system-m)]',
|
|
98
98
|
// The dragged row travels over its siblings, so it needs an opaque back.
|
|
99
99
|
isDragging && 'bg-ods-bg opacity-70 shadow-lg',
|
|
@@ -102,7 +102,7 @@ export function TicketStatusConfigRow({
|
|
|
102
102
|
{dragAndDropEnabled && (
|
|
103
103
|
<div
|
|
104
104
|
className={cn(
|
|
105
|
-
'flex h-11 w-8 shrink-0 items-center justify-center text-ods-text-secondary md:h-12',
|
|
105
|
+
'flex h-11 w-8 shrink-0 items-center justify-center text-ods-text-secondary content-md:h-12',
|
|
106
106
|
fieldRowOffset,
|
|
107
107
|
)}
|
|
108
108
|
>
|
|
@@ -131,14 +131,14 @@ export function TicketStatusConfigRow({
|
|
|
131
131
|
and the chip pins to the card's right edge on tablet/mobile. */}
|
|
132
132
|
<div
|
|
133
133
|
className={cn(
|
|
134
|
-
'min-w-0 flex-1 items-start gap-x-3 gap-y-[var(--spacing-system-m)] md:gap-x-[var(--spacing-system-m)]',
|
|
134
|
+
'min-w-0 flex-1 items-start gap-x-3 gap-y-[var(--spacing-system-m)] content-md:gap-x-[var(--spacing-system-m)]',
|
|
135
135
|
isSystem
|
|
136
136
|
? 'flex flex-wrap'
|
|
137
137
|
: // Mobile custom rows are a strict two-column grid, per the mock:
|
|
138
138
|
// fields (name / color / hex, all one width) on the left, the
|
|
139
139
|
// controls and the chip stacked in the right column. From md up
|
|
140
140
|
// the same children flow as a wrapping flex row.
|
|
141
|
-
'grid grid-cols-[minmax(0,1fr)_auto] md:flex md:flex-wrap',
|
|
141
|
+
'grid grid-cols-[minmax(0,1fr)_auto] content-md:flex content-md:flex-wrap',
|
|
142
142
|
)}
|
|
143
143
|
>
|
|
144
144
|
{/* System rows keep the chip beside the name on every width, so the name
|
|
@@ -158,7 +158,7 @@ export function TicketStatusConfigRow({
|
|
|
158
158
|
</div>
|
|
159
159
|
|
|
160
160
|
{showColorPicker ? (
|
|
161
|
-
<div className="order-3 flex min-w-0 grow basis-full flex-col gap-[var(--spacing-system-xxs)] md:order-2 md:basis-0">
|
|
161
|
+
<div className="order-3 flex min-w-0 grow basis-full flex-col gap-[var(--spacing-system-xxs)] content-md:order-2 content-md:basis-0">
|
|
162
162
|
<Label variant="large">Color</Label>
|
|
163
163
|
<ColorPresetSelect value={color} presetKey={presetKey} onChange={onColorChange} />
|
|
164
164
|
{/* Custom hex: a second field row inside the Color column, directly
|
|
@@ -170,16 +170,16 @@ export function TicketStatusConfigRow({
|
|
|
170
170
|
)}
|
|
171
171
|
</div>
|
|
172
172
|
) : (
|
|
173
|
-
<div aria-hidden className="hidden min-w-0 grow basis-0 lg:order-2 lg:block" />
|
|
173
|
+
<div aria-hidden className="hidden min-w-0 grow basis-0 content-lg:order-2 content-lg:block" />
|
|
174
174
|
)}
|
|
175
175
|
|
|
176
176
|
{/* Reserved desktop column slot (the mock's "No activity Indicator" zone). */}
|
|
177
|
-
<div aria-hidden className="hidden min-w-0 grow basis-0 lg:order-3 lg:block" />
|
|
177
|
+
<div aria-hidden className="hidden min-w-0 grow basis-0 content-lg:order-3 content-lg:block" />
|
|
178
178
|
|
|
179
179
|
{isSystem ? (
|
|
180
180
|
<div
|
|
181
181
|
className={cn(
|
|
182
|
-
'order-2 flex h-11 min-w-0 grow basis-0 items-center justify-end md:h-12 lg:order-4',
|
|
182
|
+
'order-2 flex h-11 min-w-0 grow basis-0 items-center justify-end content-md:h-12 content-lg:order-4',
|
|
183
183
|
fieldRowOffset,
|
|
184
184
|
)}
|
|
185
185
|
>
|
|
@@ -191,7 +191,7 @@ export function TicketStatusConfigRow({
|
|
|
191
191
|
before the controls. */}
|
|
192
192
|
<div
|
|
193
193
|
className={cn(
|
|
194
|
-
'hidden h-12 min-w-0 grow basis-0 items-center justify-end lg:order-4 lg:flex',
|
|
194
|
+
'hidden h-12 min-w-0 grow basis-0 items-center justify-end content-lg:order-4 content-lg:flex',
|
|
195
195
|
fieldRowOffset,
|
|
196
196
|
)}
|
|
197
197
|
>
|
|
@@ -199,25 +199,25 @@ export function TicketStatusConfigRow({
|
|
|
199
199
|
</div>
|
|
200
200
|
{/* Tablet: the chip takes a full row of its own, pinned to the
|
|
201
201
|
card's right edge (the controls above no longer narrow it). */}
|
|
202
|
-
<div className="hidden min-w-0 basis-full items-center justify-end md:order-4 md:flex lg:hidden">
|
|
202
|
+
<div className="hidden min-w-0 basis-full items-center justify-end content-md:order-4 content-md:flex content-lg:hidden">
|
|
203
203
|
{chip}
|
|
204
204
|
</div>
|
|
205
205
|
{/* Mobile: the chip fills the second grid column beside the color
|
|
206
206
|
field, left-aligned with the controls above it. */}
|
|
207
|
-
<div className={cn('order-4 flex h-11 min-w-0 items-center md:hidden', fieldRowOffset)}>{chip}</div>
|
|
207
|
+
<div className={cn('order-4 flex h-11 min-w-0 items-center content-md:hidden', fieldRowOffset)}>{chip}</div>
|
|
208
208
|
</>
|
|
209
209
|
)}
|
|
210
210
|
|
|
211
211
|
<div
|
|
212
212
|
className={cn(
|
|
213
|
-
'flex h-11 shrink-0 items-center justify-end gap-[var(--spacing-system-s)] md:h-12 lg:order-5',
|
|
214
|
-
isSystem ? 'order-3' : 'order-2 md:order-3',
|
|
213
|
+
'flex h-11 shrink-0 items-center justify-end gap-[var(--spacing-system-s)] content-md:h-12 content-lg:order-5',
|
|
214
|
+
isSystem ? 'order-3' : 'order-2 content-md:order-3',
|
|
215
215
|
fieldRowOffset,
|
|
216
216
|
)}
|
|
217
217
|
>
|
|
218
218
|
{!isSystem && moveButtons}
|
|
219
219
|
{isSystem ? (
|
|
220
|
-
<div className="flex w-11 justify-center md:w-12">
|
|
220
|
+
<div className="flex w-11 justify-center content-md:w-12">
|
|
221
221
|
<TouchFriendlyTooltip content={systemTooltip}>
|
|
222
222
|
<button
|
|
223
223
|
type="button"
|
|
@@ -238,7 +238,7 @@ export function TicketStatusConfigRow({
|
|
|
238
238
|
aria-label="Delete status"
|
|
239
239
|
disabled={deleteDisabled}
|
|
240
240
|
onClick={deleteDisabled ? undefined : onDelete}
|
|
241
|
-
className={cn('size-11 md:size-12', deleteDisabled && 'pointer-events-none')}
|
|
241
|
+
className={cn('size-11 content-md:size-12', deleteDisabled && 'pointer-events-none')}
|
|
242
242
|
>
|
|
243
243
|
<TrashIcon className="text-ods-error" />
|
|
244
244
|
</Button>
|
package/src/hooks/ui/index.ts
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, createElement, type ReactNode, useContext } from 'react';
|
|
4
|
+
import { LAYOUT_STEPS } from '../../styles/layout-steps';
|
|
5
|
+
import { useLgUp, useMdUp } from './use-media-query';
|
|
6
|
+
|
|
7
|
+
export type ContentBreakpoint = 'mobile' | 'tablet' | 'desktop';
|
|
8
|
+
|
|
9
|
+
/** Content-area steps, in px of the area's own width. */
|
|
10
|
+
export const CONTENT_BREAKPOINTS = { md: LAYOUT_STEPS.md.content, lg: LAYOUT_STEPS.lg.content } as const;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Width of the enclosing content area (`AppLayout` with a side panel provides
|
|
14
|
+
* it), or `null` outside one.
|
|
15
|
+
*/
|
|
16
|
+
export const ContentAreaWidthContext = createContext<number | null>(null);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* For window chrome opened from a content area (a modal, a drawer): its subtree
|
|
20
|
+
* is back on the viewport's steps. Context crosses a portal, so without this
|
|
21
|
+
* the hooks below would still answer with the content area's width.
|
|
22
|
+
*/
|
|
23
|
+
export function ViewportBreakpoints({ children }: { children: ReactNode }) {
|
|
24
|
+
return createElement(ContentAreaWidthContext.Provider, { value: null }, children);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function contentBreakpointFor(width: number): ContentBreakpoint {
|
|
28
|
+
if (width >= CONTENT_BREAKPOINTS.lg) return 'desktop';
|
|
29
|
+
if (width >= CONTENT_BREAKPOINTS.md) return 'tablet';
|
|
30
|
+
return 'mobile';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The breakpoint a component should lay out for: the content area's when it
|
|
35
|
+
* renders inside one, the viewport's otherwise. `undefined` until the viewport
|
|
36
|
+
* is known (first client render), like `useMdUp`.
|
|
37
|
+
*/
|
|
38
|
+
export function useContentBreakpoint(): ContentBreakpoint | undefined {
|
|
39
|
+
const width = useContext(ContentAreaWidthContext);
|
|
40
|
+
const mdUp = useMdUp();
|
|
41
|
+
const lgUp = useLgUp();
|
|
42
|
+
if (width !== null) return contentBreakpointFor(width);
|
|
43
|
+
if (mdUp === undefined) return undefined;
|
|
44
|
+
if (lgUp) return 'desktop';
|
|
45
|
+
return mdUp ? 'tablet' : 'mobile';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Content-area counterpart of `useMdUp`. */
|
|
49
|
+
export function useContentMdUp(): boolean | undefined {
|
|
50
|
+
const breakpoint = useContentBreakpoint();
|
|
51
|
+
return breakpoint === undefined ? undefined : breakpoint !== 'mobile';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Content-area counterpart of `useLgUp`. */
|
|
55
|
+
export function useContentLgUp(): boolean | undefined {
|
|
56
|
+
const breakpoint = useContentBreakpoint();
|
|
57
|
+
return breakpoint === undefined ? undefined : breakpoint === 'desktop';
|
|
58
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
+
import { LAYOUT_STEPS } from '../../styles/layout-steps';
|
|
4
5
|
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -35,8 +36,8 @@ export function useMediaQuery(query: string): boolean | undefined {
|
|
|
35
36
|
* Predefined breakpoints for common screen sizes
|
|
36
37
|
*/
|
|
37
38
|
export const breakpoints = {
|
|
38
|
-
md:
|
|
39
|
-
lg:
|
|
39
|
+
md: `(min-width: ${LAYOUT_STEPS.md.viewport}px)`, // Tablet
|
|
40
|
+
lg: `(min-width: ${LAYOUT_STEPS.lg.viewport}px)`, // Desktop
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
/** @deprecated Use useMdUp instead */
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { clamp } from '../../utils/common';
|
|
6
|
+
import { createLocalStorageAdapter } from '../../utils/local-storage-adapter';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The size of a drag-to-resize panel (`Drawer`, `AppLayoutDrawer`).
|
|
10
|
+
*
|
|
11
|
+
* Two values are kept apart, and only one of them is ever stored:
|
|
12
|
+
*
|
|
13
|
+
* - the size the user CHOSE (a drag or a key press on the handle), stored, and
|
|
14
|
+
* `null` until they choose one;
|
|
15
|
+
* - the size RENDERED, derived on every render from the choice (or, without
|
|
16
|
+
* one, from `defaultSize`) and clamped to the room there is right now.
|
|
17
|
+
*
|
|
18
|
+
* The room changing never writes anything. A narrow window, docked dev tools or
|
|
19
|
+
* a phone-sized emulation shrink the panel for as long as they last and the
|
|
20
|
+
* chosen size comes back with the room. A panel nobody resized follows
|
|
21
|
+
* `defaultSize`: given as a function of the room, it tracks the window, and a
|
|
22
|
+
* changed default reaches everyone who never chose a size.
|
|
23
|
+
*
|
|
24
|
+
* The choice is stored as `{ size }` under `<storageKey>:chosen`, never under
|
|
25
|
+
* `storageKey` itself. The previous implementation wrote a bare number there,
|
|
26
|
+
* defaults and clamped sizes included, so that value cannot be told apart from
|
|
27
|
+
* a real choice and is not read; and a page still running that implementation
|
|
28
|
+
* (a tab left open across a deploy) keeps writing it, which must not replace
|
|
29
|
+
* the choice.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** A fixed size in px, or one computed from the room along the resize axis
|
|
33
|
+
* (0 while the room is not measured, and on the server). */
|
|
34
|
+
export type PanelDefaultSize = number | ((available: number) => number);
|
|
35
|
+
|
|
36
|
+
const CHOSEN_SIZE_KEY_SUFFIX = ':chosen';
|
|
37
|
+
|
|
38
|
+
export interface UseResizablePanelSizeArgs {
|
|
39
|
+
/** False leaves the panel at `defaultSize` and reads or writes nothing. */
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
minSize: number;
|
|
42
|
+
maxSize: number;
|
|
43
|
+
/** Size while the user has chosen none. */
|
|
44
|
+
defaultSize: PanelDefaultSize;
|
|
45
|
+
/** Room along the resize axis, in px. 0 while it is not measured yet. */
|
|
46
|
+
available: number;
|
|
47
|
+
/** Px of `available` the panel never takes (the gap that keeps the handle on screen). */
|
|
48
|
+
reserve: number;
|
|
49
|
+
/** Base localStorage key for the chosen size. Omit to keep it for the mount only. */
|
|
50
|
+
storageKey?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface StoredPanelSize {
|
|
54
|
+
size: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function isStoredPanelSize(value: unknown): value is StoredPanelSize {
|
|
58
|
+
if (typeof value !== 'object' || value === null) return false;
|
|
59
|
+
const { size } = value as { size?: unknown };
|
|
60
|
+
return typeof size === 'number' && Number.isFinite(size) && size > 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function useResizablePanelSize({
|
|
64
|
+
enabled,
|
|
65
|
+
minSize,
|
|
66
|
+
maxSize,
|
|
67
|
+
defaultSize,
|
|
68
|
+
available,
|
|
69
|
+
reserve,
|
|
70
|
+
storageKey,
|
|
71
|
+
}: UseResizablePanelSizeArgs) {
|
|
72
|
+
const storage = useMemo(
|
|
73
|
+
() =>
|
|
74
|
+
enabled && storageKey
|
|
75
|
+
? createLocalStorageAdapter<StoredPanelSize>({
|
|
76
|
+
key: `${storageKey}${CHOSEN_SIZE_KEY_SUFFIX}`,
|
|
77
|
+
validate: isStoredPanelSize,
|
|
78
|
+
logTag: `[panel-size:${storageKey}]`,
|
|
79
|
+
})
|
|
80
|
+
: null,
|
|
81
|
+
[enabled, storageKey],
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// The choice belongs to the storage it was read from. When that changes (a
|
|
85
|
+
// drawer reused under another key, or resizing switched on after mount) it is
|
|
86
|
+
// read again during render, so no frame shows the other key's size.
|
|
87
|
+
const [held, setChosen] = useState(() => ({ storage, size: storage?.load()?.size ?? null }));
|
|
88
|
+
const chosen = held.storage === storage ? held : { storage, size: storage?.load()?.size ?? null };
|
|
89
|
+
if (chosen !== held) setChosen(chosen);
|
|
90
|
+
const chosenSize = chosen.size;
|
|
91
|
+
|
|
92
|
+
const clampSize = useCallback(
|
|
93
|
+
(value: number) => {
|
|
94
|
+
const ceiling = available > 0 ? Math.min(maxSize, available - reserve) : maxSize;
|
|
95
|
+
return clamp(value, minSize, Math.max(minSize, ceiling));
|
|
96
|
+
},
|
|
97
|
+
[available, reserve, minSize, maxSize],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const fallbackSize = typeof defaultSize === 'function' ? defaultSize(available) : defaultSize;
|
|
101
|
+
const size = enabled ? clampSize(chosenSize ?? fallbackSize) : fallbackSize;
|
|
102
|
+
|
|
103
|
+
/** The user's choice. The only path that stores a size. */
|
|
104
|
+
const setSize = useCallback(
|
|
105
|
+
(next: number) => {
|
|
106
|
+
const nextSize = Math.round(clampSize(next));
|
|
107
|
+
setChosen({ storage, size: nextSize });
|
|
108
|
+
storage?.save({ size: nextSize });
|
|
109
|
+
},
|
|
110
|
+
[clampSize, storage],
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return { size, setSize, clampSize };
|
|
114
|
+
}
|
package/src/styles/index.css
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
@import './ods-interaction-states.css';
|
|
6
6
|
@import './ods-effects.css';
|
|
7
7
|
@import './ods-responsive-tokens.css';
|
|
8
|
+
@import './ods-content-area.css';
|
|
9
|
+
@import './ods-content-area-tokens.css';
|
|
8
10
|
@import './app-globals.css';
|
|
9
11
|
@import './chat-animations.css';
|
|
10
12
|
@import './ods-page-shell.css';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout steps in px, the one place they are written. `viewport` is the window
|
|
3
|
+
* step (`md:`, `useMdUp`), `content` its content-area counterpart
|
|
4
|
+
* (`content-md:`, `useContentMdUp`): the viewport step less the navigation.
|
|
5
|
+
*
|
|
6
|
+
* Imported by tailwind.config.ts, so it must stay free of imports and aliases.
|
|
7
|
+
*/
|
|
8
|
+
export const LAYOUT_STEPS = {
|
|
9
|
+
sm: { viewport: 640, content: 640 },
|
|
10
|
+
md: { viewport: 800, content: 720 },
|
|
11
|
+
lg: { viewport: 1280, content: 1024 },
|
|
12
|
+
xl: { viewport: 1440, content: 1216 },
|
|
13
|
+
'2xl': { viewport: 1536, content: 1312 },
|
|
14
|
+
} as const;
|
|
@@ -417,6 +417,21 @@
|
|
|
417
417
|
--color-bg: color-mix(in srgb, var(--color-accent-primary) 2%, var(--ods-system-greys-background));
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
+
/* Mingo's own surface (Figma backgrounds/mingo-background): 2% of its cyan
|
|
421
|
+
* over the page background, whatever the tenant accent. */
|
|
422
|
+
[data-surface='mingo'] {
|
|
423
|
+
--color-bg: color-mix(in srgb, var(--ods-flamingo-cyan-base) 2%, var(--ods-system-greys-background));
|
|
424
|
+
--glow-color: var(--ods-flamingo-cyan-base);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/* Mingo-branded controls (its chat list): the cyan as the accent, and the
|
|
428
|
+
* selection fill (Figma flamingo-colors/cyan-sec) as its secondary. Scoped to
|
|
429
|
+
* those controls, not the whole panel: an approval's Approve stays yellow. */
|
|
430
|
+
[data-accent='mingo'] {
|
|
431
|
+
--color-accent-primary: var(--ods-flamingo-cyan-base);
|
|
432
|
+
--color-accent-secondary: color-mix(in srgb, var(--ods-flamingo-cyan-base) 31%, var(--color-bg));
|
|
433
|
+
}
|
|
434
|
+
|
|
420
435
|
/* ===================================================================== */
|
|
421
436
|
/* PLATFORM OVERRIDES — brand/accent ONLY. */
|
|
422
437
|
/* Reference `--ods-*` so they follow the active theme; never touch */
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* GENERATED from ods-responsive-tokens.css. Do not edit: `npm run generate:content-area`. */
|
|
2
|
+
|
|
3
|
+
@container ods-content not (min-width: 720px) {
|
|
4
|
+
.ods-content-scope {
|
|
5
|
+
--device-type: mobile;
|
|
6
|
+
--device-screen-width: 26.875rem;
|
|
7
|
+
--spacing-system-xs: 0.25rem;
|
|
8
|
+
--spacing-system-s: 0.5rem;
|
|
9
|
+
--spacing-system-m: 0.75rem;
|
|
10
|
+
--spacing-system-l: 1rem;
|
|
11
|
+
--spacing-system-xl: 1.5rem;
|
|
12
|
+
--spacing-system-xxl: 2.5rem;
|
|
13
|
+
--font-size-h1-title: 2.5rem;
|
|
14
|
+
--font-size-h2-sub-title: 1.5rem;
|
|
15
|
+
--font-size-h3-body: 0.875rem;
|
|
16
|
+
--font-size-h4-body: 0.875rem;
|
|
17
|
+
--font-size-h5-caption: 0.75rem;
|
|
18
|
+
--font-size-h6-caption: 0.75rem;
|
|
19
|
+
--font-line-space-h1-main-title: 2.5rem;
|
|
20
|
+
--font-line-space-h2-sub-title: 2rem;
|
|
21
|
+
--font-line-space-h3-body: 1.25rem;
|
|
22
|
+
--font-line-space-h4-body: 1.25rem;
|
|
23
|
+
--font-line-space-h5-caption: 1rem;
|
|
24
|
+
--font-line-space-h6-caption: 1rem;
|
|
25
|
+
--icon-size-icon-size: 1rem;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Open Design System – Content Area Tokens */
|
|
2
|
+
/*
|
|
3
|
+
* The responsive tokens in ods-responsive-tokens.css follow the VIEWPORT. A
|
|
4
|
+
* layout with a docked side panel narrows the content area without the
|
|
5
|
+
* viewport changing, so content inside `.ods-content-area` follows its OWN
|
|
6
|
+
* width instead:
|
|
7
|
+
*
|
|
8
|
+
* - `.ods-content-area` is a named inline-size container (`ods-content`).
|
|
9
|
+
* - `.ods-content-scope` sits inside it and re-declares the mobile tokens
|
|
10
|
+
* while the area is narrower than the content `md` step
|
|
11
|
+
* (ods-content-area-tokens.css, generated). The variables cascade, so
|
|
12
|
+
* every `text-h*` and `var(--spacing-system-*)` below the scope picks
|
|
13
|
+
* them up with no change to the components.
|
|
14
|
+
* - From that step up the scope declares nothing and inherits the viewport
|
|
15
|
+
* tokens from :root, so a wide content area renders exactly as before.
|
|
16
|
+
*
|
|
17
|
+
* A container query cannot style the container itself, hence two elements.
|
|
18
|
+
* The scope is `display: contents`: it carries the variables without adding a
|
|
19
|
+
* box, so pages keep `<main>` as their layout parent.
|
|
20
|
+
*
|
|
21
|
+
* Layout switches inside the area use the `content-md:` / `content-lg:`
|
|
22
|
+
* Tailwind variants. The steps themselves live in layout-steps.ts.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
.ods-content-area {
|
|
26
|
+
container: ods-content / inline-size;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ods-content-scope {
|
|
30
|
+
display: contents;
|
|
31
|
+
}
|
|
@@ -57,10 +57,12 @@
|
|
|
57
57
|
the corner, radii 100% × 103% as in the design). Written
|
|
58
58
|
on the class, not as a :root variable, so the accent resolves on the element
|
|
59
59
|
and follows a platform or runtime (tenant) accent set below the root. */
|
|
60
|
+
/* The color is `--glow-color` when a surface sets one (Mingo's cyan), the
|
|
61
|
+
accent otherwise. */
|
|
60
62
|
.ods-glow-accent-corner {
|
|
61
63
|
background-image: radial-gradient(
|
|
62
64
|
100% 103% at 100% 100%,
|
|
63
|
-
color-mix(in srgb, var(--color-accent-primary) 4%, transparent) 0%,
|
|
64
|
-
color-mix(in srgb, var(--color-accent-primary) 0%, transparent) 100%
|
|
65
|
+
color-mix(in srgb, var(--glow-color, var(--color-accent-primary)) 4%, transparent) 0%,
|
|
66
|
+
color-mix(in srgb, var(--glow-color, var(--color-accent-primary)) 0%, transparent) 100%
|
|
65
67
|
);
|
|
66
68
|
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
/* Open Design System – Responsive Design Tokens */
|
|
2
2
|
/* Mobile-first approach: base = mobile, then scale up with min-width */
|
|
3
|
-
|
|
4
|
-
:
|
|
3
|
+
/*
|
|
4
|
+
* `.ods-viewport-layer` restates the same values on an element: chrome that
|
|
5
|
+
* follows the WINDOW (a modal, a drawer) but renders inside a narrow content
|
|
6
|
+
* area, whose scope re-declares the mobile values
|
|
7
|
+
* (ods-content-area-tokens.css), gets the viewport's tokens back for its own
|
|
8
|
+
* subtree.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
:root,
|
|
12
|
+
.ods-viewport-layer {
|
|
5
13
|
/* =================================================== */
|
|
6
14
|
/* DEVICE CONTEXT */
|
|
7
15
|
/* =================================================== */
|
|
@@ -77,7 +85,8 @@
|
|
|
77
85
|
/* =================================================== */
|
|
78
86
|
|
|
79
87
|
@media (min-width: 800px) {
|
|
80
|
-
:root
|
|
88
|
+
:root,
|
|
89
|
+
.ods-viewport-layer {
|
|
81
90
|
/* Device Context */
|
|
82
91
|
--device-type: tablet;
|
|
83
92
|
--device-screen-width: 50rem;
|
|
@@ -122,7 +131,8 @@
|
|
|
122
131
|
/* =================================================== */
|
|
123
132
|
|
|
124
133
|
@media (min-width: 1280px) {
|
|
125
|
-
:root
|
|
134
|
+
:root,
|
|
135
|
+
.ods-viewport-layer {
|
|
126
136
|
/* Device Context */
|
|
127
137
|
--device-type: desktop;
|
|
128
138
|
--device-screen-width: 80rem;
|
package/tailwind.config.ts
CHANGED
|
@@ -2,6 +2,7 @@ import containerQueries from '@tailwindcss/container-queries';
|
|
|
2
2
|
import type { Config } from 'tailwindcss';
|
|
3
3
|
import tailwindcssAnimate from 'tailwindcss-animate';
|
|
4
4
|
import plugin from 'tailwindcss/plugin';
|
|
5
|
+
import { LAYOUT_STEPS } from './src/styles/layout-steps';
|
|
5
6
|
|
|
6
7
|
const odsTypographyPlugin = plugin(({ addUtilities }) => {
|
|
7
8
|
addUtilities({
|
|
@@ -78,6 +79,42 @@ const odsTypographyPlugin = plugin(({ addUtilities }) => {
|
|
|
78
79
|
});
|
|
79
80
|
});
|
|
80
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Content-area breakpoints: `content-md:` and friends apply by the width of the
|
|
84
|
+
* nearest `.ods-content-area`, not the viewport. Each step is the viewport
|
|
85
|
+
* step less the navigation sidebar (`sm` is phone-only, where there is none),
|
|
86
|
+
* so a page with nothing docked beside it switches where it did before.
|
|
87
|
+
*
|
|
88
|
+
* Outside a content area (apps without a side panel, overlays portalled to
|
|
89
|
+
* <body>) each falls back to its viewport step, so a component can switch to
|
|
90
|
+
* them without changing anywhere else it renders. So does everything under an
|
|
91
|
+
* `.ods-viewport-layer`: a modal or drawer that renders inside the content
|
|
92
|
+
* area but follows the window.
|
|
93
|
+
*
|
|
94
|
+
* Registered `max-*` first and then ascending, like Tailwind's own screens, so
|
|
95
|
+
* a wider step wins over a narrower one on the same property.
|
|
96
|
+
*/
|
|
97
|
+
const CONTENT_STEPS = Object.entries(LAYOUT_STEPS).map(([name, step]) => ({ name, ...step }));
|
|
98
|
+
|
|
99
|
+
const odsContentAreaPlugin = plugin(({ addVariant }) => {
|
|
100
|
+
const viewportLayer = '.ods-viewport-layer, .ods-viewport-layer *';
|
|
101
|
+
const byContent = `&:where(:not(${viewportLayer}))`;
|
|
102
|
+
const byViewport = `&:where(:not(.ods-content-area *), ${viewportLayer})`;
|
|
103
|
+
for (const { name, content, viewport } of CONTENT_STEPS) {
|
|
104
|
+
if (name !== 'md' && name !== 'lg') continue;
|
|
105
|
+
addVariant(`content-max-${name}`, [
|
|
106
|
+
`@container ods-content not (min-width: ${content}px) { ${byContent} }`,
|
|
107
|
+
`@media not all and (min-width: ${viewport}px) { ${byViewport} }`,
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
for (const { name, content, viewport } of CONTENT_STEPS) {
|
|
111
|
+
addVariant(`content-${name}`, [
|
|
112
|
+
`@container ods-content (min-width: ${content}px) { ${byContent} }`,
|
|
113
|
+
`@media (min-width: ${viewport}px) { ${byViewport} }`,
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
81
118
|
/**
|
|
82
119
|
* Make Tailwind opacity modifiers (`bg-ods-error/10`, `hover:bg-ods-accent/90`, …)
|
|
83
120
|
* actually work on var()-based ODS tokens. Without `<alpha-value>` in the color
|
|
@@ -106,6 +143,8 @@ const config: Config = {
|
|
|
106
143
|
'lg:hidden',
|
|
107
144
|
'md:flex',
|
|
108
145
|
'lg:flex',
|
|
146
|
+
// ...and their content-area forms (DataTable `hideAt`)
|
|
147
|
+
...['md', 'lg', 'xl', '2xl'].flatMap(step => [`content-${step}:hidden`, `content-${step}:flex`]),
|
|
109
148
|
],
|
|
110
149
|
theme: {
|
|
111
150
|
container: {
|
|
@@ -305,12 +344,8 @@ const config: Config = {
|
|
|
305
344
|
current: 'var(--ods-current)',
|
|
306
345
|
}),
|
|
307
346
|
},
|
|
308
|
-
//
|
|
309
|
-
screens: {
|
|
310
|
-
md: '800px', // Tablet: 50rem
|
|
311
|
-
lg: '1280px', // Desktop: 80rem
|
|
312
|
-
xl: '1440px', // Large desktop: 90rem
|
|
313
|
-
},
|
|
347
|
+
// Aligned with the ODS responsive tokens from Figma: md tablet, lg desktop.
|
|
348
|
+
screens: Object.fromEntries(CONTENT_STEPS.map(({ name, viewport }) => [name, `${viewport}px`])),
|
|
314
349
|
|
|
315
350
|
borderRadius: {
|
|
316
351
|
lg: 'var(--radius)', // 8px
|
|
@@ -429,7 +464,7 @@ const config: Config = {
|
|
|
429
464
|
},
|
|
430
465
|
},
|
|
431
466
|
},
|
|
432
|
-
plugins: [tailwindcssAnimate, odsTypographyPlugin, containerQueries],
|
|
467
|
+
plugins: [tailwindcssAnimate, odsTypographyPlugin, odsContentAreaPlugin, containerQueries],
|
|
433
468
|
};
|
|
434
469
|
|
|
435
470
|
export default config;
|