Skip to content

Commit 429f1fd

Browse files
committed
feat: migrate toolchain to Vite+
Replace split vite/vitest/oxlint/oxfmt tooling with vite-plus 0.2.7 via vp migrate. - Bump apps/web to Vite 8.2.0, resolved through the new pnpm catalog to the Rolldown-powered @voidzero-dev/vite-plus-core build - Consolidate .oxlintrc.json into the new root vite.config.ts - Rewrite vitest imports to vite-plus/test in 56 files, switch package scripts to vp lint / vp fmt / vp test run - Reformat 319 files with the bundled Oxfmt 0.62, which now also formats Markdown - Keep husky + gitleaks pre-commit hooks; vp hook setup skipped - Leave type-aware linting off in the root config: it reports 88 pre-existing findings and its suggested rootDir fix would break the apps/api build, which compiles workspace packages via tsconfig paths
1 parent 17aaf48 commit 429f1fd

383 files changed

Lines changed: 13854 additions & 9106 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/migrate-radix-to-base/SKILL.md‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ transforming, and record gaps in the report.
4242
fetch base variants directly by URL instead
4343
(`https://ui.shadcn.com/r/styles/base-<style>/<component>.json`).
4444
3. PRISTINE wrappers, whole-project mode: `shadcn add <component>
45-
--overwrite` delivers the base variant with the project's exact
45+
--overwrite` delivers the base variant with the project's exact
4646
icon/font/preset resolution. Never bulk `--all --overwrite`; go
4747
component by component, or you drown in unrelated registry version
4848
drift. PROGRESSIVE mode: never use `--overwrite` (it destroys the
@@ -59,9 +59,9 @@ transforming, and record gaps in the report.
5959
file. The registry sometimes reorders functions between variants, which
6060
makes three-way merges report zero conflicts while leaving stale radix
6161
hunks in place. A clean merge is NOT proof of a clean file.
62-
This is more reliable than reconstructing transforms; use it whenever the
63-
pair exists. Consumer/app code has no CLI mechanism: always hand-migrate it
64-
against `consumer-props.md`.
62+
This is more reliable than reconstructing transforms; use it whenever the
63+
pair exists. Consumer/app code has no CLI mechanism: always hand-migrate it
64+
against `consumer-props.md`.
6565
- **Legacy styles (new-york, new-york-v4, default): classification only, no
6666
replay.** These have no base counterpart (there is no base-new-york), and
6767
retargeting onto a base-<style> variant would restyle the user's app. Use
@@ -83,6 +83,7 @@ transforming, and record gaps in the report.
8383
## Modes
8484

8585
**Progressive (default).** "Migrate accordion" = one component, strangler-fig:
86+
8687
1. Detect in-progress state first: an existing `<component>-base.tsx`,
8788
consumers split between old/new imports. The files ARE the state; resume,
8889
never restart.
@@ -126,6 +127,7 @@ Typecheck per file, build per batch, full build at the end vs the baseline.
126127
Reports live in a `.migration/` directory at the project root, ONE FILE PER
127128
COMPONENT: `.migration/<component>.md` (e.g. `.migration/accordion.md`).
128129
Rules:
130+
129131
- Each run writes (or fully overwrites) the file for each component it
130132
migrated. Re-running a component replaces its report; never touch other
131133
components' files.

‎.agents/skills/migrate-radix-to-base/class-mapping.md‎

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ including app code. They are safe, mechanical rewrites.
55

66
## Data-attribute selectors
77

8-
| Radix pattern | Base UI pattern |
9-
|---|---|
10-
| `data-[state=open]:` | `data-open:` |
11-
| `data-[state=closed]:` | `data-closed:` |
12-
| `data-[state=checked]:` | `data-checked:` |
13-
| `data-[state=unchecked]:` | `data-unchecked:` |
14-
| `data-[state=active]:` (tabs) | `data-active:` |
15-
| `data-[state=on]:` (toggle) | `data-pressed:` |
16-
| `data-[highlighted]:` | `data-highlighted:` (unchanged) |
17-
| `data-[disabled]:` | `data-disabled:` (unchanged) |
18-
| `data-[side=...]:` | `data-[side=...]:` (unchanged, still parameterized) |
19-
| `group-data-[state=open]` / `peer-data-[state=open]` | `group-data-open` / `peer-data-open` |
20-
| submenu trigger open marker `data-[state=open]:` | `data-popup-open:` |
8+
| Radix pattern | Base UI pattern |
9+
| ---------------------------------------------------- | --------------------------------------------------- |
10+
| `data-[state=open]:` | `data-open:` |
11+
| `data-[state=closed]:` | `data-closed:` |
12+
| `data-[state=checked]:` | `data-checked:` |
13+
| `data-[state=unchecked]:` | `data-unchecked:` |
14+
| `data-[state=active]:` (tabs) | `data-active:` |
15+
| `data-[state=on]:` (toggle) | `data-pressed:` |
16+
| `data-[highlighted]:` | `data-highlighted:` (unchanged) |
17+
| `data-[disabled]:` | `data-disabled:` (unchanged) |
18+
| `data-[side=...]:` | `data-[side=...]:` (unchanged, still parameterized) |
19+
| `group-data-[state=open]` / `peer-data-[state=open]` | `group-data-open` / `peer-data-open` |
20+
| submenu trigger open marker `data-[state=open]:` | `data-popup-open:` |
2121

2222
## Animation idiom
2323

@@ -34,15 +34,15 @@ uses per-side slide classes, keep the `data-[side=...]` or
3434

3535
## CSS variables
3636

37-
| Radix var | Base UI var |
38-
|---|---|
39-
| `--radix-<comp>-content-transform-origin` | `--transform-origin` |
40-
| `--radix-<comp>-content-available-height` | `--available-height` |
41-
| `--radix-<comp>-content-available-width` | `--available-width` |
42-
| `--radix-<comp>-trigger-width` | `--anchor-width` |
43-
| `--radix-<comp>-trigger-height` | `--anchor-height` |
44-
| `--radix-accordion-content-height` | `--accordion-panel-height` |
45-
| `--radix-collapsible-content-height` | `--collapsible-panel-height` |
37+
| Radix var | Base UI var |
38+
| ----------------------------------------------- | -------------------------------------------- |
39+
| `--radix-<comp>-content-transform-origin` | `--transform-origin` |
40+
| `--radix-<comp>-content-available-height` | `--available-height` |
41+
| `--radix-<comp>-content-available-width` | `--available-width` |
42+
| `--radix-<comp>-trigger-width` | `--anchor-width` |
43+
| `--radix-<comp>-trigger-height` | `--anchor-height` |
44+
| `--radix-accordion-content-height` | `--accordion-panel-height` |
45+
| `--radix-collapsible-content-height` | `--collapsible-panel-height` |
4646
| `--radix-navigation-menu-viewport-height/width` | `--positioner-height` / `--positioner-width` |
4747

4848
## Element changes kill pseudo-class variants

‎.agents/skills/migrate-radix-to-base/consumer-props.md‎

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,39 @@ check node_modules/@base-ui/react/**/*.d.ts, never guess.
88

99
## Universal
1010

11-
| Radix | Base UI | Call-site action |
12-
|---|---|---|
11+
| Radix | Base UI | Call-site action |
12+
| ----------------------- | ------------- | --------------------------------------------------------------------------- |
1313
| `asChild` (any wrapper) | `render` prop | `<Trigger asChild><Button/></Trigger>` -> `<Trigger render={<Button/>}>...` |
1414

1515
## Per component
1616

17-
| Component | Radix prop | Base UI fate | Call-site action |
18-
|---|---|---|---|
19-
| Accordion | `type="single"\|"multiple"` + `collapsible` | dropped; `value`/`defaultValue` are ALWAYS arrays; multiple-open via `multiple` | `type="single" collapsible` -> remove both; wrap values in arrays; `type="multiple"` -> `multiple` |
20-
| Tabs | `activationMode="manual"` | dropped; Base UI defaults to MANUAL activation | remove prop; near-equivalent opt-in is `Tabs.List activateOnFocus` (behavior delta: flag, do not auto-add) |
21-
| Select | `position="popper"\|"item-aligned"` | `alignItemWithTrigger` boolean (on Positioner; wrappers expose it) | `position="popper"` -> `alignItemWithTrigger={false}`; `item-aligned` -> `alignItemWithTrigger` (default) |
22-
| TooltipProvider | `delayDuration`, `skipDelayDuration` | `delay`; skip-delay concept dropped | rename / remove |
23-
| Tooltip | `disableHoverableContent` | NO equivalent | remove; FLAG the behavior change in the report |
24-
| Avatar.Image | `delayMs` | `delay` | rename |
25-
| ScrollArea | `type="always"\|"scroll"\|...` | dropped | remove |
26-
| Separator | `decorative` | dropped | remove |
27-
| Checkbox | `checked="indeterminate"` | `indeterminate` is a SEPARATE boolean prop | `checked="indeterminate"` -> `indeterminate` + boolean `checked` |
28-
| Slider | `onValueChange(value)` | signature gains event details; also `inverted` REMOVED | check handler arity; remove `inverted` (flag vertical-inverted usage) |
29-
| Select | `onValueChange(value: string)` | widens to `(value: Value \| null, eventDetails)` | `useState<string>` + `onValueChange={setState}` breaks: widen state to `string \| null` or wrap the setter |
30-
| Slider | `onValueCommit` | `onValueCommitted` | rename |
31-
| ToggleGroup | `type="single"\|"multiple"` | `multiple` boolean; value shape arrays | same treatment as Accordion |
32-
| ToggleGroup / Toolbar | `rovingFocus={false}` | dropped (roving focus always on); `loop` -> `loopFocus` | remove / rename |
33-
| Menubar | `value`/`onValueChange` (active menu) | dropped; control per Menu.Root `open` | restructure if used; usually unused |
34-
| Menubar | `loop` | `loopFocus` | rename |
35-
| ContextMenu.Root | `modal` | REMOVED | remove |
36-
| ContextMenu.Trigger | `disabled` | REMOVED | remove; gate the trigger yourself |
37-
| DropdownMenu/ContextMenu items | (Radix closed menu on select) | `closeOnClick` defaults FALSE on CheckboxItem/RadioItem | behavior delta: flag; add `closeOnClick` only if the user asks |
38-
| NavigationMenu | `delayDuration`(200), `skipDelayDuration`, `viewport` | `delay`(50) + `closeDelay`; viewport prop gone (Positioner handles it) | rename/remove; flag the 200->50 hover-delay feel change |
39-
| Popover / HoverCard | `openDelay`/`closeDelay` on Root | move to TRIGGER as `delay`/`closeDelay` | relocate props Root -> Trigger |
40-
| Dialog / AlertDialog | `onOpenAutoFocus` | `initialFocus` (element/ref-based, not event-based) | restructure: pass target instead of preventDefault handler |
41-
| Dialog / AlertDialog | `onCloseAutoFocus` | `finalFocus` | same restructure |
42-
| Dialog family | `onEscapeKeyDown`, `onPointerDownOutside`, `onInteractOutside` | consolidated; see the overlays reference for exact per-part signatures | consult overlays.md; do not guess |
43-
| DirectionProvider | `dir` | `direction` | rename |
17+
| Component | Radix prop | Base UI fate | Call-site action |
18+
| ------------------------------ | -------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
19+
| Accordion | `type="single"\|"multiple"` + `collapsible` | dropped; `value`/`defaultValue` are ALWAYS arrays; multiple-open via `multiple` | `type="single" collapsible` -> remove both; wrap values in arrays; `type="multiple"` -> `multiple` |
20+
| Tabs | `activationMode="manual"` | dropped; Base UI defaults to MANUAL activation | remove prop; near-equivalent opt-in is `Tabs.List activateOnFocus` (behavior delta: flag, do not auto-add) |
21+
| Select | `position="popper"\|"item-aligned"` | `alignItemWithTrigger` boolean (on Positioner; wrappers expose it) | `position="popper"` -> `alignItemWithTrigger={false}`; `item-aligned` -> `alignItemWithTrigger` (default) |
22+
| TooltipProvider | `delayDuration`, `skipDelayDuration` | `delay`; skip-delay concept dropped | rename / remove |
23+
| Tooltip | `disableHoverableContent` | NO equivalent | remove; FLAG the behavior change in the report |
24+
| Avatar.Image | `delayMs` | `delay` | rename |
25+
| ScrollArea | `type="always"\|"scroll"\|...` | dropped | remove |
26+
| Separator | `decorative` | dropped | remove |
27+
| Checkbox | `checked="indeterminate"` | `indeterminate` is a SEPARATE boolean prop | `checked="indeterminate"` -> `indeterminate` + boolean `checked` |
28+
| Slider | `onValueChange(value)` | signature gains event details; also `inverted` REMOVED | check handler arity; remove `inverted` (flag vertical-inverted usage) |
29+
| Select | `onValueChange(value: string)` | widens to `(value: Value \| null, eventDetails)` | `useState<string>` + `onValueChange={setState}` breaks: widen state to `string \| null` or wrap the setter |
30+
| Slider | `onValueCommit` | `onValueCommitted` | rename |
31+
| ToggleGroup | `type="single"\|"multiple"` | `multiple` boolean; value shape arrays | same treatment as Accordion |
32+
| ToggleGroup / Toolbar | `rovingFocus={false}` | dropped (roving focus always on); `loop` -> `loopFocus` | remove / rename |
33+
| Menubar | `value`/`onValueChange` (active menu) | dropped; control per Menu.Root `open` | restructure if used; usually unused |
34+
| Menubar | `loop` | `loopFocus` | rename |
35+
| ContextMenu.Root | `modal` | REMOVED | remove |
36+
| ContextMenu.Trigger | `disabled` | REMOVED | remove; gate the trigger yourself |
37+
| DropdownMenu/ContextMenu items | (Radix closed menu on select) | `closeOnClick` defaults FALSE on CheckboxItem/RadioItem | behavior delta: flag; add `closeOnClick` only if the user asks |
38+
| NavigationMenu | `delayDuration`(200), `skipDelayDuration`, `viewport` | `delay`(50) + `closeDelay`; viewport prop gone (Positioner handles it) | rename/remove; flag the 200->50 hover-delay feel change |
39+
| Popover / HoverCard | `openDelay`/`closeDelay` on Root | move to TRIGGER as `delay`/`closeDelay` | relocate props Root -> Trigger |
40+
| Dialog / AlertDialog | `onOpenAutoFocus` | `initialFocus` (element/ref-based, not event-based) | restructure: pass target instead of preventDefault handler |
41+
| Dialog / AlertDialog | `onCloseAutoFocus` | `finalFocus` | same restructure |
42+
| Dialog family | `onEscapeKeyDown`, `onPointerDownOutside`, `onInteractOutside` | consolidated; see the overlays reference for exact per-part signatures | consult overlays.md; do not guess |
43+
| DirectionProvider | `dir` | `direction` | rename |
4444

4545
## Callback signature rule
4646

0 commit comments

Comments
 (0)