basalt-ui 1.25.0 → 1.27.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 +26 -0
- package/MIGRATING.md +815 -23
- 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 +160 -0
- package/agent/rules/basalt-mantine.md +146 -439
- package/agent/rules/basalt-state.md +118 -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 +1465 -36
- package/configs/oxlint-plugin.test.ts +1190 -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 +39 -0
- package/dist/controls/enum-filter.d.ts.map +1 -0
- package/dist/controls/enum-filter.js +93 -0
- package/dist/controls/filter-context.d.ts +60 -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 +20 -0
- package/dist/controls/index.d.ts.map +1 -0
- package/dist/controls/index.js +46 -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/number-filter.d.ts +26 -0
- package/dist/controls/number-filter.d.ts.map +1 -0
- package/dist/controls/number-filter.js +143 -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 +43 -0
- package/dist/controls/range-filter.d.ts.map +1 -0
- package/dist/controls/range-filter.js +135 -0
- package/dist/controls/range-filter.type-guard.test.d.ts +2 -0
- package/dist/controls/range-filter.type-guard.test.d.ts.map +1 -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/index.d.ts +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +3 -1
- 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 +95 -9
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +108 -49
- package/dist/dashboard/stat-card.module.css +153 -0
- package/dist/dashboard/stat-card.module.css.d.ts +15 -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 +96 -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 +78 -7
- package/dist/guard/types.d.ts +3 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +13 -3
- 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 +84 -0
- package/dist/router-tanstack/search-store.d.ts.map +1 -0
- package/dist/router-tanstack/search-store.js +271 -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 +565 -0
- package/dist/state/fields.d.ts.map +1 -0
- package/dist/state/fields.js +405 -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 +60 -0
- package/dist/state/persisted.d.ts.map +1 -0
- package/dist/state/persisted.js +123 -0
- package/dist/state/persisted.test.d.ts +2 -0
- package/dist/state/persisted.test.d.ts.map +1 -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 +156 -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 +67 -0
- package/dist/widget-header/widget-header.d.ts.map +1 -0
- package/dist/widget-header/widget-header.js +89 -0
- package/dist/widget-header/widget-header.module.css +350 -0
- package/dist/widget-header/widget-header.module.css.d.ts +25 -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 +1053 -0
- package/src/controls/enum-filter.tsx +170 -0
- package/src/controls/filter-context.tsx +158 -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 +49 -0
- package/src/controls/multi-select-filter.tsx +140 -0
- package/src/controls/number-filter.tsx +291 -0
- package/src/controls/peer-boundary.test.ts +85 -0
- package/src/controls/props-contract.test.tsx +137 -0
- package/src/controls/range-filter.tsx +237 -0
- package/src/controls/range-filter.type-guard.test.tsx +122 -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/index.ts +6 -1
- 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 +153 -0
- package/src/dashboard/stat-card.module.css.d.ts +15 -0
- package/src/dashboard/stat-card.test.tsx +298 -1
- package/src/dashboard/stat-card.tsx +289 -67
- package/src/data/data-table.test.tsx +96 -11
- package/src/data/data-table.tsx +228 -84
- package/src/guard/check-source.test.ts +159 -13
- package/src/guard/grace.test.ts +158 -0
- package/src/guard/index.ts +185 -29
- package/src/guard/types.ts +4 -2
- package/src/index.ts +51 -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 +35 -0
- package/src/router-tanstack/index.ts +28 -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 +882 -0
- package/src/router-tanstack/search-store.test.ts +578 -0
- package/src/router-tanstack/search-store.ts +546 -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 +512 -0
- package/src/state/fields.ts +1150 -0
- package/src/state/persisted.test.ts +91 -0
- package/src/state/persisted.ts +261 -0
- package/src/state.ts +52 -240
- package/src/styles.css +13 -0
- package/src/surfaces.ts +204 -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 +350 -0
- package/src/widget-header/widget-header.module.css.d.ts +25 -0
- package/src/widget-header/widget-header.test.tsx +187 -0
- package/src/widget-header/widget-header.tsx +213 -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
|
@@ -1,76 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DeltaBadge
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* with no glyph. The label never carries a leading "+"; pass `format` to control the magnitude
|
|
6
|
-
* string (defaults to a one-decimal percentage of the absolute value).
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* import { DeltaBadge } from 'basalt-ui'
|
|
10
|
-
*
|
|
11
|
-
* <DeltaBadge value={12.4} /> // ▲ 12.4%, success tint
|
|
12
|
-
* <DeltaBadge value={-3.1} /> // ▼ 3.1%, danger tint
|
|
13
|
-
* <DeltaBadge value={0} /> // 0.0%, neutral faint tint, no glyph
|
|
14
|
-
* <DeltaBadge value={182} format={(v) => `${Math.abs(v)}ms`} withGlyph={false} />
|
|
2
|
+
* `DeltaBadge` moved to `src/widget-header/` (docs/CONTROLS-SPEC.md §2.2) so `WidgetHeader` can
|
|
3
|
+
* compose it Mantine-free. Re-exported here unchanged so this deep import path — and `StatCard`'s
|
|
4
|
+
* own `./delta-badge` import — keep working without a wave-3 edit.
|
|
15
5
|
*/
|
|
16
|
-
|
|
17
|
-
import { alpha, VX } from '../tokens'
|
|
18
|
-
|
|
19
|
-
export type DeltaBadgeProps = {
|
|
20
|
-
/** Signed delta driving tone (positive/negative/zero) and, by default, the label magnitude. */
|
|
21
|
-
value: number
|
|
22
|
-
/** Formats the value into the label text. Defaults to `${Math.abs(value).toFixed(1)}%`. */
|
|
23
|
-
format?: (value: number) => string
|
|
24
|
-
/** Render the ▲/▼ direction glyph. Defaults to `true`; a zero value never shows a glyph. */
|
|
25
|
-
withGlyph?: boolean
|
|
26
|
-
/** Optional comparison timeframe rendered directly after the value in a dimmer shade of the same
|
|
27
|
-
* tone (e.g. `MoM`, `WoW`, `YTD`) — states what the delta is measured against without a hover. */
|
|
28
|
-
period?: string | undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const defaultFormat = (value: number): string => `${Math.abs(value).toFixed(1)}%`
|
|
32
|
-
|
|
33
|
-
export function DeltaBadge({
|
|
34
|
-
value,
|
|
35
|
-
format = defaultFormat,
|
|
36
|
-
withGlyph = true,
|
|
37
|
-
period,
|
|
38
|
-
}: DeltaBadgeProps) {
|
|
39
|
-
const tone = value > 0 ? VX.status.good : value < 0 ? VX.status.bad : VX.faint
|
|
40
|
-
const glyph = value > 0 ? '▲' : value < 0 ? '▼' : undefined
|
|
41
|
-
const showGlyph = withGlyph && glyph !== undefined
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<Badge
|
|
45
|
-
styles={{
|
|
46
|
-
root: {
|
|
47
|
-
backgroundColor: alpha(tone, 0.13),
|
|
48
|
-
padding: 'var(--vx-space-badge-inset-y) var(--vx-space-badge-inset-x)',
|
|
49
|
-
height: 'auto',
|
|
50
|
-
},
|
|
51
|
-
label: {
|
|
52
|
-
display: 'inline-flex', // theme-allow inline-display — a Badge `styles.label` part, not a layout node Flex could replace
|
|
53
|
-
alignItems: 'center',
|
|
54
|
-
gap: 3, // theme-allow inline-spacing — sub-scale glyph-to-label gap, below the smallest scale stop
|
|
55
|
-
fontFamily: 'var(--basalt-font-mono)',
|
|
56
|
-
fontSize: VX.text.xs,
|
|
57
|
-
fontWeight: 600,
|
|
58
|
-
textTransform: 'none',
|
|
59
|
-
letterSpacing: 'normal',
|
|
60
|
-
color: tone,
|
|
61
|
-
},
|
|
62
|
-
}}
|
|
63
|
-
>
|
|
64
|
-
{/* optical glyph ratio relative to the label, not a scale step */}
|
|
65
|
-
{showGlyph && <span style={{ fontSize: '0.8em' }}>{glyph}</span>}
|
|
66
|
-
{format(value)}
|
|
67
|
-
{period && (
|
|
68
|
-
<span
|
|
69
|
-
style={{ marginLeft: 4, fontWeight: 500, opacity: 0.6 }} // theme-allow inline-spacing — sub-scale optical period offset, below the smallest scale stop
|
|
70
|
-
>
|
|
71
|
-
{period}
|
|
72
|
-
</span>
|
|
73
|
-
)}
|
|
74
|
-
</Badge>
|
|
75
|
-
)
|
|
76
|
-
}
|
|
6
|
+
export { DeltaBadge, type DeltaBadgeProps } from '../widget-header/delta-badge'
|
package/src/dashboard/index.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { DeltaBadge, type DeltaBadgeProps } from './delta-badge'
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
StatCard,
|
|
4
|
+
type StatCardBreakdownRow,
|
|
5
|
+
type StatCardProps,
|
|
6
|
+
type StatCardTone,
|
|
7
|
+
} from './stat-card'
|
|
3
8
|
export { EmptyState, type EmptyStateProps } from './empty-state'
|
|
4
9
|
export {
|
|
5
10
|
SettingsSection,
|
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
* vertical padding and a 1px `--vx-divider` rule below it, EXCEPT the last row in the section —
|
|
4
4
|
* `:not(:last-child)` strips the divider there so the section doesn't end on a trailing line.
|
|
5
5
|
*/
|
|
6
|
+
|
|
7
|
+
/* The WidgetHeader block (plus DangerZone's eyebrow, when present) sits above `.rows` with the
|
|
8
|
+
* same gap the old inline `Stack gap={2} mb="sm"` produced. */
|
|
9
|
+
.header {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
gap: 2px;
|
|
13
|
+
margin-bottom: var(--mantine-spacing-sm);
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
.rows > * {
|
|
7
17
|
padding: var(--vx-space-settings-row-inset-y) 0;
|
|
8
18
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SettingsSection / DangerZone — the WidgetHeader composition (docs/CONTROLS-SPEC.md §2.2):
|
|
3
|
+
* `description` renamed to `subtitle`, both now render an h2 (`tier="section"`) via `WidgetHeader`,
|
|
4
|
+
* and `actions` reaches the header's actions slot.
|
|
5
|
+
*/
|
|
6
|
+
import { MantineProvider } from '@mantine/core'
|
|
7
|
+
import { render, screen } from '@testing-library/react'
|
|
8
|
+
import { describe, expect, test } from 'bun:test'
|
|
9
|
+
import type { ReactElement } from 'react'
|
|
10
|
+
import { DangerZone, SettingsSection } from './settings-section'
|
|
11
|
+
|
|
12
|
+
function renderWith(node: ReactElement) {
|
|
13
|
+
return render(<MantineProvider>{node}</MantineProvider>)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('SettingsSection composes WidgetHeader at the section tier', () => {
|
|
17
|
+
test('renders an h2 carrying the title', () => {
|
|
18
|
+
renderWith(
|
|
19
|
+
<SettingsSection title="Profile">
|
|
20
|
+
<div>rows</div>
|
|
21
|
+
</SettingsSection>,
|
|
22
|
+
)
|
|
23
|
+
expect(screen.getByRole('heading', { level: 2, name: 'Profile' })).toBeDefined()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('subtitle (renamed from description) renders below the title', () => {
|
|
27
|
+
renderWith(
|
|
28
|
+
<SettingsSection title="Profile" subtitle="Your public identity.">
|
|
29
|
+
<div>rows</div>
|
|
30
|
+
</SettingsSection>,
|
|
31
|
+
)
|
|
32
|
+
expect(screen.getByText('Your public identity.')).toBeDefined()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('actions reach the header actions slot', () => {
|
|
36
|
+
renderWith(
|
|
37
|
+
<SettingsSection title="Profile" actions={<button type="button">Export</button>}>
|
|
38
|
+
<div>rows</div>
|
|
39
|
+
</SettingsSection>,
|
|
40
|
+
)
|
|
41
|
+
expect(screen.getByRole('button', { name: 'Export' })).toBeDefined()
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('DangerZone keeps its eyebrow alongside the WidgetHeader', () => {
|
|
46
|
+
test('renders the eyebrow and an h2 title', () => {
|
|
47
|
+
renderWith(
|
|
48
|
+
<DangerZone title="Delete workspace" subtitle="This action cannot be undone.">
|
|
49
|
+
<div>rows</div>
|
|
50
|
+
</DangerZone>,
|
|
51
|
+
)
|
|
52
|
+
expect(screen.getByText('Danger Zone')).toBeDefined()
|
|
53
|
+
expect(screen.getByRole('heading', { level: 2, name: 'Delete workspace' })).toBeDefined()
|
|
54
|
+
expect(screen.getByText('This action cannot be undone.')).toBeDefined()
|
|
55
|
+
})
|
|
56
|
+
})
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SettingsSection / SettingsRow / DangerZone — the settings-page building blocks
|
|
3
|
-
* (docs/DESIGN-SPEC.md §5). A `SettingsSection` is a titled card
|
|
4
|
-
* `SettingsRow`s, each separated by a 1px `--vx-divider` rule (no border on the
|
|
5
|
-
* handled by the shared `.rows` container in `settings-section.module.css`). `DangerZone`
|
|
6
|
-
* `SettingsSection` variant for irreversible actions: a mono "DANGER ZONE" eyebrow in
|
|
3
|
+
* (docs/DESIGN-SPEC.md §5, docs/CONTROLS-SPEC.md §2.2). A `SettingsSection` is a titled card
|
|
4
|
+
* grouping a stack of `SettingsRow`s, each separated by a 1px `--vx-divider` rule (no border on the
|
|
5
|
+
* last row — handled by the shared `.rows` container in `settings-section.module.css`). `DangerZone`
|
|
6
|
+
* is a `SettingsSection` variant for irreversible actions: a mono "DANGER ZONE" eyebrow in
|
|
7
7
|
* status-danger, and a danger-tinted ring layered atop the card's shadow-card depth.
|
|
8
8
|
*
|
|
9
|
+
* Both compose `WidgetHeader tier="section"` for the title/subtitle/actions row — `actions` is
|
|
10
|
+
* wrapped in `CtlSlot` (C1/C5).
|
|
11
|
+
*
|
|
9
12
|
* @example
|
|
10
13
|
* import { SettingsSection, SettingsRow, DangerZone } from 'basalt-ui'
|
|
11
14
|
*
|
|
12
|
-
* <SettingsSection title="Profile"
|
|
15
|
+
* <SettingsSection title="Profile" subtitle="Your public identity.">
|
|
13
16
|
* <SettingsRow label="Display name" control={<TextInput value={name} onChange={...} />} />
|
|
14
17
|
* <SettingsRow
|
|
15
18
|
* label="Email"
|
|
@@ -18,7 +21,7 @@
|
|
|
18
21
|
* />
|
|
19
22
|
* </SettingsSection>
|
|
20
23
|
*
|
|
21
|
-
* <DangerZone title="Delete workspace"
|
|
24
|
+
* <DangerZone title="Delete workspace" subtitle="This action cannot be undone.">
|
|
22
25
|
* <SettingsRow
|
|
23
26
|
* label="Delete this workspace"
|
|
24
27
|
* control={<Button color="red" variant="outline">Delete</Button>}
|
|
@@ -27,17 +30,11 @@
|
|
|
27
30
|
*/
|
|
28
31
|
import { Card, Stack } from '@mantine/core'
|
|
29
32
|
import type { ReactNode } from 'react'
|
|
33
|
+
import { WidgetHeader } from '../widget-header'
|
|
34
|
+
import { CtlSlot } from '../theme'
|
|
30
35
|
import { alpha, VX } from '../tokens'
|
|
31
36
|
import classes from './settings-section.module.css'
|
|
32
37
|
|
|
33
|
-
const titleStyle = {
|
|
34
|
-
fontFamily: 'var(--basalt-font-head)',
|
|
35
|
-
fontStretch: '88%' as const,
|
|
36
|
-
fontSize: VX.text.md,
|
|
37
|
-
fontWeight: 550,
|
|
38
|
-
color: VX.ink,
|
|
39
|
-
}
|
|
40
|
-
|
|
41
38
|
const eyebrowStyle = {
|
|
42
39
|
fontFamily: 'var(--basalt-font-mono)',
|
|
43
40
|
fontSize: VX.text.micro,
|
|
@@ -48,23 +45,27 @@ const eyebrowStyle = {
|
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
export type SettingsSectionProps = {
|
|
51
|
-
/** Head-font section title
|
|
48
|
+
/** Head-font section title, rendered via `WidgetHeader tier="section"`. */
|
|
52
49
|
title: string
|
|
53
50
|
/** Optional 13px muted description below the title. */
|
|
54
|
-
|
|
51
|
+
subtitle?: string
|
|
52
|
+
/** Header-right slot — wrapped in `CtlSlot` (C1/C5). */
|
|
53
|
+
actions?: ReactNode
|
|
55
54
|
/** Section body — typically a stack of `SettingsRow`s. */
|
|
56
55
|
children: ReactNode
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
export function SettingsSection({ title,
|
|
58
|
+
export function SettingsSection({ title, subtitle, actions, children }: SettingsSectionProps) {
|
|
60
59
|
return (
|
|
61
60
|
<Card style={{ padding: 'var(--mantine-spacing-xs) var(--mantine-spacing-sm)' }}>
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
<div className={classes.header}>
|
|
62
|
+
<WidgetHeader
|
|
63
|
+
tier="section"
|
|
64
|
+
title={title}
|
|
65
|
+
{...(subtitle !== undefined && { subtitle })}
|
|
66
|
+
{...(actions !== undefined && { actions: <CtlSlot>{actions}</CtlSlot> })}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
68
69
|
<div className={classes.rows}>{children}</div>
|
|
69
70
|
</Card>
|
|
70
71
|
)
|
|
@@ -97,7 +98,7 @@ export function SettingsRow({ label, description, control, children }: SettingsR
|
|
|
97
98
|
|
|
98
99
|
export type DangerZoneProps = SettingsSectionProps
|
|
99
100
|
|
|
100
|
-
export function DangerZone({ title,
|
|
101
|
+
export function DangerZone({ title, subtitle, actions, children }: DangerZoneProps) {
|
|
101
102
|
return (
|
|
102
103
|
<Card
|
|
103
104
|
style={{
|
|
@@ -105,13 +106,15 @@ export function DangerZone({ title, description, children }: DangerZoneProps) {
|
|
|
105
106
|
boxShadow: `${VX.shadowCard}, 0 0 0 1px ${alpha(VX.status.bad, 0.25)}`,
|
|
106
107
|
}}
|
|
107
108
|
>
|
|
108
|
-
<
|
|
109
|
+
<div className={classes.header}>
|
|
109
110
|
<span style={eyebrowStyle}>Danger Zone</span>
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
<WidgetHeader
|
|
112
|
+
tier="section"
|
|
113
|
+
title={title}
|
|
114
|
+
{...(subtitle !== undefined && { subtitle })}
|
|
115
|
+
{...(actions !== undefined && { actions: <CtlSlot>{actions}</CtlSlot> })}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
115
118
|
<div className={classes.rows}>{children}</div>
|
|
116
119
|
</Card>
|
|
117
120
|
)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* StatCard's sparkline placement (docs/CONTROLS-SPEC.md §2.2). `bleed` (default) keeps the historic
|
|
3
|
+
* full-width row beneath the hero value, bled past the card's own inset padding — same negative
|
|
4
|
+
* margins the pre-WidgetHeader version drew inline. `right` sits the sparkline beside the
|
|
5
|
+
* `WidgetHeader`'s hero-value row instead, the reference-design look, and collapses back to
|
|
6
|
+
* `bleed`'s stacked layout below `sm` — CSS only, no JS branch (`47.99375em` is Mantine's own
|
|
7
|
+
* complement of `min-width: 48em`, same value `content/prose.module.css` derives it from).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.body {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
gap: var(--vx-space-stat-card-gap);
|
|
14
|
+
height: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* `flex-end`, not `center`: the sparkline belongs to the HERO ROW, and the hero row is the header
|
|
19
|
+
* block's last line. Centred against the whole body it floated between the title and the value,
|
|
20
|
+
* which reads as a third, unrelated element; bottom-aligned to the header block it sits beside the
|
|
21
|
+
* number it describes, the reference layout. `gap` is the card's own control gap so the trend never
|
|
22
|
+
* touches a long value.
|
|
23
|
+
*/
|
|
24
|
+
.body[data-placement='right'] {
|
|
25
|
+
flex-direction: row;
|
|
26
|
+
align-items: flex-end;
|
|
27
|
+
gap: var(--vx-space-control-gap);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.header {
|
|
31
|
+
min-width: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* `flex-shrink: 0` on the header, `1` on the sparkline slot below: the hero value and its delta keep
|
|
36
|
+
* their width and the TREND gives ground. The other way round, a 4-up KPI grid on a 1440 viewport
|
|
37
|
+
* ellipsized `$1,294,900` to `$1294.…` in order to keep 72px of bars intact, which is the wrong
|
|
38
|
+
* thing to protect. The value still carries `overflow: hidden` as the last resort, and `Card` clips.
|
|
39
|
+
*/
|
|
40
|
+
.body[data-placement='right'] .header {
|
|
41
|
+
flex: 1 0 auto;
|
|
42
|
+
min-width: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* The `breakdown` rows — the two or three parts a hero number is made of, under it.
|
|
47
|
+
*
|
|
48
|
+
* NO hairline, anywhere in this block, and that is a law rather than a taste: `docs/CONTROLS-SPEC.md`
|
|
49
|
+
* §2.1 puts a horizontal rule between OPTION rows and nowhere else, and `theme/divider-law.test.ts`
|
|
50
|
+
* inventories every one basalt draws. Three rules inside a KPI card would read as a table wearing a
|
|
51
|
+
* card's clothes. The rows are separated by the stack rhythm and by weight — a muted label against
|
|
52
|
+
* an ink value — which is the same separation the sheet's own field groups use.
|
|
53
|
+
*/
|
|
54
|
+
.breakdown {
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
margin: var(--vx-space-stack-sm) 0 0;
|
|
58
|
+
padding: 0;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* One row, one line, at the TAG tier (`controlHeightTag`, 20px at level 0) — the smallest control
|
|
64
|
+
* step basalt declares, and a token rather than a literal so the rows track the density knob with
|
|
65
|
+
* everything else. `justify-content: space-between` is what makes the pair read as a row without a
|
|
66
|
+
* grid: the label leads, the value trails, and neither needs a column to align against because
|
|
67
|
+
* every row in one card is the same box.
|
|
68
|
+
*/
|
|
69
|
+
.breakdownRow {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
gap: var(--vx-space-control-gap);
|
|
74
|
+
min-height: var(--vx-space-control-height-tag);
|
|
75
|
+
min-width: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.breakdownLabel {
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
text-overflow: ellipsis;
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
font-size: var(--vx-text-sm);
|
|
83
|
+
color: var(--vx-muted);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Mono and ink — a breakdown value is a number, and it is the half of the row worth reading. Never
|
|
87
|
+
* shrinks: the LABEL is the prose half and the one that may ellipsize. */
|
|
88
|
+
.breakdownValue {
|
|
89
|
+
flex-shrink: 0;
|
|
90
|
+
margin: 0;
|
|
91
|
+
font-family: var(--basalt-font-mono);
|
|
92
|
+
font-size: var(--vx-text-sm);
|
|
93
|
+
font-weight: 500;
|
|
94
|
+
color: var(--vx-ink);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* A row past a threshold. Same vocabulary and the same per-scheme solids as the card's own tone rail
|
|
99
|
+
* (`stat-card.tsx`'s `VX.status[tone]`), so a row saying `bad` and a rail saying `bad` are one claim
|
|
100
|
+
* at two scales. Colour is not the only carrier at the CARD level (the rail ships a
|
|
101
|
+
* `VisuallyHidden` verdict); at the ROW level the label is the carrier — a row reading
|
|
102
|
+
* `Paid · 1,204` states its own subject either way, and the tint only ranks it.
|
|
103
|
+
*/
|
|
104
|
+
.breakdownRow[data-tone='good'] .breakdownValue {
|
|
105
|
+
color: var(--vx-status-good);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.breakdownRow[data-tone='warn'] .breakdownValue {
|
|
109
|
+
color: var(--vx-status-warn);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.breakdownRow[data-tone='bad'] .breakdownValue {
|
|
113
|
+
color: var(--vx-status-bad);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.sparklineBleed {
|
|
117
|
+
margin-top: auto;
|
|
118
|
+
margin-inline: calc(-1 * var(--mantine-spacing-sm));
|
|
119
|
+
margin-bottom: calc(-1 * var(--mantine-spacing-xs));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Asks for `StatCard`'s `SPARKLINE_RIGHT_WIDTH`/`_HEIGHT` (handed down as custom properties, so this
|
|
123
|
+
* rule and the `< sm` reset below can both reach them) and shrinks below the width before the hero
|
|
124
|
+
* row does — see the `.header` note above. `min-width: 0` is what lets it. */
|
|
125
|
+
.sparklineRight {
|
|
126
|
+
display: flex;
|
|
127
|
+
flex: 0 1 var(--basalt-stat-sparkline-w, 4.5rem);
|
|
128
|
+
min-width: 0;
|
|
129
|
+
height: var(--basalt-stat-sparkline-h, 1.625rem);
|
|
130
|
+
align-items: flex-end;
|
|
131
|
+
overflow: hidden;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@media (max-width: 47.99375em) {
|
|
135
|
+
.body[data-placement='right'] {
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
align-items: stretch;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.body[data-placement='right'] .header {
|
|
141
|
+
flex: initial;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* The row became a COLUMN, so `flex-basis` is now the main-axis HEIGHT — the 72px width would
|
|
145
|
+
* become a 72px-tall box around 26px of bars. `flex: none` + the height keeps the bled trend the
|
|
146
|
+
* same 26px it is beside a hero row. */
|
|
147
|
+
.body[data-placement='right'] .sparklineRight {
|
|
148
|
+
flex: none;
|
|
149
|
+
margin-top: auto;
|
|
150
|
+
margin-inline: calc(-1 * var(--mantine-spacing-sm));
|
|
151
|
+
margin-bottom: calc(-1 * var(--mantine-spacing-xs));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed CSS-module declaration (the S4 CSS-modules path). Named string props — not an index
|
|
3
|
+
* signature — so dot access stays verbatim under the package's strict flags.
|
|
4
|
+
*/
|
|
5
|
+
declare const classes: {
|
|
6
|
+
readonly body: string
|
|
7
|
+
readonly header: string
|
|
8
|
+
readonly breakdown: string
|
|
9
|
+
readonly breakdownRow: string
|
|
10
|
+
readonly breakdownLabel: string
|
|
11
|
+
readonly breakdownValue: string
|
|
12
|
+
readonly sparklineBleed: string
|
|
13
|
+
readonly sparklineRight: string
|
|
14
|
+
}
|
|
15
|
+
export default classes
|