basalt-ui 2.0.2 → 2.0.4

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/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## [2.0.4](https://github.com/jkrumm/basalt-ui/compare/v2.0.3...v2.0.4) (2026-10-14)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * assert the visible strip above the sticky header, not raw row overlap ([13b5a7e](https://github.com/jkrumm/basalt-ui/commit/13b5a7e736cfdf4be2c212b9894ea0ab6b1fd41e))
7
+ * seal the sticky table header under the app bar, keep narrow columns legible ([9046f21](https://github.com/jkrumm/basalt-ui/commit/9046f2174adaef3d9d71acacc216fe4663181ef5))
8
+
9
+ ## [2.0.3](https://github.com/jkrumm/basalt-ui/compare/v2.0.2...v2.0.3) (2026-10-14)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * follow the router import in app-wiring and let CI run make check ([47b6152](https://github.com/jkrumm/basalt-ui/commit/47b61526ab3ae959c1d9e4595916782defb0454f))
15
+ * label the provider's nav commands and drop duplicate nav entries ([08ec6ee](https://github.com/jkrumm/basalt-ui/commit/08ec6eef320f1ae8e072584c48a903f672222364))
16
+ * show nav badges in the collapsed rail ([5e09ea0](https://github.com/jkrumm/basalt-ui/commit/5e09ea07f05822f853c118a19c2cf72fe593501a))
17
+
1
18
  ## [2.0.2](https://github.com/jkrumm/basalt-ui/compare/v2.0.1...v2.0.2) (2026-10-14)
2
19
 
3
20
 
package/MIGRATING.md CHANGED
@@ -66,18 +66,18 @@ There is one row per SURFACE, not per export, and a surface earns a row once any
66
66
  shipped lefthook preset both changed in 1.30.0 with no row that owned them — which is how a
67
67
  consumer read this index, found nothing, and diffed a KPI row that had silently gone 4-up → 2-up.
68
68
 
69
- | Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | 2.0.1 | 2.0.2 | Unreleased |
70
- | ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- | --- | --- |
71
- | **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
72
- | **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
73
- | **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — |
74
- | **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
75
- | **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
76
- | **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
77
- | **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
78
- | **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
79
- | **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — | — | — |
80
- | **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
69
+ | Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | 1.34.1 | 1.35.0 | 1.36.0 | 1.36.1 | 1.37.0 | 1.37.1 | 1.38.0 | 1.38.1 | 1.39.0 | 1.40.0 | 1.40.1 | 1.40.2 | 1.40.3 | 1.41.0 | 2.0.0 | 2.0.1 | 2.0.2 | 2.0.3 | 2.0.4 | Unreleased |
70
+ | ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ------ | ------ | -------------------------------------------------------------------------------------------- | ------ | ------ | ------ | ------ | ------ | ----------------------------------------------- | ------ | ------ | ------ | ------ | ------------------------------------------------------------ | ---------- | --- | --- | --- | --- | --- | --- |
71
+ | **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — | — | — | — | — | — | — | | `appShellInset` 20 → 16 (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — | — | — |
72
+ | **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
73
+ | **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — | — | `useCoarsePointer()` (§ `useCoarsePointer()`) | — | — | — | — | | content gutter 16, block 8 from `sm` (§ 1.38.1) | — | — | — | — | — | — | — | — | — | — | — | — |
74
+ | **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — | — | `FormSection`/`FormRow`/`FormGroup`/`FormActions` move here (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
75
+ | **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — | — | the layout + `useForm`/`schemaResolver` deprecated, removed 1.37.0 (§ The form layout moves) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
76
+ | **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
77
+ | **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
78
+ | **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
79
+ | **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | the managed block moves `CLAUDE.md` → `AGENTS.md` (§ 1.41.0) | — | — | — | — | — | — |
80
+ | **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — | — | `unknown-vx-token` → `error`; the token factories throw (§ Guards) | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — | — |
81
81
 
82
82
  ---
83
83
 
@@ -992,16 +992,50 @@ optional, subpath-required peers.
992
992
  _Nothing yet. Author the next section under this heading as `## Unreleased — <title>`; the
993
993
  release renames it and opens a new one here._
994
994
 
995
+ ## 2.0.4 — argo table and peer friction
996
+
997
+ - `BasaltDataTable` `stickyHeader` inside `BasaltShell` now pins flush under the app chrome. The
998
+ header used to stick at `AppShell.Main`'s content edge, one block-padding below the band, so body
999
+ rows scrolled through that strip. The default offset cancels the padding; a `stickyHeaderOffset`
1000
+ you pass still wins, so delete a hand-tuned offset that was compensating for the gap.
1001
+ - A `Badge` in a table cell keeps its whole label (`WORKING` no longer shrinks to `WOR…` beside
1002
+ wrapping prose). Narrow numeric headers (`Peak`) clip only if the column is given a `size`
1003
+ smaller than its label — that is a column width, not a table default.
1004
+ - The column-fold toggle column's header cell carries a visually hidden `Details` label instead of
1005
+ an empty `aria-hidden` cell.
1006
+ - `doctor` gains `subpath-peers`: when your source imports a basalt-ui subpath whose required peers
1007
+ are not installed (e.g. `shiki`, `@shikijs/langs`, `@shikijs/themes` for `basalt-ui/content`) it
1008
+ fails with the `bun add` line to run. Without them the build succeeded and the chunk threw
1009
+ "Could not resolve" at load. `CodeBlock` also warns once in dev when the highlighter cannot load.
1010
+
1011
+ ## 2.0.3 — argo shell and CI friction
1012
+
1013
+ - `doctor`'s `app-wiring` follows the entry's relative imports (three deep): `createBasaltRouter`
1014
+ may be called in `src/lib/router.ts` (or any module `main.tsx` imports), not only in `main.tsx`.
1015
+ - The seeded `.github/workflows/check.yml` runs `make check` when the repo's Makefile has a
1016
+ `check:` target, after `doctor` and `sync --check` (which always run, so drift is never
1017
+ skippable); otherwise it keeps the built-in lint, theme and format steps. `init` decides once, on
1018
+ seeding. An already-seeded workflow is yours and unchanged: replace its lint/theme/format steps
1019
+ with `- run: make check` to adopt it.
1020
+ - The collapsed `BasaltShell` rail shows a dot on the icon of any nav item with a count or badge,
1021
+ and the link's accessible name carries the count (e.g. "Calendar, 3"). Expanded rendering is
1022
+ unchanged.
1023
+ - `BasaltProvider` takes `navCommandLabel?: (item) => string` to label the Spotlight `nav.<id>`
1024
+ entries it generates from the nav (e.g. "Go to …"); default unchanged. A `defineCommands` entry
1025
+ with id `nav.<id>` now replaces the generated one instead of showing twice.
1026
+
995
1027
  ## 2.0.2
996
1028
 
997
- _Nothing to migrate in this release._
1029
+ - `doctor` and `sync` are monorepo-aware. The manifest, `.claude/` and the AGENTS block stay at the
1030
+ install root; the app-scoped half (`tsconfig-base`, `app-wiring`, the `src/main.tsx`,
1031
+ `src/lib/nav.tsx` and `src/routes/__root.tsx` seeds) targets the app package: `basalt.app`
1032
+ (relative path, e.g. `"apps/dashboard"`) in the root package.json, else the one workspace package
1033
+ that depends on basalt-ui and has `src/main.tsx` or `index.html`, else the cwd. Two candidates
1034
+ fail with a message naming `basalt.app`. `doctor` run inside the app package finds the root
1035
+ manifest, and warns about a router seed an earlier `sync` left at the root — delete it.
998
1036
 
999
1037
  ## 2.0.1
1000
1038
 
1001
- _Nothing to migrate in this release._
1002
-
1003
- ## Next patch — doctor reads the peers and the config
1004
-
1005
1039
  - `doctor` gains `exact-peers`: for each exact-pinned peer of the installed basalt-ui (the three
1006
1040
  `@fontsource-variable/*`, `motion`, `remend`, …) it compares your installed version and prints a
1007
1041
  one-line `bun add <pkg>@<version>` fix on a mismatch. `bun add` accepts the mismatch silently.
@@ -1012,17 +1046,6 @@ _Nothing to migrate in this release._
1012
1046
  - Corrected the § 2.0 "Upgrading from 1.x" step 2: delete only the core, notifications and
1013
1047
  spotlight layer imports; extension packages (`@mantine/dates`, `@mantine/schedule`) stay, after
1014
1048
  `basalt-ui/styles.css`.
1015
- - `doctor` and `sync` are monorepo-aware. The manifest, `.claude/` and the AGENTS block stay at the
1016
- install root; the app-scoped half (`tsconfig-base`, `app-wiring`, the `src/main.tsx`,
1017
- `src/lib/nav.tsx` and `src/routes/__root.tsx` seeds) targets the app package: `basalt.app`
1018
- (relative path, e.g. `"apps/dashboard"`) in the root package.json, else the one workspace package
1019
- that depends on basalt-ui and has `src/main.tsx` or `index.html`, else the cwd. Two candidates
1020
- fail with a message naming `basalt.app`. `doctor` run inside the app package finds the root
1021
- manifest, and warns about a router seed an earlier `sync` left at the root — delete it.
1022
-
1023
- ## 2.0.0
1024
-
1025
- _Nothing to migrate in this release._
1026
1049
 
1027
1050
  ## 1.41.0 — the managed block moves to AGENTS.md
1028
1051
 
package/configs/check.yml CHANGED
@@ -13,6 +13,10 @@
13
13
  # from the working directory (bun's isolated linker puts it beside the package that depends
14
14
  # on it, not at the root) bunx silently downloads a DIFFERENT copy from npm and the gate
15
15
  # runs a version nobody pinned.
16
+ # The gate is the consumer's when it has one: with a Makefile `check:` target the workflow runs
17
+ # `make check` (after `doctor` and `sync --check`, which always run first so drift can never be
18
+ # skipped by a custom gate); without one it runs the built-in lint + theme guard + format steps.
19
+ # `init` decides once, when it seeds this file. Add gates to your `make check`, not to this file.
16
20
  name: check
17
21
  on:
18
22
  pull_request:
@@ -28,11 +32,7 @@ jobs:
28
32
  with:
29
33
  bun-version: latest
30
34
  - run: bun install --frozen-lockfile
31
- - run: bunx oxlint .
32
- - run: '{{BASALT_BIN}} doctor'
33
- - run: '{{BASALT_BIN}} check-theme'
34
- - run: '{{BASALT_BIN}} sync --check'
35
- - run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check
35
+ # {{GATE_STEPS}}
36
36
  # Enable once your app defines these package.json scripts:
37
37
  # - run: bun run typecheck
38
38
  # - run: bun run test
@@ -22,7 +22,7 @@ export declare function droppedSubpathsCheck(cwd: string, cfg: BasaltConfig, ins
22
22
  export declare function seedTsconfigExtends(cwd: string): string | null;
23
23
  /**
24
24
  * `app-wiring`: the entry module `index.html` loads (default src/main.tsx) mounts `BasaltProvider`
25
- * on a `createBasaltRouter` router, and the router tree is generated: the vite config calls a
25
+ * on a `createBasaltRouter` router (called in the entry or a module it imports), and the router tree is generated: the vite config calls a
26
26
  * binding imported from `@tanstack/router-plugin` in `plugins`, or a `routeTree.gen.*` already sits
27
27
  * beside the entry (or in src/). `basaltViteConfig` does not register that plugin, so naming it
28
28
  * proves nothing.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAgB9D,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MACc,CAAA;AA+CvD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAqBpD;AA+CD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAyBhF;AA4CD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,aAAa,GACrB,KAAK,CA8BP;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC9D;AAoDD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CA+BjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAezD;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAwB1E"}
1
+ {"version":3,"file":"doctor-upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-upgrade.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAgB9D,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,MACc,CAAA;AA+CvD,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAqBpD;AA+CD,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAyBhF;AA4CD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,aAAa,GACrB,KAAK,CA8BP;AAUD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkC9D;AAgGD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAkCjD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAezD;AAaD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,KAAK,CAwB1E"}
@@ -234,6 +234,39 @@ function registersRouterPlugin(src) {
234
234
  );
235
235
  });
236
236
  }
237
+ const RELATIVE_IMPORT = /(?:\b(?:import|export)\b[^'";]*?\bfrom|\bimport)\s*['"](\.{1,2}\/[^'"]+)['"]/g;
238
+ function resolveRelative(from, spec) {
239
+ const base = resolve(dirname(from), spec.replace(/\.[jt]sx?$/, ""));
240
+ return [
241
+ resolve(dirname(from), spec),
242
+ `${base}.ts`,
243
+ `${base}.tsx`,
244
+ `${base}/index.ts`,
245
+ `${base}/index.tsx`
246
+ ].find((f) => /\.[jt]sx?$/.test(f) && existsSync(f)) ?? null;
247
+ }
248
+ function routerCreatedInImports(cwd, entry) {
249
+ const seen = /* @__PURE__ */ new Set([resolve(cwd, entry)]);
250
+ let frontier = [...seen];
251
+ for (let depth = 0; depth < 3 && frontier.length > 0; depth++) {
252
+ const next = [];
253
+ for (const file of frontier) {
254
+ for (const m of (readIfExists(file) ?? "").matchAll(RELATIVE_IMPORT)) {
255
+ const dep = resolveRelative(file, m[1] ?? "");
256
+ if (dep === null || seen.has(dep)) continue;
257
+ seen.add(dep);
258
+ const { code, inLiteral } = tokenize(readIfExists(dep) ?? "");
259
+ const called = [...code.matchAll(/\bcreateBasaltRouter\b/g)].some(
260
+ (c) => !inLiteral(c.index)
261
+ );
262
+ if (called) return true;
263
+ next.push(dep);
264
+ }
265
+ }
266
+ frontier = next;
267
+ }
268
+ return false;
269
+ }
237
270
  function appWiringCheck(cwd) {
238
271
  return guarded("app-wiring", () => {
239
272
  const entry = (htmlEntry(readIfExists(resolve(cwd, "index.html")) ?? "") ?? "src/main.tsx").replace(/^\//, "");
@@ -243,7 +276,9 @@ function appWiringCheck(cwd) {
243
276
  }
244
277
  const { code, inLiteral } = tokenize(text);
245
278
  const used = (name) => [...code.matchAll(new RegExp(`\\b${name}\\b`, "g"))].some((m) => !inLiteral(m.index));
246
- const missing = ["BasaltProvider", "createBasaltRouter"].filter((name) => !used(name));
279
+ const missing = ["BasaltProvider", "createBasaltRouter"].filter(
280
+ (name) => !used(name) && !(name === "createBasaltRouter" && routerCreatedInImports(cwd, entry))
281
+ );
247
282
  if (missing.length > 0) {
248
283
  return {
249
284
  fail: `app-wiring: ${entry} does not use ${missing.join(" or ")}. Fix: make it match ${SEED_HINT} (\`init\` seeds it only when the file is absent).`
@@ -152,6 +152,8 @@ type TemplateVars = {
152
152
  * `bunx basalt-ui` only as the pre-install fallback.
153
153
  */
154
154
  BASALT_BIN: string;
155
+ /** The CI gate steps after install: `make check` when the repo owns one, else the built-in set. */
156
+ GATE_STEPS: string;
155
157
  };
156
158
  export declare const MANIFEST_PATH = ".basalt/manifest.json";
157
159
  /** The host file the managed block is spliced into (and its manifest key). */
@@ -170,6 +172,12 @@ export declare function readFrameworkVersion(pkgRoot: string): string;
170
172
  * cached package, so it lets a consumer pin one version and be gated by another).
171
173
  */
172
174
  export declare function basaltBinCommand(install: BasaltInstall, cwd: string): string;
175
+ /**
176
+ * The consumer owns the CI gate when its Makefile has a `check:` target: `doctor` and `sync --check`
177
+ * stay as steps of their own (drift is never skippable), then `make check` replaces the built-in
178
+ * lint/theme/format steps. Without one, the built-in steps run. Rendered at `{{GATE_STEPS}}`.
179
+ */
180
+ export declare function ciGateSteps(cwd: string): string;
173
181
  /** True when both paths resolve to one file (a symlinked pair). A missing path is simply "no". */
174
182
  export declare function sameFile(a: string, b: string): boolean;
175
183
  /** True when the host text carries a managed block (begin marker present). */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -268,6 +268,18 @@ function basaltBinCommand(install, cwd) {
268
268
  const binDir = resolve(install.dir, "..", ".bin");
269
269
  return `${relativePosix(cwd, binDir).replace(/^\.\//, "")}/basalt-ui`;
270
270
  }
271
+ function ciGateSteps(cwd) {
272
+ const owned = /^check\s*:/m.test(readIfExists(resolve(cwd, "Makefile")) ?? "");
273
+ const drift = ["- run: '{{BASALT_BIN}} doctor'", "- run: '{{BASALT_BIN}} sync --check'"];
274
+ const steps = owned ? [...drift, "- run: make check"] : [
275
+ "- run: bunx oxlint .",
276
+ drift[0],
277
+ "- run: '{{BASALT_BIN}} check-theme'",
278
+ drift[1],
279
+ "- run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check"
280
+ ];
281
+ return steps.join("\n ");
282
+ }
271
283
  function buildTemplateVars(pkgRoot, cwd, cfg) {
272
284
  const install = findBasaltInstall(cwd);
273
285
  return {
@@ -278,14 +290,16 @@ function buildTemplateVars(pkgRoot, cwd, cfg) {
278
290
  ROOTS_GLOBS: resolveRoots(cfg).map(toRootGlob).join(" "),
279
291
  OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, OXLINT_FILES.preset),
280
292
  LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, "configs/lefthook.yml"),
281
- BASALT_BIN: basaltBinCommand(install, cwd)
293
+ BASALT_BIN: basaltBinCommand(install, cwd),
294
+ GATE_STEPS: ciGateSteps(cwd)
282
295
  };
283
296
  }
284
297
  function fillTemplate(tpl, vars) {
285
- return tpl.replace(/\{\{(\w+)\}\}/g, (m, key) => {
298
+ const fill = (text) => text.replace(/\{\{(\w+)\}\}/g, (m, key) => {
286
299
  const v = vars[key];
287
300
  return v ?? m;
288
301
  });
302
+ return fill(tpl.replace("# {{GATE_STEPS}}", vars.GATE_STEPS));
289
303
  }
290
304
  function findBlockRegion(host) {
291
305
  const start = host.indexOf(BLOCK_BEGIN_PREFIX);
@@ -1000,6 +1014,7 @@ export {
1000
1014
  basaltBinCommand,
1001
1015
  basaltPresetEntry,
1002
1016
  checkTheme,
1017
+ ciGateSteps,
1003
1018
  classify,
1004
1019
  conflictingProfileFlags,
1005
1020
  declaredProfile,
@@ -5,6 +5,7 @@ import type { BuildPaletteOpts } from '../tokens/core.js';
5
5
  import type { SizeClass } from '../shell/use-size-class.js';
6
6
  import type { Telemetry } from '../telemetry.js';
7
7
  import type { BasaltRouter } from './create-router.js';
8
+ import type { FlatNavItem } from '../router-tanstack/nav.js';
8
9
  export type BasaltProviderProps = {
9
10
  /** From `createBasaltRouter`; the provider mounts it and reads its `queryClient`. */
10
11
  router: BasaltRouter;
@@ -41,6 +42,12 @@ export type BasaltProviderProps = {
41
42
  * can answer. Default `'compact'`. SSR only; an SSR desktop app SHOULD pass it.
42
43
  */
43
44
  sizeClassHint?: SizeClass;
45
+ /**
46
+ * Label for the `nav.<id>` Spotlight entries generated from `defineNav`, e.g.
47
+ * `(item) => `Go to ${item.label}``. Default: the destination's own label. A `defineCommands`
48
+ * entry with id `nav.<id>` replaces the generated one outright.
49
+ */
50
+ navCommandLabel?: (item: FlatNavItem) => string;
44
51
  } & Omit<MantineProviderProps, 'children' | 'theme' | 'defaultColorScheme' | 'cssVariablesResolver'>;
45
52
  type RootBoundaryProps = {
46
53
  children: ReactNode;
@@ -76,6 +83,6 @@ export declare function composeInjectedCss(base: string, fontsCss: string, radiu
76
83
  * closes the gap between hydration and the next client paint.
77
84
  */
78
85
  export declare function useHostAttribute(): void;
79
- export declare function BasaltProvider({ router, theme, telemetry, fallback, injectPalette, paletteOptions, defaultColorScheme, nonce, sizeClassHint, ...rest }: BasaltProviderProps): import("react").JSX.Element;
86
+ export declare function BasaltProvider({ router, theme, telemetry, fallback, injectPalette, paletteOptions, defaultColorScheme, nonce, sizeClassHint, navCommandLabel, ...rest }: BasaltProviderProps): import("react").JSX.Element;
80
87
  export {};
81
88
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/provider/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AASzD,OAAO,EAAE,SAAS,EAAqE,MAAM,OAAO,CAAA;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAA;AAIxE,MAAM,MAAM,mBAAmB,GAAG;IAChC,qFAAqF;IACrF,MAAM,EAAE,YAAY,CAAA;IACpB,qFAAqF;IACrF,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC,CAAA;IACtD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAA;IACjC,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,oBAAoB,CAAC,oBAAoB,CAAC,CAAA;IAC/D;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,CAAA;CAC1B,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,OAAO,GAAG,oBAAoB,GAAG,sBAAsB,CAAC,CAAA;AAIpG,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,SAAS,CAAA;IACnB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAA;CAC1C,CAAA;AAED,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAwB1D,mGAAmG;AACnG,qBAAa,YAAa,SAAQ,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC;gBAC/D,KAAK,EAAE,iBAAiB;IAKpC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa;IAIrD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAczD,MAAM,IAAI,SAAS;CAO7B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAYD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAmBvC;AAqMD,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,cAAc,EACd,kBAA2B,EAC3B,KAAK,EACL,aAAyB,EACzB,GAAG,IAAI,EACR,EAAE,mBAAmB,+BA6ErB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/provider/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AASzD,OAAO,EAAE,SAAS,EAAqE,MAAM,OAAO,CAAA;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAStD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,iBAAiB,CAAA;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGzD,MAAM,MAAM,mBAAmB,GAAG;IAChC,qFAAqF;IACrF,MAAM,EAAE,YAAY,CAAA;IACpB,qFAAqF;IACrF,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;IACrC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,yGAAyG;IACzG,QAAQ,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,SAAS,CAAC,CAAA;IACtD;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAA;IACjC,8CAA8C;IAC9C,kBAAkB,CAAC,EAAE,oBAAoB,CAAC,oBAAoB,CAAC,CAAA;IAC/D;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,CAAA;CAChD,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,OAAO,GAAG,oBAAoB,GAAG,sBAAsB,CAAC,CAAA;AAIpG,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,SAAS,CAAA;IACnB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAA;CAC1C,CAAA;AAED,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAwB1D,mGAAmG;AACnG,qBAAa,YAAa,SAAQ,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC;gBAC/D,KAAK,EAAE,iBAAiB;IAKpC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa;IAIrD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI;IAczD,MAAM,IAAI,SAAS;CAO7B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAYD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAmBvC;AAqMD,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,cAAc,EACd,kBAA2B,EAC3B,KAAK,EACL,aAAyB,EACzB,eAAe,EACf,GAAG,IAAI,EACR,EAAE,mBAAmB,+BA6ErB"}
@@ -242,6 +242,7 @@ function BasaltProvider({
242
242
  defaultColorScheme = "dark",
243
243
  nonce,
244
244
  sizeClassHint = "compact",
245
+ navCommandLabel,
245
246
  ...rest
246
247
  }) {
247
248
  useDuplicateProviderGuard();
@@ -259,8 +260,8 @@ function BasaltProvider({
259
260
  const [devTool, setDevTool] = useState(null);
260
261
  const [actions, setActions] = useState([]);
261
262
  const refreshActions = useCallback(
262
- () => setActions(buildSpotlightActions(router, setDevTool)),
263
- [router]
263
+ () => setActions(buildSpotlightActions(router, setDevTool, navCommandLabel)),
264
+ [router, navCommandLabel]
264
265
  );
265
266
  useEffect(refreshActions, [refreshActions]);
266
267
  const resolvedTheme = useLabTheme(theme);
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * The provider's Spotlight list: the `defineCommands` registry, then the `defineNav` destinations
3
- * (via `flattenNav`), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
3
+ * (via `flattenNav`, skipping any id a registered `nav.<id>` command already owns), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
4
4
  * opens, so a command's `when()` is current. Not for use during render (`detectMac` reads `navigator`).
5
5
  */
6
6
  import type { SpotlightActionData } from '@mantine/spotlight';
7
7
  import type { AnyRouter } from '@tanstack/react-router';
8
+ import type { FlatNavItem } from '../router-tanstack/nav.js';
8
9
  import type { BasaltDevDockTool } from '../dev-dock.js';
9
- export declare function buildSpotlightActions(router: AnyRouter, openDevTool: (tool: BasaltDevDockTool) => void): SpotlightActionData[];
10
+ export declare function buildSpotlightActions(router: AnyRouter, openDevTool: (tool: BasaltDevDockTool) => void, navCommandLabel?: (item: FlatNavItem) => string): SpotlightActionData[];
10
11
  //# sourceMappingURL=spotlight-actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spotlight-actions.d.ts","sourceRoot":"","sources":["../../src/provider/spotlight-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AASpD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,GAC7C,mBAAmB,EAAE,CA8CvB"}
1
+ {"version":3,"file":"spotlight-actions.d.ts","sourceRoot":"","sources":["../../src/provider/spotlight-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AASpD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,EAC9C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,MAAM,GAC9C,mBAAmB,EAAE,CAiDvB"}
@@ -7,9 +7,10 @@ const DEV_TOOLS = [
7
7
  { tool: "query", label: "Query devtools" },
8
8
  { tool: "theme", label: "Theme lab" }
9
9
  ];
10
- function buildSpotlightActions(router, openDevTool) {
10
+ function buildSpotlightActions(router, openDevTool, navCommandLabel) {
11
11
  const actions = [];
12
- for (const [id, cmd] of Object.entries(getActiveCommands())) {
12
+ const commands = getActiveCommands();
13
+ for (const [id, cmd] of Object.entries(commands)) {
13
14
  if (cmd.when !== void 0 && !cmd.when()) continue;
14
15
  actions.push({
15
16
  id,
@@ -27,9 +28,10 @@ function buildSpotlightActions(router, openDevTool) {
27
28
  if (nav !== void 0) {
28
29
  for (const item of flattenNav(nav)) {
29
30
  if (item.disabled === true) continue;
31
+ if (`nav.${item.id}` in commands) continue;
30
32
  actions.push({
31
33
  id: `nav.${item.id}`,
32
- label: item.label,
34
+ label: navCommandLabel?.(item) ?? item.label,
33
35
  group: item.groupLabel,
34
36
  leftSection: item.icon,
35
37
  // `link` is the destination's own `linkOptions`, so a store-backed `search` thunk restores
@@ -1 +1 @@
1
- {"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/app-sidebar.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,cAAc,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAgBjF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;;;;OAIG;IACH,KAAK,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,CAAA;IACjD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACtC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IACjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CACxB,CAAA;AAmTD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BA2KhD"}
1
+ {"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../../src/shell/app-sidebar.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAe,cAAc,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAE1E,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAgBjF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;;;;OAIG;IACH,KAAK,EAAE,WAAW,GAAG;QAAE,IAAI,CAAC,EAAE,eAAe,EAAE,CAAA;KAAE,CAAA;IACjD,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,SAAS,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACtC;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAA;IAC5B;;;;OAIG;IACH,MAAM,CAAC,EAAE,mBAAmB,GAAG;QAAE,OAAO,CAAC,EAAE,oBAAoB,CAAA;KAAE,CAAA;IACjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,YAAY,EAAE,CAAA;CACxB,CAAA;AAiUD,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,+BA2KhD"}
@@ -88,14 +88,21 @@ function NavLinkBody({
88
88
  collapsed = false
89
89
  }) {
90
90
  const Anchor = item.Anchor;
91
+ const icon = iconOrInitial(item.icon, item.label);
92
+ const railDot = collapsed && (item.badge !== void 0 && item.badge !== null || Boolean(item.count));
91
93
  const shared = {
92
94
  classNames: { root: classes.link },
93
95
  label: item.label,
94
- leftSection: iconOrInitial(item.icon, item.label),
96
+ leftSection: railDot ? /* @__PURE__ */ jsxs("span", { className: classes.navIconDotHost, children: [
97
+ icon,
98
+ /* @__PURE__ */ jsx("span", { className: classes.blockDot, "data-basalt-rail-dot": true, "aria-hidden": true })
99
+ ] }) : icon,
95
100
  // Only the collapsed rail hides the label (CSS), leaving the icon alone — name the link there.
96
101
  // Expanded, the visible text IS the name and carries the count badge; an `aria-label` would
97
102
  // override both and drop the count ("Inbox 5" → "Inbox").
98
- ...collapsed && { "aria-label": item.label },
103
+ ...collapsed && {
104
+ "aria-label": item.count ? `${item.label}, ${item.count}` : item.label
105
+ },
99
106
  rightSection: item.badge ?? (item.count ? /* @__PURE__ */ jsx(NavCountBadge, { count: item.count }) : void 0),
100
107
  active,
101
108
  // Basalt is the one that stamps `aria-current`, not the theme and not a router `<Link>`'s own
@@ -472,6 +472,12 @@
472
472
  box-shadow: 0 0 0 2px var(--mantine-color-body);
473
473
  }
474
474
 
475
+ /* Host for a nav row's rail dot: the dot anchors on the icon itself, not the 48px row. */
476
+ .navIconDotHost {
477
+ position: relative;
478
+ display: inline-flex;
479
+ }
480
+
475
481
  .blockItems {
476
482
  display: flex;
477
483
  flex-direction: column;
@@ -29,6 +29,7 @@ declare const classes: {
29
29
  readonly blockHeaderButton: string
30
30
  readonly blockIcon: string
31
31
  readonly blockDot: string
32
+ readonly navIconDotHost: string
32
33
  readonly blockItems: string
33
34
  readonly blockRow: string
34
35
  readonly blockRowStatic: string
@@ -1 +1 @@
1
- {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/table/data-table.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../../src/table/data-table.tsx"],"names":[],"mappings":"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"}
@@ -588,7 +588,11 @@ function BasaltDataTable(props) {
588
588
  const tableNode = /* @__PURE__ */ jsxs(
589
589
  Table,
590
590
  {
591
- className: cx(classNames?.table),
591
+ className: cx(
592
+ classes.table,
593
+ pageStickyHeader && !contained && classes.pageSticky,
594
+ classNames?.table
595
+ ),
592
596
  ...striped !== void 0 && { striped },
593
597
  ...highlightOnHover !== void 0 && { highlightOnHover },
594
598
  ...stickyHeader !== void 0 && { stickyHeader },
@@ -601,7 +605,7 @@ function BasaltDataTable(props) {
601
605
  withTableBorder,
602
606
  children: [
603
607
  /* @__PURE__ */ jsx(Table.Thead, { children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
604
- hasFolded && /* @__PURE__ */ jsx(Table.Th, { className: classes.foldToggleCell, "aria-hidden": true }),
608
+ hasFolded && /* @__PURE__ */ jsx(Table.Th, { className: classes.foldToggleCell, children: /* @__PURE__ */ jsx("span", { className: classes.srOnly, children: "Details" }) }),
605
609
  headerGroup.headers.map((header) => {
606
610
  const canSort = sortingEnabled && header.column.getCanSort();
607
611
  const sorted = header.column.getIsSorted();
@@ -63,6 +63,49 @@
63
63
  overflow-x: auto;
64
64
  }
65
65
 
66
+ /*
67
+ * A page-scrolled sticky header INSIDE the shell seals the strip above it.
68
+ *
69
+ * `AppShell.Main` is the scrollport and carries block padding (`app-main.module.css`: `stack-md`,
70
+ * one rung down to `stack-sm` from `sm` up). A sticky `<thead>` resolves against the scrollport's
71
+ * CONTENT edge, so at `top: 0` it parked that padding below the band and every body row scrolled
72
+ * through the gap. A negative offset equal to the padding moves the stick line out to the band's
73
+ * edge, flush. The two media/token pairs below mirror `.main` there — the layout suite
74
+ * (`data-table.layout.test.ts`, invariant 8) fails on drift. A consumer `stickyHeaderOffset` is an
75
+ * inline `--table-sticky-header-offset` on the table and beats this class, so it still wins.
76
+ * Outside a shell no `.mantine-AppShell-main` ancestor matches and the offset stays 0.
77
+ */
78
+ :global(.mantine-AppShell-main) .pageSticky {
79
+ --table-sticky-header-offset: calc(-1 * var(--vx-space-stack-md));
80
+ }
81
+
82
+ /* theme-allow raw-media-query — mirrors app-main.module.css's own `sm` switch for Main's block padding; invariant 8 in data-table.layout.test.ts fails on drift */
83
+ @media (min-width: 52.5em) {
84
+ :global(.mantine-AppShell-main) .pageSticky {
85
+ --table-sticky-header-offset: calc(-1 * var(--vx-space-stack-sm));
86
+ }
87
+ }
88
+
89
+ /*
90
+ * A Badge cell keeps its label. Mantine's Badge label is `overflow: hidden; text-overflow:
91
+ * ellipsis`, which gives the badge a min-content of ~0, so an auto-layout column holding only
92
+ * badges was free to shrink under its neighbours (`WORKING` → `WOR…` at 1280px). `max-content`
93
+ * as the floor makes the status column the widest thing a short enum ever needs.
94
+ */
95
+ .table :global(.mantine-Badge-root) {
96
+ min-width: max-content;
97
+ }
98
+
99
+ /* Visually hidden, still announced — the fold toggle column's header has no visible label. */
100
+ .srOnly {
101
+ position: absolute;
102
+ width: 1px;
103
+ height: 1px;
104
+ overflow: hidden;
105
+ clip-path: inset(50%);
106
+ white-space: nowrap;
107
+ }
108
+
66
109
  /*
67
110
  * The selection column's hit area is the WHOLE cell (`docs/CONTROLS-SPEC.md` §2): the
68
111
  * cell is the positioning box and the wrapping <label>'s ::after stretches over it, so a tap
@@ -16,7 +16,10 @@ declare const classes: {
16
16
  readonly foldToggle: string
17
17
  readonly foldToggleCell: string
18
18
  readonly foldWrapper: string
19
+ readonly pageSticky: string
19
20
  readonly selectCell: string
20
21
  readonly selectHit: string
22
+ readonly srOnly: string
23
+ readonly table: string
21
24
  }
22
25
  export default classes
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # basalt-ui v2.0.2
1
+ # basalt-ui v2.0.4
2
2
  # Opinionated framework for Mantine-based React apps — theme, app shell, TanStack Charts, toolchain presets
3
3
  #
4
4
  # Entry points: use the exact import specifier below; do not guess.
@@ -13,7 +13,7 @@
13
13
  # A subpath's `Install:` line is its required peers; `OptionalPeers:` are import()-only, install on use.
14
14
 
15
15
  Package: basalt-ui
16
- Version: 2.0.2
16
+ Version: 2.0.4
17
17
 
18
18
  ## basalt-ui
19
19
  Import: import { ... } from 'basalt-ui'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "basalt-ui",
3
- "version": "2.0.2",
3
+ "version": "2.0.4",
4
4
  "description": "Opinionated framework for Mantine-based React apps — theme, app shell, TanStack Charts, toolchain presets",
5
5
  "keywords": [
6
6
  "charts",
@@ -352,9 +352,53 @@ function registersRouterPlugin(src: string): boolean {
352
352
  })
353
353
  }
354
354
 
355
+ const RELATIVE_IMPORT =
356
+ /(?:\b(?:import|export)\b[^'";]*?\bfrom|\bimport)\s*['"](\.{1,2}\/[^'"]+)['"]/g
357
+
358
+ /** The source file a relative specifier names: as written, `.ts`/`.tsx` appended, or a directory index. */
359
+ function resolveRelative(from: string, spec: string): string | null {
360
+ const base = resolve(dirname(from), spec.replace(/\.[jt]sx?$/, ''))
361
+ return (
362
+ [
363
+ resolve(dirname(from), spec),
364
+ `${base}.ts`,
365
+ `${base}.tsx`,
366
+ `${base}/index.ts`,
367
+ `${base}/index.tsx`,
368
+ ].find((f) => /\.[jt]sx?$/.test(f) && existsSync(f)) ?? null
369
+ )
370
+ }
371
+
372
+ /**
373
+ * Whether a module the entry imports (relative imports, three deep) calls `createBasaltRouter` —
374
+ * the router often lives in a singleton module other code also imports.
375
+ */
376
+ function routerCreatedInImports(cwd: string, entry: string): boolean {
377
+ const seen = new Set([resolve(cwd, entry)])
378
+ let frontier = [...seen]
379
+ for (let depth = 0; depth < 3 && frontier.length > 0; depth++) {
380
+ const next: string[] = []
381
+ for (const file of frontier) {
382
+ for (const m of (readIfExists(file) ?? '').matchAll(RELATIVE_IMPORT)) {
383
+ const dep = resolveRelative(file, m[1] ?? '')
384
+ if (dep === null || seen.has(dep)) continue
385
+ seen.add(dep)
386
+ const { code, inLiteral } = tokenize(readIfExists(dep) ?? '')
387
+ const called = [...code.matchAll(/\bcreateBasaltRouter\b/g)].some(
388
+ (c) => !inLiteral(c.index),
389
+ )
390
+ if (called) return true
391
+ next.push(dep)
392
+ }
393
+ }
394
+ frontier = next
395
+ }
396
+ return false
397
+ }
398
+
355
399
  /**
356
400
  * `app-wiring`: the entry module `index.html` loads (default src/main.tsx) mounts `BasaltProvider`
357
- * on a `createBasaltRouter` router, and the router tree is generated: the vite config calls a
401
+ * on a `createBasaltRouter` router (called in the entry or a module it imports), and the router tree is generated: the vite config calls a
358
402
  * binding imported from `@tanstack/router-plugin` in `plugins`, or a `routeTree.gen.*` already sits
359
403
  * beside the entry (or in src/). `basaltViteConfig` does not register that plugin, so naming it
360
404
  * proves nothing.
@@ -371,7 +415,10 @@ export function appWiringCheck(cwd: string): Check {
371
415
  const { code, inLiteral } = tokenize(text)
372
416
  const used = (name: string): boolean =>
373
417
  [...code.matchAll(new RegExp(`\\b${name}\\b`, 'g'))].some((m) => !inLiteral(m.index))
374
- const missing = ['BasaltProvider', 'createBasaltRouter'].filter((name) => !used(name))
418
+ const missing = ['BasaltProvider', 'createBasaltRouter'].filter(
419
+ (name) =>
420
+ !used(name) && !(name === 'createBasaltRouter' && routerCreatedInImports(cwd, entry)),
421
+ )
375
422
  if (missing.length > 0) {
376
423
  return {
377
424
  fail:
package/src/cli/index.ts CHANGED
@@ -474,6 +474,8 @@ type TemplateVars = {
474
474
  * `bunx basalt-ui` only as the pre-install fallback.
475
475
  */
476
476
  BASALT_BIN: string
477
+ /** The CI gate steps after install: `make check` when the repo owns one, else the built-in set. */
478
+ GATE_STEPS: string
477
479
  }
478
480
 
479
481
  // The block markers the AGENTS.md template emits. The begin marker carries the framework version
@@ -536,6 +538,26 @@ export function basaltBinCommand(install: BasaltInstall, cwd: string): string {
536
538
  return `${relativePosix(cwd, binDir).replace(/^\.\//, '')}/basalt-ui`
537
539
  }
538
540
 
541
+ /**
542
+ * The consumer owns the CI gate when its Makefile has a `check:` target: `doctor` and `sync --check`
543
+ * stay as steps of their own (drift is never skippable), then `make check` replaces the built-in
544
+ * lint/theme/format steps. Without one, the built-in steps run. Rendered at `{{GATE_STEPS}}`.
545
+ */
546
+ export function ciGateSteps(cwd: string): string {
547
+ const owned = /^check\s*:/m.test(readIfExists(resolve(cwd, 'Makefile')) ?? '')
548
+ const drift = ["- run: '{{BASALT_BIN}} doctor'", "- run: '{{BASALT_BIN}} sync --check'"]
549
+ const steps = owned
550
+ ? [...drift, '- run: make check']
551
+ : [
552
+ '- run: bunx oxlint .',
553
+ drift[0],
554
+ "- run: '{{BASALT_BIN}} check-theme'",
555
+ drift[1],
556
+ "- run: bunx oxfmt {{ROOTS_GLOBS}} '!**/dist/**' --check",
557
+ ]
558
+ return steps.join('\n ')
559
+ }
560
+
539
561
  /** Build the template-variable map from the framework root + consumer cwd/config. */
540
562
  function buildTemplateVars(pkgRoot: string, cwd: string, cfg: BasaltConfig): TemplateVars {
541
563
  const install = findBasaltInstall(cwd)
@@ -548,15 +570,20 @@ function buildTemplateVars(pkgRoot: string, cwd: string, cfg: BasaltConfig): Tem
548
570
  OXLINT_PRESET_PATH: shippedAssetPath(install, cwd, OXLINT_FILES.preset),
549
571
  LEFTHOOK_PRESET_PATH: shippedAssetPath(install, cwd, 'configs/lefthook.yml'),
550
572
  BASALT_BIN: basaltBinCommand(install, cwd),
573
+ GATE_STEPS: ciGateSteps(cwd),
551
574
  }
552
575
  }
553
576
 
554
577
  /** Substitute every `{{KEY}}` placeholder from the variable map; unknown keys are left verbatim. */
555
578
  function fillTemplate(tpl: string, vars: TemplateVars): string {
556
- return tpl.replace(/\{\{(\w+)\}\}/g, (m, key: string) => {
557
- const v = (vars as Record<string, string>)[key]
558
- return v ?? m
559
- })
579
+ const fill = (text: string): string =>
580
+ text.replace(/\{\{(\w+)\}\}/g, (m, key: string) => {
581
+ const v = (vars as Record<string, string>)[key]
582
+ return v ?? m
583
+ })
584
+ // The marker is a YAML comment so the template stays valid YAML; GATE_STEPS itself carries
585
+ // placeholders, so it expands before the generic pass.
586
+ return fill(tpl.replace('# {{GATE_STEPS}}', vars.GATE_STEPS))
560
587
  }
561
588
 
562
589
  /**
@@ -41,6 +41,7 @@ import type { Telemetry } from '../telemetry'
41
41
  import type { BasaltDevDockTool } from '../dev-dock'
42
42
  import type { BasaltRouter, BasaltRouterContext } from './create-router'
43
43
  import { useRegistryHotkeys } from './hotkeys'
44
+ import type { FlatNavItem } from '../router-tanstack/nav'
44
45
  import { buildSpotlightActions } from './spotlight-actions'
45
46
 
46
47
  export type BasaltProviderProps = {
@@ -79,6 +80,12 @@ export type BasaltProviderProps = {
79
80
  * can answer. Default `'compact'`. SSR only; an SSR desktop app SHOULD pass it.
80
81
  */
81
82
  sizeClassHint?: SizeClass
83
+ /**
84
+ * Label for the `nav.<id>` Spotlight entries generated from `defineNav`, e.g.
85
+ * `(item) => `Go to ${item.label}``. Default: the destination's own label. A `defineCommands`
86
+ * entry with id `nav.<id>` replaces the generated one outright.
87
+ */
88
+ navCommandLabel?: (item: FlatNavItem) => string
82
89
  } & Omit<MantineProviderProps, 'children' | 'theme' | 'defaultColorScheme' | 'cssVariablesResolver'>
83
90
 
84
91
  // ── Root error boundary ───────────────────────────────────────────────────────────────────────────
@@ -408,6 +415,7 @@ export function BasaltProvider({
408
415
  defaultColorScheme = 'dark',
409
416
  nonce,
410
417
  sizeClassHint = 'compact',
418
+ navCommandLabel,
411
419
  ...rest
412
420
  }: BasaltProviderProps) {
413
421
  useDuplicateProviderGuard()
@@ -432,8 +440,8 @@ export function BasaltProvider({
432
440
  // appears, not frozen at mount — and `detectMac` (inside the builder) never runs during render.
433
441
  const [actions, setActions] = useState<SpotlightActionData[]>([])
434
442
  const refreshActions = useCallback(
435
- () => setActions(buildSpotlightActions(router, setDevTool)),
436
- [router],
443
+ () => setActions(buildSpotlightActions(router, setDevTool, navCommandLabel)),
444
+ [router, navCommandLabel],
437
445
  )
438
446
  useEffect(refreshActions, [refreshActions])
439
447
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * The provider's Spotlight list: the `defineCommands` registry, then the `defineNav` destinations
3
- * (via `flattenNav`), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
3
+ * (via `flattenNav`, skipping any id a registered `nav.<id>` command already owns), then the three dev-dock commands in dev. A snapshot rebuilt each time Spotlight
4
4
  * opens, so a command's `when()` is current. Not for use during render (`detectMac` reads `navigator`).
5
5
  */
6
6
  import type { SpotlightActionData } from '@mantine/spotlight'
@@ -8,6 +8,7 @@ import type { AnyRouter } from '@tanstack/react-router'
8
8
  import { getActiveCommands } from '../commands/define-commands'
9
9
  import { detectMac, formatShortcutDisplay } from '../commands/shortcut-format'
10
10
  import { flattenNav, getActiveNav } from '../router-tanstack/nav'
11
+ import type { FlatNavItem } from '../router-tanstack/nav'
11
12
  import type { BasaltDevDockTool } from '../dev-dock'
12
13
  import { runCommandSafely } from './hotkeys'
13
14
 
@@ -20,10 +21,12 @@ const DEV_TOOLS: ReadonlyArray<{ tool: BasaltDevDockTool; label: string }> = [
20
21
  export function buildSpotlightActions(
21
22
  router: AnyRouter,
22
23
  openDevTool: (tool: BasaltDevDockTool) => void,
24
+ navCommandLabel?: (item: FlatNavItem) => string,
23
25
  ): SpotlightActionData[] {
24
26
  const actions: SpotlightActionData[] = []
27
+ const commands = getActiveCommands()
25
28
 
26
- for (const [id, cmd] of Object.entries(getActiveCommands())) {
29
+ for (const [id, cmd] of Object.entries(commands)) {
27
30
  if (cmd.when !== undefined && !cmd.when()) continue
28
31
  actions.push({
29
32
  id,
@@ -42,9 +45,11 @@ export function buildSpotlightActions(
42
45
  if (nav !== undefined) {
43
46
  for (const item of flattenNav(nav)) {
44
47
  if (item.disabled === true) continue
48
+ // A registered `nav.<id>` command owns that destination: the consumer wins, no duplicate.
49
+ if (`nav.${item.id}` in commands) continue
45
50
  actions.push({
46
51
  id: `nav.${item.id}`,
47
- label: item.label,
52
+ label: navCommandLabel?.(item) ?? item.label,
48
53
  group: item.groupLabel,
49
54
  leftSection: item.icon,
50
55
  // `link` is the destination's own `linkOptions`, so a store-backed `search` thunk restores
@@ -472,6 +472,12 @@
472
472
  box-shadow: 0 0 0 2px var(--mantine-color-body);
473
473
  }
474
474
 
475
+ /* Host for a nav row's rail dot: the dot anchors on the icon itself, not the 48px row. */
476
+ .navIconDotHost {
477
+ position: relative;
478
+ display: inline-flex;
479
+ }
480
+
475
481
  .blockItems {
476
482
  display: flex;
477
483
  flex-direction: column;
@@ -29,6 +29,7 @@ declare const classes: {
29
29
  readonly blockHeaderButton: string
30
30
  readonly blockIcon: string
31
31
  readonly blockDot: string
32
+ readonly navIconDotHost: string
32
33
  readonly blockItems: string
33
34
  readonly blockRow: string
34
35
  readonly blockRowStatic: string
@@ -207,14 +207,28 @@ function NavLinkBody({
207
207
  collapsed?: boolean
208
208
  }) {
209
209
  const Anchor = item.Anchor
210
+ const icon = iconOrInitial(item.icon, item.label)
211
+ // The rail hides the right section (where the badge lives), so a badged row keeps a dot on its
212
+ // icon instead — the count rides the accessible name since the number itself has no room.
213
+ const railDot =
214
+ collapsed && ((item.badge !== undefined && item.badge !== null) || Boolean(item.count))
210
215
  const shared = {
211
216
  classNames: { root: classes.link },
212
217
  label: item.label,
213
- leftSection: iconOrInitial(item.icon, item.label),
218
+ leftSection: railDot ? (
219
+ <span className={classes.navIconDotHost}>
220
+ {icon}
221
+ <span className={classes.blockDot} data-basalt-rail-dot aria-hidden />
222
+ </span>
223
+ ) : (
224
+ icon
225
+ ),
214
226
  // Only the collapsed rail hides the label (CSS), leaving the icon alone — name the link there.
215
227
  // Expanded, the visible text IS the name and carries the count badge; an `aria-label` would
216
228
  // override both and drop the count ("Inbox 5" → "Inbox").
217
- ...(collapsed && { 'aria-label': item.label }),
229
+ ...(collapsed && {
230
+ 'aria-label': item.count ? `${item.label}, ${item.count}` : item.label,
231
+ }),
218
232
  rightSection: item.badge ?? (item.count ? <NavCountBadge count={item.count} /> : undefined),
219
233
  active,
220
234
  // Basalt is the one that stamps `aria-current`, not the theme and not a router `<Link>`'s own
@@ -63,6 +63,49 @@
63
63
  overflow-x: auto;
64
64
  }
65
65
 
66
+ /*
67
+ * A page-scrolled sticky header INSIDE the shell seals the strip above it.
68
+ *
69
+ * `AppShell.Main` is the scrollport and carries block padding (`app-main.module.css`: `stack-md`,
70
+ * one rung down to `stack-sm` from `sm` up). A sticky `<thead>` resolves against the scrollport's
71
+ * CONTENT edge, so at `top: 0` it parked that padding below the band and every body row scrolled
72
+ * through the gap. A negative offset equal to the padding moves the stick line out to the band's
73
+ * edge, flush. The two media/token pairs below mirror `.main` there — the layout suite
74
+ * (`data-table.layout.test.ts`, invariant 8) fails on drift. A consumer `stickyHeaderOffset` is an
75
+ * inline `--table-sticky-header-offset` on the table and beats this class, so it still wins.
76
+ * Outside a shell no `.mantine-AppShell-main` ancestor matches and the offset stays 0.
77
+ */
78
+ :global(.mantine-AppShell-main) .pageSticky {
79
+ --table-sticky-header-offset: calc(-1 * var(--vx-space-stack-md));
80
+ }
81
+
82
+ /* theme-allow raw-media-query — mirrors app-main.module.css's own `sm` switch for Main's block padding; invariant 8 in data-table.layout.test.ts fails on drift */
83
+ @media (min-width: 52.5em) {
84
+ :global(.mantine-AppShell-main) .pageSticky {
85
+ --table-sticky-header-offset: calc(-1 * var(--vx-space-stack-sm));
86
+ }
87
+ }
88
+
89
+ /*
90
+ * A Badge cell keeps its label. Mantine's Badge label is `overflow: hidden; text-overflow:
91
+ * ellipsis`, which gives the badge a min-content of ~0, so an auto-layout column holding only
92
+ * badges was free to shrink under its neighbours (`WORKING` → `WOR…` at 1280px). `max-content`
93
+ * as the floor makes the status column the widest thing a short enum ever needs.
94
+ */
95
+ .table :global(.mantine-Badge-root) {
96
+ min-width: max-content;
97
+ }
98
+
99
+ /* Visually hidden, still announced — the fold toggle column's header has no visible label. */
100
+ .srOnly {
101
+ position: absolute;
102
+ width: 1px;
103
+ height: 1px;
104
+ overflow: hidden;
105
+ clip-path: inset(50%);
106
+ white-space: nowrap;
107
+ }
108
+
66
109
  /*
67
110
  * The selection column's hit area is the WHOLE cell (`docs/CONTROLS-SPEC.md` §2): the
68
111
  * cell is the positioning box and the wrapping <label>'s ::after stretches over it, so a tap
@@ -16,7 +16,10 @@ declare const classes: {
16
16
  readonly foldToggle: string
17
17
  readonly foldToggleCell: string
18
18
  readonly foldWrapper: string
19
+ readonly pageSticky: string
19
20
  readonly selectCell: string
20
21
  readonly selectHit: string
22
+ readonly srOnly: string
23
+ readonly table: string
21
24
  }
22
25
  export default classes
@@ -1642,7 +1642,11 @@ export function BasaltDataTable<T extends RowData>(props: BasaltDataTableProps<T
1642
1642
 
1643
1643
  const tableNode = (
1644
1644
  <Table
1645
- className={cx(classNames?.table)}
1645
+ className={cx(
1646
+ classes.table,
1647
+ pageStickyHeader && !contained && classes.pageSticky,
1648
+ classNames?.table,
1649
+ )}
1646
1650
  {...(striped !== undefined && { striped })}
1647
1651
  {...(highlightOnHover !== undefined && { highlightOnHover })}
1648
1652
  {...(stickyHeader !== undefined && { stickyHeader })}
@@ -1659,7 +1663,11 @@ export function BasaltDataTable<T extends RowData>(props: BasaltDataTableProps<T
1659
1663
  <Table.Tr key={headerGroup.id}>
1660
1664
  {/* The disclosure toggle column has no header of its own — nothing is "sorted" or
1661
1665
  "selected all" across it, only revealed per row. */}
1662
- {hasFolded && <Table.Th className={classes.foldToggleCell} aria-hidden />}
1666
+ {hasFolded && (
1667
+ <Table.Th className={classes.foldToggleCell}>
1668
+ <span className={classes.srOnly}>Details</span>
1669
+ </Table.Th>
1670
+ )}
1663
1671
  {headerGroup.headers.map((header) => {
1664
1672
  const canSort = sortingEnabled && header.column.getCanSort()
1665
1673
  const sorted = header.column.getIsSorted()