basalt-ui 1.25.0 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -6
- package/CHANGELOG.md +18 -0
- package/MIGRATING.md +546 -20
- package/README.md +45 -32
- package/agent/rules/basalt-batteries.md +205 -0
- package/agent/rules/basalt-charts.md +125 -555
- package/agent/rules/basalt-controls.md +155 -0
- package/agent/rules/basalt-mantine.md +146 -439
- package/agent/rules/basalt-state.md +113 -96
- package/agent/rules/basalt-tokens.md +126 -288
- package/agent/skills/basalt-app/SKILL.md +70 -195
- package/agent/skills/basalt-charts/SKILL.md +54 -234
- package/agent/skills/basalt-design/SKILL.md +56 -248
- package/agent/templates/CLAUDE-block.md.tpl +31 -40
- package/agent/templates/DESIGN.md.tpl +22 -51
- package/configs/oxlint-plugin.js +1275 -31
- package/configs/oxlint-plugin.test.ts +947 -11
- package/configs/oxlint.json +11 -3
- package/dist/charts/cursor/resolve.d.ts +18 -0
- package/dist/charts/cursor/resolve.d.ts.map +1 -1
- package/dist/charts/cursor/resolve.js +15 -6
- package/dist/charts/cursor/scope.d.ts +6 -3
- package/dist/charts/cursor/scope.d.ts.map +1 -1
- package/dist/charts/cursor/store.d.ts +5 -1
- package/dist/charts/cursor/store.d.ts.map +1 -1
- package/dist/charts/cursor/store.js +4 -4
- package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
- package/dist/charts/hooks/useChartCursor.js +9 -8
- package/dist/charts/index.d.ts +2 -2
- package/dist/charts/index.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.d.ts +34 -9
- package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
- package/dist/charts/primitives/ChartCard.js +29 -114
- package/dist/charts/primitives/ChartCard.test.d.ts +2 -0
- package/dist/charts/primitives/ChartCard.test.d.ts.map +1 -0
- package/dist/charts/sparklines/BarSparkline.d.ts +26 -2
- package/dist/charts/sparklines/BarSparkline.d.ts.map +1 -1
- package/dist/charts/sparklines/BarSparkline.js +18 -4
- package/dist/cli/check-coverage.test.d.ts +2 -0
- package/dist/cli/check-coverage.test.d.ts.map +1 -0
- package/dist/cli/index.d.ts +67 -4
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +225 -7
- package/dist/connectivity/connectivity-indicator.d.ts +4 -1
- package/dist/connectivity/connectivity-indicator.d.ts.map +1 -1
- package/dist/connectivity/connectivity-indicator.js +1 -1
- package/dist/content/index.d.ts +5 -3
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -2
- package/dist/content/prose.module.css +7 -28
- package/dist/controls/actions.d.ts +169 -0
- package/dist/controls/actions.d.ts.map +1 -0
- package/dist/controls/actions.js +287 -0
- package/dist/controls/actions.module.css +62 -0
- package/dist/controls/actions.module.css.d.ts +13 -0
- package/dist/controls/actions.test.d.ts +2 -0
- package/dist/controls/actions.test.d.ts.map +1 -0
- package/dist/controls/actions.type-guard.test.d.ts +2 -0
- package/dist/controls/actions.type-guard.test.d.ts.map +1 -0
- package/dist/controls/compare-filter.d.ts +41 -0
- package/dist/controls/compare-filter.d.ts.map +1 -0
- package/dist/controls/compare-filter.js +23 -0
- package/dist/controls/control-group.d.ts +19 -0
- package/dist/controls/control-group.d.ts.map +1 -0
- package/dist/controls/control-group.js +20 -0
- package/dist/controls/control-group.test.d.ts +2 -0
- package/dist/controls/control-group.test.d.ts.map +1 -0
- package/dist/controls/controls.module.css +542 -0
- package/dist/controls/controls.module.css.d.ts +35 -0
- package/dist/controls/controls.router.test.d.ts +2 -0
- package/dist/controls/controls.router.test.d.ts.map +1 -0
- package/dist/controls/enum-filter.d.ts +30 -0
- package/dist/controls/enum-filter.d.ts.map +1 -0
- package/dist/controls/enum-filter.js +91 -0
- package/dist/controls/filter-context.d.ts +55 -0
- package/dist/controls/filter-context.d.ts.map +1 -0
- package/dist/controls/filter-context.js +69 -0
- package/dist/controls/filter-pill.d.ts +28 -0
- package/dist/controls/filter-pill.d.ts.map +1 -0
- package/dist/controls/filter-pill.js +70 -0
- package/dist/controls/filter-set.d.ts +13 -0
- package/dist/controls/filter-set.d.ts.map +1 -0
- package/dist/controls/filter-set.js +125 -0
- package/dist/controls/filter-set.test.d.ts +2 -0
- package/dist/controls/filter-set.test.d.ts.map +1 -0
- package/dist/controls/filter-sheet.d.ts +117 -0
- package/dist/controls/filter-sheet.d.ts.map +1 -0
- package/dist/controls/filter-sheet.js +146 -0
- package/dist/controls/glyphs.d.ts +27 -0
- package/dist/controls/glyphs.d.ts.map +1 -0
- package/dist/controls/glyphs.js +49 -0
- package/dist/controls/index.d.ts +19 -0
- package/dist/controls/index.d.ts.map +1 -0
- package/dist/controls/index.js +44 -0
- package/dist/controls/multi-select-filter.d.ts +23 -0
- package/dist/controls/multi-select-filter.d.ts.map +1 -0
- package/dist/controls/multi-select-filter.js +89 -0
- package/dist/controls/peer-boundary.test.d.ts +2 -0
- package/dist/controls/peer-boundary.test.d.ts.map +1 -0
- package/dist/controls/props-contract.test.d.ts +2 -0
- package/dist/controls/props-contract.test.d.ts.map +1 -0
- package/dist/controls/range-filter.d.ts +29 -0
- package/dist/controls/range-filter.d.ts.map +1 -0
- package/dist/controls/range-filter.js +120 -0
- package/dist/controls/search-filter.d.ts +10 -0
- package/dist/controls/search-filter.d.ts.map +1 -0
- package/dist/controls/search-filter.js +81 -0
- package/dist/controls/select-filter.d.ts +74 -0
- package/dist/controls/select-filter.d.ts.map +1 -0
- package/dist/controls/select-filter.js +10 -0
- package/dist/controls/sync-button.d.ts +38 -0
- package/dist/controls/sync-button.d.ts.map +1 -0
- package/dist/controls/sync-button.js +119 -0
- package/dist/controls/sync-button.module.css +63 -0
- package/dist/controls/sync-button.module.css.d.ts +11 -0
- package/dist/controls/sync-button.test.d.ts +2 -0
- package/dist/controls/sync-button.test.d.ts.map +1 -0
- package/dist/controls/toggle-filter.d.ts +9 -0
- package/dist/controls/toggle-filter.d.ts.map +1 -0
- package/dist/controls/toggle-filter.js +42 -0
- package/dist/controls/view-tabs.d.ts +23 -0
- package/dist/controls/view-tabs.d.ts.map +1 -0
- package/dist/controls/view-tabs.js +59 -0
- package/dist/controls-dates/date-range-picker.d.ts +4 -0
- package/dist/controls-dates/date-range-picker.d.ts.map +1 -0
- package/dist/controls-dates/date-range-picker.js +18 -0
- package/dist/controls-dates/index.d.ts +9 -0
- package/dist/controls-dates/index.d.ts.map +1 -0
- package/dist/controls-dates/index.js +4 -0
- package/dist/dashboard/delta-badge.d.ts +6 -12
- package/dist/dashboard/delta-badge.d.ts.map +1 -1
- package/dist/dashboard/delta-badge.js +1 -50
- package/dist/dashboard/settings-section.d.ts +6 -4
- package/dist/dashboard/settings-section.d.ts.map +1 -1
- package/dist/dashboard/settings-section.js +23 -16
- package/dist/dashboard/settings-section.module.css +10 -0
- package/dist/dashboard/settings-section.module.css.d.ts +1 -0
- package/dist/dashboard/settings-section.test.d.ts +2 -0
- package/dist/dashboard/settings-section.test.d.ts.map +1 -0
- package/dist/dashboard/stat-card.d.ts +44 -9
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +80 -48
- package/dist/dashboard/stat-card.module.css +82 -0
- package/dist/dashboard/stat-card.module.css.d.ts +11 -0
- package/dist/data/data-table.d.ts +37 -15
- package/dist/data/data-table.d.ts.map +1 -1
- package/dist/data/data-table.js +88 -58
- package/dist/guard/grace.test.d.ts +20 -0
- package/dist/guard/grace.test.d.ts.map +1 -0
- package/dist/guard/index.d.ts +66 -3
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +82 -7
- package/dist/guard/types.d.ts +3 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -10
- package/dist/nav/types.d.ts +78 -2
- package/dist/nav/types.d.ts.map +1 -1
- package/dist/notifications/bell.d.ts +4 -1
- package/dist/notifications/bell.d.ts.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/router-tanstack/field.d.ts +14 -0
- package/dist/router-tanstack/field.d.ts.map +1 -0
- package/dist/router-tanstack/field.js +4 -0
- package/dist/router-tanstack/index.d.ts +6 -2
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +4 -0
- package/dist/router-tanstack/multi-search-param-store.d.ts +4 -52
- package/dist/router-tanstack/multi-search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/multi-search-param-store.js +19 -27
- package/dist/router-tanstack/search-param-store.d.ts +3 -87
- package/dist/router-tanstack/search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/search-param-store.js +16 -45
- package/dist/router-tanstack/search-store.d.ts +81 -0
- package/dist/router-tanstack/search-store.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.js +187 -0
- package/dist/router-tanstack/search-store.router.test.d.ts +2 -0
- package/dist/router-tanstack/search-store.router.test.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.test.d.ts +2 -0
- package/dist/router-tanstack/search-store.test.d.ts.map +1 -0
- package/dist/router-tanstack/use-nav.d.ts +0 -2
- package/dist/router-tanstack/use-nav.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.js +34 -12
- package/dist/router-tanstack/use-nav.test.d.ts +2 -0
- package/dist/router-tanstack/use-nav.test.d.ts.map +1 -0
- package/dist/section/index.d.ts +2 -0
- package/dist/section/index.d.ts.map +1 -0
- package/dist/section/index.js +4 -0
- package/dist/section/section.d.ts +24 -0
- package/dist/section/section.d.ts.map +1 -0
- package/dist/section/section.js +126 -0
- package/dist/section/section.module.css +104 -0
- package/dist/section/section.module.css.d.ts +11 -0
- package/dist/section/section.test.d.ts +2 -0
- package/dist/section/section.test.d.ts.map +1 -0
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.js +18 -15
- package/dist/shell/app-header.module.css +77 -37
- package/dist/shell/app-header.module.css.d.ts +2 -1
- package/dist/shell/app-mobile-nav.d.ts +9 -2
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +98 -11
- package/dist/shell/app-mobile-nav.module.css +8 -0
- package/dist/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/dist/shell/app-sidebar.d.ts +55 -28
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +116 -67
- package/dist/shell/app-sidebar.module.css +303 -20
- package/dist/shell/app-sidebar.module.css.d.ts +19 -1
- package/dist/shell/index.d.ts +55 -21
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +40 -18
- package/dist/shell/mobile-nav-model.d.ts +13 -2
- package/dist/shell/mobile-nav-model.d.ts.map +1 -1
- package/dist/shell/mobile-nav-model.js +15 -1
- package/dist/shell/nav-count-badge.d.ts +1 -1
- package/dist/shell/page-bar.d.ts +51 -0
- package/dist/shell/page-bar.d.ts.map +1 -0
- package/dist/shell/page-bar.js +154 -0
- package/dist/shell/page-bar.module.css +178 -0
- package/dist/shell/page-bar.module.css.d.ts +17 -0
- package/dist/shell/page-bar.test.d.ts +2 -0
- package/dist/shell/page-bar.test.d.ts.map +1 -0
- package/dist/shell/sidebar-block-model.d.ts +48 -0
- package/dist/shell/sidebar-block-model.d.ts.map +1 -0
- package/dist/shell/sidebar-block-model.js +39 -0
- package/dist/shell/sidebar-blocks.d.ts +32 -0
- package/dist/shell/sidebar-blocks.d.ts.map +1 -0
- package/dist/shell/sidebar-blocks.js +169 -0
- package/dist/shell/sidebar-search.d.ts +13 -1
- package/dist/shell/sidebar-search.d.ts.map +1 -1
- package/dist/shell/sidebar-search.js +34 -1
- package/dist/shell/sidebar-search.module.css +26 -0
- package/dist/shell/sidebar-search.module.css.d.ts +2 -0
- package/dist/state/fields.d.ts +392 -0
- package/dist/state/fields.d.ts.map +1 -0
- package/dist/state/fields.js +369 -0
- package/dist/state/fields.test.d.ts +2 -0
- package/dist/state/fields.test.d.ts.map +1 -0
- package/dist/state/persisted.d.ts +48 -0
- package/dist/state/persisted.d.ts.map +1 -0
- package/dist/state/persisted.js +105 -0
- package/dist/state.d.ts +11 -56
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +14 -120
- package/dist/styles.css +13 -0
- package/dist/surfaces.d.ts +106 -24
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +155 -19
- package/dist/theme/controls.module.css +16 -1
- package/dist/theme/ctl-theme.d.ts +32 -0
- package/dist/theme/ctl-theme.d.ts.map +1 -0
- package/dist/theme/ctl-theme.js +54 -0
- package/dist/theme/ctl-theme.test.d.ts +2 -0
- package/dist/theme/ctl-theme.test.d.ts.map +1 -0
- package/dist/theme/ctl-tier-coverage.test.d.ts +2 -0
- package/dist/theme/ctl-tier-coverage.test.d.ts.map +1 -0
- package/dist/theme/divider-law.test.d.ts +2 -0
- package/dist/theme/divider-law.test.d.ts.map +1 -0
- package/dist/theme/icon-slot.d.ts +44 -0
- package/dist/theme/icon-slot.d.ts.map +1 -0
- package/dist/theme/icon-slot.js +21 -0
- package/dist/theme/icon-slot.module.css +47 -0
- package/dist/theme/icon-slot.module.css.d.ts +8 -0
- package/dist/theme/icon-slot.test.d.ts +2 -0
- package/dist/theme/icon-slot.test.d.ts.map +1 -0
- package/dist/theme/index.d.ts +1 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +82 -5
- package/dist/theme/layout-rhythm-css.test.d.ts +2 -0
- package/dist/theme/layout-rhythm-css.test.d.ts.map +1 -0
- package/dist/theme/segmented-control.module.css +20 -0
- package/dist/theme/shadow-surfaces.test.d.ts.map +1 -1
- package/dist/tokens/index.d.ts +12 -0
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +38 -8
- package/dist/tokens/palette.d.ts +97 -61
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +76 -38
- package/dist/tokens.css +10 -2
- package/dist/widget-header/delta-badge.d.ts +13 -0
- package/dist/widget-header/delta-badge.d.ts.map +1 -0
- package/dist/widget-header/delta-badge.js +29 -0
- package/dist/widget-header/delta-badge.test.d.ts +2 -0
- package/dist/widget-header/delta-badge.test.d.ts.map +1 -0
- package/dist/widget-header/index.d.ts +3 -0
- package/dist/widget-header/index.d.ts.map +1 -0
- package/dist/widget-header/index.js +6 -0
- package/dist/widget-header/no-mantine.test.d.ts +2 -0
- package/dist/widget-header/no-mantine.test.d.ts.map +1 -0
- package/dist/widget-header/widget-header.d.ts +37 -0
- package/dist/widget-header/widget-header.d.ts.map +1 -0
- package/dist/widget-header/widget-header.js +77 -0
- package/dist/widget-header/widget-header.module.css +335 -0
- package/dist/widget-header/widget-header.module.css.d.ts +24 -0
- package/dist/widget-header/widget-header.test.d.ts +2 -0
- package/dist/widget-header/widget-header.test.d.ts.map +1 -0
- package/llms.txt +30 -17
- package/package.json +14 -1
- package/src/charts/cursor/resolve.test.ts +29 -1
- package/src/charts/cursor/resolve.ts +38 -6
- package/src/charts/cursor/scope.tsx +6 -3
- package/src/charts/cursor/store.test.ts +19 -1
- package/src/charts/cursor/store.ts +10 -5
- package/src/charts/hooks/useChartCursor.ts +16 -8
- package/src/charts/index.ts +2 -2
- package/src/charts/primitives/CartesianChart.test.tsx +124 -0
- package/src/charts/primitives/ChartCard.test.tsx +66 -0
- package/src/charts/primitives/ChartCard.tsx +86 -146
- package/src/charts/sparklines/BarSparkline.tsx +43 -5
- package/src/cli/check-coverage.test.ts +297 -0
- package/src/cli/check-theme.test.ts +38 -14
- package/src/cli/index.ts +392 -16
- package/src/cli/init-sync.test.ts +97 -0
- package/src/connectivity/connectivity-indicator.tsx +16 -9
- package/src/content/index.ts +16 -3
- package/src/content/prose.module.css +7 -28
- package/src/content/prose.module.css.test.ts +8 -24
- package/src/controls/actions.module.css +62 -0
- package/src/controls/actions.module.css.d.ts +13 -0
- package/src/controls/actions.test.tsx +252 -0
- package/src/controls/actions.tsx +655 -0
- package/src/controls/actions.type-guard.test.ts +63 -0
- package/src/controls/compare-filter.tsx +64 -0
- package/src/controls/control-group.test.tsx +229 -0
- package/src/controls/control-group.tsx +63 -0
- package/src/controls/controls.module.css +542 -0
- package/src/controls/controls.module.css.d.ts +35 -0
- package/src/controls/controls.router.test.tsx +637 -0
- package/src/controls/enum-filter.tsx +159 -0
- package/src/controls/filter-context.tsx +153 -0
- package/src/controls/filter-pill.tsx +120 -0
- package/src/controls/filter-set.test.tsx +472 -0
- package/src/controls/filter-set.tsx +225 -0
- package/src/controls/filter-sheet.tsx +285 -0
- package/src/controls/glyphs.tsx +81 -0
- package/src/controls/index.ts +48 -0
- package/src/controls/multi-select-filter.tsx +140 -0
- package/src/controls/peer-boundary.test.ts +85 -0
- package/src/controls/props-contract.test.tsx +106 -0
- package/src/controls/range-filter.tsx +184 -0
- package/src/controls/search-filter.tsx +123 -0
- package/src/controls/select-filter.tsx +89 -0
- package/src/controls/sync-button.module.css +63 -0
- package/src/controls/sync-button.module.css.d.ts +11 -0
- package/src/controls/sync-button.test.tsx +183 -0
- package/src/controls/sync-button.tsx +197 -0
- package/src/controls/toggle-filter.tsx +60 -0
- package/src/controls/view-tabs.tsx +110 -0
- package/src/controls-dates/date-range-picker.tsx +42 -0
- package/src/controls-dates/index.ts +8 -0
- package/src/dashboard/delta-badge.tsx +4 -74
- package/src/dashboard/settings-section.module.css +10 -0
- package/src/dashboard/settings-section.module.css.d.ts +1 -0
- package/src/dashboard/settings-section.test.tsx +56 -0
- package/src/dashboard/settings-section.tsx +33 -30
- package/src/dashboard/stat-card.module.css +82 -0
- package/src/dashboard/stat-card.module.css.d.ts +11 -0
- package/src/dashboard/stat-card.test.tsx +67 -1
- package/src/dashboard/stat-card.tsx +209 -68
- package/src/data/data-table.test.tsx +96 -11
- package/src/data/data-table.tsx +220 -84
- package/src/guard/check-source.test.ts +126 -13
- package/src/guard/grace.test.ts +149 -0
- package/src/guard/index.ts +172 -29
- package/src/guard/types.ts +4 -2
- package/src/index.ts +46 -5
- package/src/nav/types.ts +84 -2
- package/src/notifications/bell.tsx +6 -3
- package/src/notifications/index.ts +1 -1
- package/src/router-tanstack/field.ts +31 -0
- package/src/router-tanstack/index.ts +24 -2
- package/src/router-tanstack/multi-search-param-store.test.ts +71 -3
- package/src/router-tanstack/multi-search-param-store.ts +46 -77
- package/src/router-tanstack/search-param-store.ts +42 -159
- package/src/router-tanstack/search-store.router.test.tsx +661 -0
- package/src/router-tanstack/search-store.test.ts +418 -0
- package/src/router-tanstack/search-store.ts +380 -0
- package/src/router-tanstack/use-nav.test.tsx +187 -0
- package/src/router-tanstack/use-nav.ts +72 -14
- package/src/section/index.ts +1 -0
- package/src/section/section.module.css +104 -0
- package/src/section/section.module.css.d.ts +11 -0
- package/src/section/section.test.tsx +204 -0
- package/src/section/section.tsx +220 -0
- package/src/shell/app-breadcrumbs.tsx +44 -31
- package/src/shell/app-header.module.css +77 -37
- package/src/shell/app-header.module.css.d.ts +2 -1
- package/src/shell/app-mobile-nav.module.css +8 -0
- package/src/shell/app-mobile-nav.module.css.d.ts +1 -0
- package/src/shell/app-mobile-nav.tsx +147 -8
- package/src/shell/app-sidebar-account.tsx +2 -2
- package/src/shell/app-sidebar.module.css +303 -20
- package/src/shell/app-sidebar.module.css.d.ts +19 -1
- package/src/shell/app-sidebar.test.tsx +456 -41
- package/src/shell/app-sidebar.tsx +276 -140
- package/src/shell/index.test.tsx +291 -5
- package/src/shell/index.tsx +137 -38
- package/src/shell/mobile-nav-model.test.ts +228 -7
- package/src/shell/mobile-nav-model.ts +53 -3
- package/src/shell/nav-count-badge.tsx +1 -1
- package/src/shell/page-bar.module.css +178 -0
- package/src/shell/page-bar.module.css.d.ts +17 -0
- package/src/shell/page-bar.test.tsx +316 -0
- package/src/shell/page-bar.tsx +315 -0
- package/src/shell/sidebar-block-model.ts +83 -0
- package/src/shell/sidebar-blocks.tsx +301 -0
- package/src/shell/sidebar-search.module.css +26 -0
- package/src/shell/sidebar-search.module.css.d.ts +2 -0
- package/src/shell/sidebar-search.tsx +71 -2
- package/src/state/fields.test.tsx +258 -0
- package/src/state/fields.ts +892 -0
- package/src/state/persisted.ts +211 -0
- package/src/state.ts +46 -240
- package/src/styles.css +13 -0
- package/src/surfaces.ts +203 -36
- package/src/theme/controls.module.css +16 -1
- package/src/theme/ctl-theme.test.tsx +275 -0
- package/src/theme/ctl-theme.tsx +138 -0
- package/src/theme/ctl-tier-coverage.test.ts +170 -0
- package/src/theme/density-relations.test.ts +106 -51
- package/src/theme/divider-law.test.ts +259 -0
- package/src/theme/icon-slot.module.css +47 -0
- package/src/theme/icon-slot.module.css.d.ts +8 -0
- package/src/theme/icon-slot.test.tsx +275 -0
- package/src/theme/icon-slot.tsx +59 -0
- package/src/theme/index.ts +165 -3
- package/src/theme/layout-rhythm-css.test.ts +72 -0
- package/src/theme/radius.test.ts +11 -1
- package/src/theme/segmented-control.module.css +20 -0
- package/src/theme/shadow-surfaces.test.ts +20 -7
- package/src/theme/spacing.test.ts +75 -27
- package/src/theme/use-basalt-spacing.ts +2 -2
- package/src/tokens/density.test.ts +7 -25
- package/src/tokens/index.ts +48 -8
- package/src/tokens/palette.ts +107 -73
- package/src/widget-header/delta-badge.test.tsx +60 -0
- package/src/widget-header/delta-badge.tsx +57 -0
- package/src/widget-header/index.ts +2 -0
- package/src/widget-header/no-mantine.test.ts +33 -0
- package/src/widget-header/widget-header.module.css +335 -0
- package/src/widget-header/widget-header.module.css.d.ts +24 -0
- package/src/widget-header/widget-header.test.tsx +187 -0
- package/src/widget-header/widget-header.tsx +168 -0
- package/agent/rules/basalt-agent.md +0 -452
- package/agent/rules/basalt-app.md +0 -246
- package/agent/rules/basalt-commands.md +0 -320
- package/agent/rules/basalt-content.md +0 -409
- package/agent/rules/basalt-data.md +0 -329
- package/agent/rules/basalt-forms.md +0 -186
- package/agent/rules/basalt-notifications.md +0 -264
- package/agent/rules/basalt-query.md +0 -187
- package/agent/rules/basalt-router.md +0 -336
- package/dist/content/article-filter-bar.d.ts +0 -40
- package/dist/content/article-filter-bar.d.ts.map +0 -1
- package/dist/content/article-filter-bar.js +0 -56
- package/dist/shell/page-header.d.ts +0 -13
- package/dist/shell/page-header.d.ts.map +0 -1
- package/dist/shell/page-header.js +0 -23
- package/src/content/article-filter-bar.tsx +0 -88
- package/src/shell/page-header.tsx +0 -35
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section — the tier-2 heading composer (docs/CONTROLS-SPEC.md §2.2, law C8): a page-level content
|
|
3
|
+
* grouping under `WidgetHeader tier="section"`. Named exactly `Section` — not `PageSection` — so
|
|
4
|
+
* the existing `shadow-basalt-export` guard fires on a consumer's own hand-rolled `Section` /
|
|
5
|
+
* `PageSection` / `SectionTitle` / `SectionHeading` copy with zero new rule code.
|
|
6
|
+
*
|
|
7
|
+
* No `variant`, no border/background of its own — one shaded container level per page belongs to
|
|
8
|
+
* the cards inside a Section (`ChartCard`/`StatCard`), not to the Section itself.
|
|
9
|
+
*
|
|
10
|
+
* `actions` and `tabs` are two separate `CtlSlot`-wrapped fragments rendered in the header row
|
|
11
|
+
* (C1/C5) via `WidgetHeader`'s single `actions` slot; `tabs` hides while the section is collapsed.
|
|
12
|
+
* `Section` holds ≤3 actions (C6) — past that, a dev-only console warning fires (the AST guard
|
|
13
|
+
* lands in wave 6).
|
|
14
|
+
*
|
|
15
|
+
* `collapsible` state persists via `createPersistedState('basalt:section:<persistKey>')` when
|
|
16
|
+
* `persistKey` is given, else it is local `useState` — the header always stays drawn, only the body
|
|
17
|
+
* unmounts. `defaultOpen` picks the state a first visit lands on; a persisted value outranks it.
|
|
18
|
+
*
|
|
19
|
+
* `summary` renders under the header and survives a collapse. That is the whole reason it is a
|
|
20
|
+
* separate slot rather than the first child: a section a reader folded away should still state its
|
|
21
|
+
* headline figures, or folding it costs them the numbers they were watching.
|
|
22
|
+
*
|
|
23
|
+
* `id` turns the root into a scroll anchor, offset by both the shell header height and the
|
|
24
|
+
* `PageBar`'s measured height (`--basalt-page-bar-h`, wave 4) so an anchor-jumped heading isn't
|
|
25
|
+
* hidden under either sticky bar.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* import { Section, StatCard } from 'basalt-ui'
|
|
29
|
+
*
|
|
30
|
+
* <Section title="Revenue" icon={<IconChartBar size={16} />} count={rows.length}>
|
|
31
|
+
* <StatCard title="MRR" value="$48,204" delta={3.1} />
|
|
32
|
+
* </Section>
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Collapsible, with tabs and a persisted fold state.
|
|
36
|
+
* <Section
|
|
37
|
+
* id="usage"
|
|
38
|
+
* title="Usage"
|
|
39
|
+
* collapsible
|
|
40
|
+
* persistKey="usage"
|
|
41
|
+
* tabs={<ViewTabs field={viewField} />}
|
|
42
|
+
* >
|
|
43
|
+
* <UsageChart />
|
|
44
|
+
* </Section>
|
|
45
|
+
*/
|
|
46
|
+
import { Children, useId, useMemo, useState } from 'react'
|
|
47
|
+
import type { ReactNode } from 'react'
|
|
48
|
+
import { CtlSlot } from '../theme'
|
|
49
|
+
import { createPersistedState } from '../state'
|
|
50
|
+
import { WidgetHeader } from '../widget-header'
|
|
51
|
+
import type { WidgetHeaderProps } from '../widget-header'
|
|
52
|
+
import classes from './section.module.css'
|
|
53
|
+
|
|
54
|
+
export type SectionProps = Omit<WidgetHeaderProps, 'tier'> & {
|
|
55
|
+
/** Rendered in the header row, in its own `CtlSlot` — hidden while the section is collapsed. */
|
|
56
|
+
tabs?: ReactNode
|
|
57
|
+
/** Renders a chevron toggle in the header; the header stays drawn when closed, only `children`
|
|
58
|
+
* (and `tabs`) unmount. @default false */
|
|
59
|
+
collapsible?: boolean
|
|
60
|
+
/** Persists the fold state at `basalt:section:<persistKey>`. Omit for a local, unpersisted fold
|
|
61
|
+
* (`useState`). */
|
|
62
|
+
persistKey?: string
|
|
63
|
+
/** The fold state a section opens on, respected only while no persisted value exists — a section
|
|
64
|
+
* a reader has closed stays closed. `false` is what a long secondary block wants. @default true */
|
|
65
|
+
defaultOpen?: boolean
|
|
66
|
+
/** Rendered directly under the header and ALWAYS visible, collapsed or not: a collapsed section
|
|
67
|
+
* still states its headline figures, which is what makes collapsing it a real option. Keep it to
|
|
68
|
+
* one row — the body is what `children` is for. */
|
|
69
|
+
summary?: ReactNode
|
|
70
|
+
/** Turns the root into a scroll anchor (`id` + `scroll-margin-top` cleared for both sticky bars). */
|
|
71
|
+
id?: string
|
|
72
|
+
children: ReactNode
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The house dev gate (`data/data-table.tsx`, `provider`, `charts/kinds/BandStrip` use the same
|
|
76
|
+
* expression): `basaltViteConfig` defines `process.env.NODE_ENV`, so a production bundle
|
|
77
|
+
* constant-folds this to `false` and drops the warning. Read per call, never hoisted. */
|
|
78
|
+
function isDev(): boolean {
|
|
79
|
+
return process.env['NODE_ENV'] !== 'production'
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** ≤3 actions is C6 (docs/CONTROLS-SPEC.md §1) — the AST guard (`basalt/page-bar-budget`) lands in
|
|
83
|
+
* wave 6; this is the dev-only stopgap so the budget is visible before the lint rule exists. */
|
|
84
|
+
function warnPastActionBudget(title: string, actions: ReactNode): void {
|
|
85
|
+
if (!isDev()) return
|
|
86
|
+
const count = Children.count(actions)
|
|
87
|
+
if (count <= 3) return
|
|
88
|
+
console.warn(
|
|
89
|
+
`Section "${title}": ${count} actions exceeds the ≤3 budget (docs/CONTROLS-SPEC.md C6) — ` +
|
|
90
|
+
'move the rest behind a menu.',
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const UNPERSISTED_KEY = '__local__'
|
|
95
|
+
|
|
96
|
+
/** Collapse state — `createPersistedState` when `persistKey` is given, else local `useState`.
|
|
97
|
+
* Both hooks are always called (stable order across renders); only the unpersisted branch's setter
|
|
98
|
+
* is ever invoked when `persistKey` is absent, so no unpersisted Section writes to storage. */
|
|
99
|
+
function useSectionOpen(
|
|
100
|
+
persistKey: string | undefined,
|
|
101
|
+
defaultOpen: boolean,
|
|
102
|
+
): readonly [boolean, (next: boolean) => void] {
|
|
103
|
+
const [localOpen, setLocalOpen] = useState(defaultOpen)
|
|
104
|
+
const usePersistedOpen = useMemo(
|
|
105
|
+
() =>
|
|
106
|
+
createPersistedState<boolean>({
|
|
107
|
+
key: `section:${persistKey ?? UNPERSISTED_KEY}`,
|
|
108
|
+
version: 1,
|
|
109
|
+
initial: defaultOpen,
|
|
110
|
+
}),
|
|
111
|
+
[persistKey, defaultOpen],
|
|
112
|
+
)
|
|
113
|
+
const [persistedOpen, setPersistedOpen] = usePersistedOpen()
|
|
114
|
+
|
|
115
|
+
if (persistKey !== undefined) return [persistedOpen, setPersistedOpen] as const
|
|
116
|
+
return [localOpen, setLocalOpen] as const
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function ChevronToggle({
|
|
120
|
+
open,
|
|
121
|
+
onToggle,
|
|
122
|
+
controls,
|
|
123
|
+
}: {
|
|
124
|
+
open: boolean
|
|
125
|
+
onToggle: () => void
|
|
126
|
+
controls: string
|
|
127
|
+
}) {
|
|
128
|
+
return (
|
|
129
|
+
<button
|
|
130
|
+
type="button"
|
|
131
|
+
className={classes.chevron}
|
|
132
|
+
data-open={open}
|
|
133
|
+
aria-expanded={open}
|
|
134
|
+
aria-controls={controls}
|
|
135
|
+
aria-label={open ? 'Collapse section' : 'Expand section'}
|
|
136
|
+
onClick={onToggle}
|
|
137
|
+
>
|
|
138
|
+
<svg
|
|
139
|
+
width={12}
|
|
140
|
+
height={12}
|
|
141
|
+
viewBox="0 0 24 24"
|
|
142
|
+
fill="none"
|
|
143
|
+
stroke="currentColor"
|
|
144
|
+
strokeWidth={2.5}
|
|
145
|
+
aria-hidden="true"
|
|
146
|
+
>
|
|
147
|
+
<path d="M6 9l6 6 6-6" strokeLinecap="round" strokeLinejoin="round" />
|
|
148
|
+
</svg>
|
|
149
|
+
</button>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function Section({
|
|
154
|
+
title,
|
|
155
|
+
icon,
|
|
156
|
+
subtitle,
|
|
157
|
+
info,
|
|
158
|
+
value,
|
|
159
|
+
delta,
|
|
160
|
+
deltaPeriod,
|
|
161
|
+
sparkline,
|
|
162
|
+
count,
|
|
163
|
+
actions,
|
|
164
|
+
tabs,
|
|
165
|
+
collapsible = false,
|
|
166
|
+
persistKey,
|
|
167
|
+
defaultOpen = true,
|
|
168
|
+
summary,
|
|
169
|
+
id,
|
|
170
|
+
children,
|
|
171
|
+
}: SectionProps) {
|
|
172
|
+
const [open, setOpen] = useSectionOpen(persistKey, defaultOpen)
|
|
173
|
+
const bodyId = useId()
|
|
174
|
+
|
|
175
|
+
if (actions !== undefined) warnPastActionBudget(title, actions)
|
|
176
|
+
|
|
177
|
+
const headerActions =
|
|
178
|
+
tabs !== undefined || actions !== undefined || collapsible ? (
|
|
179
|
+
<>
|
|
180
|
+
{tabs !== undefined && open && <CtlSlot>{tabs}</CtlSlot>}
|
|
181
|
+
{actions !== undefined && <CtlSlot>{actions}</CtlSlot>}
|
|
182
|
+
{collapsible && (
|
|
183
|
+
<ChevronToggle open={open} onToggle={() => setOpen(!open)} controls={bodyId} />
|
|
184
|
+
)}
|
|
185
|
+
</>
|
|
186
|
+
) : undefined
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<div
|
|
190
|
+
className={classes.root}
|
|
191
|
+
{...(id !== undefined && { id })}
|
|
192
|
+
{...(id !== undefined && {
|
|
193
|
+
style: {
|
|
194
|
+
scrollMarginTop:
|
|
195
|
+
'calc(var(--app-shell-header-height, 0px) + var(--basalt-page-bar-h, 0px))',
|
|
196
|
+
},
|
|
197
|
+
})}
|
|
198
|
+
>
|
|
199
|
+
<WidgetHeader
|
|
200
|
+
tier="section"
|
|
201
|
+
title={title}
|
|
202
|
+
{...(icon !== undefined && { icon })}
|
|
203
|
+
{...(subtitle !== undefined && { subtitle })}
|
|
204
|
+
{...(info !== undefined && { info })}
|
|
205
|
+
{...(value !== undefined && { value })}
|
|
206
|
+
{...(delta !== undefined && { delta })}
|
|
207
|
+
{...(deltaPeriod !== undefined && { deltaPeriod })}
|
|
208
|
+
{...(sparkline !== undefined && { sparkline })}
|
|
209
|
+
{...(count !== undefined && { count })}
|
|
210
|
+
{...(headerActions !== undefined && { actions: headerActions })}
|
|
211
|
+
/>
|
|
212
|
+
{summary !== undefined && <div className={classes.summary}>{summary}</div>}
|
|
213
|
+
{open && (
|
|
214
|
+
<div id={bodyId} className={classes.body}>
|
|
215
|
+
{children}
|
|
216
|
+
</div>
|
|
217
|
+
)}
|
|
218
|
+
</div>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
@@ -14,6 +14,7 @@ import { Anchor, Group, Text } from '@mantine/core'
|
|
|
14
14
|
import type { CSSProperties } from 'react'
|
|
15
15
|
import type { NavAnchor } from '../nav/types'
|
|
16
16
|
import { VX } from '../tokens'
|
|
17
|
+
import classes from './app-header.module.css'
|
|
17
18
|
|
|
18
19
|
/** Parent/section crumbs — faint. */
|
|
19
20
|
const crumbStyle: CSSProperties = { fontSize: VX.text.md, color: 'var(--vx-faint)' }
|
|
@@ -52,37 +53,49 @@ export function AppBreadcrumbs({
|
|
|
52
53
|
if (!page) return null
|
|
53
54
|
return (
|
|
54
55
|
<Group gap={6} wrap="nowrap" style={{ minWidth: 0 }}>
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{parent
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
56
|
+
{/*
|
|
57
|
+
The ANCESTOR crumbs, in one box so CSS can drop them below `sm` — law C9's swap, owned by the
|
|
58
|
+
component, no JS media query and no first-paint flash. On a phone the header row is the
|
|
59
|
+
scarcest space in the app and the breadcrumb is its one elastic side, so `Overview / Dashboard`
|
|
60
|
+
truncated to `O… / D…` — three crumbs' worth of separators and ellipses saying nothing. The
|
|
61
|
+
PAGE is the crumb that names where you are; the ancestors are navigation context, and the
|
|
62
|
+
sidebar (a tap away on the bottom bar) is where a phone reader looks for that.
|
|
63
|
+
*/}
|
|
64
|
+
{(section !== undefined || parent !== undefined) && (
|
|
65
|
+
<Group gap={6} wrap="nowrap" className={classes.crumbAncestors} style={{ minWidth: 0 }}>
|
|
66
|
+
{section && (
|
|
67
|
+
<>
|
|
68
|
+
<Text style={crumbStyle} truncate>
|
|
69
|
+
{section}
|
|
70
|
+
</Text>
|
|
71
|
+
<Text style={separatorStyle}>/</Text>
|
|
72
|
+
</>
|
|
73
|
+
)}
|
|
74
|
+
{parent && parentAnchor && (
|
|
75
|
+
<>
|
|
76
|
+
<Anchor style={crumbStyle} underline="never" component={parentAnchor} truncate>
|
|
77
|
+
{parent}
|
|
78
|
+
</Anchor>
|
|
79
|
+
<Text style={separatorStyle}>/</Text>
|
|
80
|
+
</>
|
|
81
|
+
)}
|
|
82
|
+
{parent && !parentAnchor && parentHref && (
|
|
83
|
+
<>
|
|
84
|
+
<Anchor style={crumbStyle} underline="never" href={parentHref} truncate>
|
|
85
|
+
{parent}
|
|
86
|
+
</Anchor>
|
|
87
|
+
<Text style={separatorStyle}>/</Text>
|
|
88
|
+
</>
|
|
89
|
+
)}
|
|
90
|
+
{parent && !parentAnchor && !parentHref && (
|
|
91
|
+
<>
|
|
92
|
+
<Text style={crumbStyle} truncate>
|
|
93
|
+
{parent}
|
|
94
|
+
</Text>
|
|
95
|
+
<Text style={separatorStyle}>/</Text>
|
|
96
|
+
</>
|
|
97
|
+
)}
|
|
98
|
+
</Group>
|
|
86
99
|
)}
|
|
87
100
|
<Text style={currentStyle} truncate>
|
|
88
101
|
{page}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
/* App-shell top bar layout.
|
|
2
|
-
* [
|
|
3
|
-
*
|
|
4
|
-
*
|
|
1
|
+
/* App-shell top bar layout. ONE 48px row on every viewport —
|
|
2
|
+
* [breadcrumb] ········ [page bar row 1] | [global actions].
|
|
3
|
+
*
|
|
4
|
+
* The pre-1.26.0 mobile layout wrapped to a second, always-reserved row for the page actions and
|
|
5
|
+
* scrolled it sideways. Both are gone (law C7 and law C14): the header height is now the
|
|
6
|
+
* `appShellHeaderHeight` token at every width, an empty page bar reserves nothing, and overflow
|
|
7
|
+
* folds into `ActionGroup`'s kebab instead of scrolling out of view. */
|
|
5
8
|
|
|
6
9
|
/*
|
|
7
10
|
* Transparent header (docs/DESIGN-SPEC.md §5): NO bottom rule at all. The header and the page body
|
|
@@ -16,58 +19,95 @@
|
|
|
16
19
|
height: 100%;
|
|
17
20
|
}
|
|
18
21
|
|
|
22
|
+
/*
|
|
23
|
+
* **Exactly ONE side of the header row is elastic, and it is the side whose content can ellipsize.**
|
|
24
|
+
* That is the whole rule, and both collisions this header has produced were the same violation of
|
|
25
|
+
* it from opposite directions.
|
|
26
|
+
*
|
|
27
|
+
* First the breadcrumb was `flex-shrink: 0`, so it won the whole width and the primary action
|
|
28
|
+
* rendered UNDERNEATH it. Then BOTH sides were made shrinkable (`.lead` at `0 1 auto`, `.pageBar` at
|
|
29
|
+
* `1 1 auto` with `min-width: 0` pushed onto its children) — and at 390px the controls, which cannot
|
|
30
|
+
* clip, shrank below their content and spilled: a flex container with `justify-content: flex-end`
|
|
31
|
+
* overflows towards its START, so the sync button painted 30px INTO the page title. Measured in
|
|
32
|
+
* Chrome: the title spanned 119.7–197.1 and the sync button 158.3–188.3.
|
|
33
|
+
*
|
|
34
|
+
* So the lead is now the elastic side (`flex: 1 1 auto`, `min-width: 0`, each crumb truncating via
|
|
35
|
+
* its own `truncate` prop) and the control side is rigid. A row of buttons that genuinely does not
|
|
36
|
+
* fit is not a shrinking problem — it is the OVERFLOW FOLD's problem, and basalt already owns that
|
|
37
|
+
* (law C7: below `sm` row 1 is the primary plus ONE kebab).
|
|
38
|
+
*/
|
|
19
39
|
.lead {
|
|
20
40
|
display: flex;
|
|
21
41
|
align-items: center;
|
|
22
42
|
gap: var(--mantine-spacing-sm);
|
|
23
|
-
flex
|
|
43
|
+
flex: 1 1 auto;
|
|
24
44
|
min-width: 0;
|
|
25
45
|
}
|
|
26
46
|
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
/* No `overflow: hidden` here or on `.lead` above: Mantine's focus ring is `outline: 2px solid;
|
|
48
|
+
* outline-offset: 2px` — OUTSIDE the anchor box — and a wrapper clipping this tightly to the
|
|
49
|
+
* breadcrumb anchors clipped the ring on every edge, leaving the primary in-shell nav link with no
|
|
50
|
+
* visible focus indicator. Truncation is already owned by each crumb's own `truncate` prop
|
|
51
|
+
* (`app-breadcrumbs.tsx`, Mantine's `[data-truncate]` rule sets its own `overflow: hidden;
|
|
52
|
+
* text-overflow: ellipsis; white-space: nowrap` on the element that actually holds the text) — this
|
|
53
|
+
* wrapper only needs to let its children shrink. */
|
|
54
|
+
.lead * {
|
|
29
55
|
min-width: 0;
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
justify-content: flex-end;
|
|
33
|
-
gap: var(--mantine-spacing-xs);
|
|
34
|
-
overflow-x: auto;
|
|
35
|
-
scrollbar-width: thin;
|
|
36
56
|
}
|
|
37
57
|
|
|
38
|
-
/*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
|
|
58
|
+
/*
|
|
59
|
+
* The `PageBar` row-1 portal target — the RIGID side of the row (see `.lead` above for the rule and
|
|
60
|
+
* for the two collisions that established it). Never a scroll container — see the header note above.
|
|
61
|
+
*
|
|
62
|
+
* `flex: 0 0 auto` and no `min-width: 0` anywhere below it, deliberately: a button cannot ellipsize,
|
|
63
|
+
* so letting this side shrink does not make it narrower, it makes it OVERFLOW — leftwards, into the
|
|
64
|
+
* breadcrumb, because of the `justify-content: flex-end` two lines down. The previous version pushed
|
|
65
|
+
* `min-width: 0` onto every child for exactly the reason that comment gave (a `wrap="nowrap"` group's
|
|
66
|
+
* automatic minimum size is its min-content width and flex will not go below it) — the reasoning was
|
|
67
|
+
* right and the conclusion was backwards: that floor is the row's protection, not its bug.
|
|
68
|
+
*/
|
|
69
|
+
.pageBar {
|
|
70
|
+
flex: 0 0 auto;
|
|
71
|
+
display: flex;
|
|
42
72
|
flex-wrap: nowrap;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: flex-end;
|
|
75
|
+
gap: var(--vx-space-control-gap);
|
|
43
76
|
}
|
|
44
77
|
|
|
78
|
+
/*
|
|
79
|
+
* The shell globals sit at the SAME 30px tier as everything else in the row, and they get there the
|
|
80
|
+
* same way a home's slot does — `HeaderGlobalActions` wraps this region in a `CtlSlot`, so a
|
|
81
|
+
* consumer's bare `<ActionIcon>` in `globalActions` defaults to `size="ctl"` with no prop at the call
|
|
82
|
+
* site (law C5). They rendered at Mantine's `md` 28px before, which is 2px under the page group
|
|
83
|
+
* beside them: close enough to look like a mistake rather than a tier.
|
|
84
|
+
*
|
|
85
|
+
* The gap to the page group is `.bar`'s own `sm`, so the globals read as a separate cluster; between
|
|
86
|
+
* themselves they use the control gap, like every other adjacent-control pair.
|
|
87
|
+
*/
|
|
45
88
|
.global {
|
|
46
89
|
display: flex;
|
|
90
|
+
flex-wrap: nowrap;
|
|
47
91
|
align-items: center;
|
|
48
|
-
gap: var(--
|
|
92
|
+
gap: var(--vx-space-control-gap);
|
|
49
93
|
flex-shrink: 0;
|
|
50
94
|
}
|
|
51
95
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.lead {
|
|
59
|
-
order: 1;
|
|
60
|
-
flex: 1 1 auto;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.global {
|
|
64
|
-
order: 2;
|
|
65
|
-
}
|
|
96
|
+
.global :global(.mantine-ActionIcon-root) > svg {
|
|
97
|
+
width: 1rem;
|
|
98
|
+
height: 1rem;
|
|
99
|
+
}
|
|
66
100
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
101
|
+
/*
|
|
102
|
+
* The breadcrumb's ANCESTOR crumbs — hidden below `sm`. See `app-breadcrumbs.tsx` for why: at 390px
|
|
103
|
+
* the row's elastic side truncated `Overview / Dashboard` to `O… / D…`, which is two ellipses and a
|
|
104
|
+
* separator in place of the one word that says where the reader is.
|
|
105
|
+
*
|
|
106
|
+
* `47.99375em` is the `sm` breakpoint in the exact literal form every other basalt CSS module uses —
|
|
107
|
+
* a media query cannot resolve a custom property.
|
|
108
|
+
*/
|
|
109
|
+
@media (max-width: 47.99375em) {
|
|
110
|
+
.crumbAncestors {
|
|
111
|
+
display: none;
|
|
72
112
|
}
|
|
73
113
|
}
|
|
@@ -252,6 +252,14 @@
|
|
|
252
252
|
background-color: color-mix(in srgb, var(--vx-ink) 10%, transparent);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
/* Trailing meta on a block-item row (a timestamp, an owner) — the mobile twin of the sidebar's
|
|
256
|
+
* `.blockRowMeta`, so the same `SidebarBlockItem.meta` reads the same on both surfaces. */
|
|
257
|
+
.rowMeta {
|
|
258
|
+
flex: none;
|
|
259
|
+
font-size: var(--vx-text-micro);
|
|
260
|
+
color: var(--vx-faint);
|
|
261
|
+
}
|
|
262
|
+
|
|
255
263
|
/*
|
|
256
264
|
* Active = neutral surface fill + plain text color. Never the identity blue (DESIGN.md). --nl-color
|
|
257
265
|
* forces NavLink's active text/icon color (otherwise the accent) to the plain text color. The
|