Update ReallySimpleDocs to 1.0.1

This commit is contained in:
Ronan Berder
2026-06-24 20:17:41 +08:00
parent a8c066306b
commit b3c5d16e28
7 changed files with 5 additions and 625 deletions
-8
View File
@@ -1,8 +0,0 @@
# TODO
## Chart
- Verify chart tick label color against upstream shadcn/ui across light/dark and all style packs. The target is `muted-foreground`; Chart.js renders labels on canvas, so it may not visually match Recharts SVG text exactly even with the same token.
- Add an explicit legend interaction option if needed. Upstream shadcn/ui's `ChartLegendContent` is display-only by default, so Basecoat should not toggle series visibility unless users opt into it.
- Document chart sizing escape hatches after visual QA. Default should stay `aspect-video`, matching upstream `ChartContainer`; users can override with height, `min-h-*`, or `aspect-*` on the generated container path once the public API is settled.
- Add chart examples for line, area, and tooltip indicator variants once the MVP bar chart behavior is visually aligned.
-156
View File
@@ -1,156 +0,0 @@
# Basecoat Multi-Style Migration Handoff
This handoff is for resuming the `release/1.0.0` work on Basecoat's split CSS architecture and shadcn/ui v4 style-pack support.
## Ground Truth
- Local Basecoat repo: `/Users/hunvreus/Workspace/basecoat`
- Local shadcn/ui upstream repo: `/Users/hunvreus/Workspace/_sandbox/shadcn-ui`
- Upstream branch/commit verified during this pass: `main` at `460ad60d8`
- Upstream style registry: `../_sandbox/shadcn-ui/apps/v4/registry/styles.tsx`
- Current upstream styles: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, `rhea`
The earlier five-style assumption was wrong. Luma, Sera, and Rhea are current upstream styles and must be included in every component migration.
## Core Rules
- Keep Basecoat's own class API (`btn`, `btn-outline`, `dialog`, `popover`, etc.).
- Do not introduce shadcn/ui `cn-*` classes.
- Use upstream shadcn/ui as a style reference, not as selectors to copy directly.
- Translate upstream style intent to Basecoat selectors and markup.
- Component CSS should stay structural/shared when possible.
- Style-pack CSS owns visual differences: radius, density, spacing, typography, focus rings, shadows, and style-specific variant details.
- Default aggregate behavior remains Vega.
- Non-default styles are selected by importing or loading the relevant style file, not by requiring `.style-*` wrapper classes.
## Files To Check For Every Component
- Basecoat component CSS: `src/css/components/<component>.css`
- Basecoat templates/macros if relevant: `src/nunjucks/*.njk`, `src/jinja/*.html.jinja`
- Basecoat docs page: `docs/src/components/<component>.md`
- Upstream base component: `../_sandbox/shadcn-ui/apps/v4/registry/bases/base/ui/<component>.tsx`
- Upstream styles: `../_sandbox/shadcn-ui/apps/v4/registry/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
- Basecoat styles: `src/css/styles/{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
## Required Process
1. Review current Basecoat CSS and markup/templates/docs.
2. Review upstream base component source.
3. Review the component section in all eight upstream style files.
4. Decide what belongs in shared component CSS versus each style file.
5. Remove outdated shared visual rules if those rules are now style-owned.
6. Implement the component section in all eight Basecoat style files.
7. Keep Basecoat selectors only.
8. Classify non-trivial differences as `intentional`, `drift fixed`, or `deferred`.
9. Update `migration-tracker.md`.
10. Run `npm run build`.
11. Run `npm run docs:build` when docs or docs style assets are touched.
12. Browser-check light/dark and all eight styles.
Do not mark a component done just because CSS compiles.
## What Has Been Done
- Split CSS source into:
- `src/css/base/base.css`
- `src/css/components/*.css`
- `src/css/styles/*.css`
- Kept `src/css/basecoat.css` as the backward-compatible default aggregate.
- Added `src/css/basecoat.all.css` as an explicit all-in-one Tailwind source.
- Updated `scripts/build.js` to copy split CSS folders into `packages/css/dist`.
- Split `select` and `native-select`.
- Kept `src/css/components/form.css` as a convenience aggregate rather than nesting under `components/form/*`.
- Added docs style switcher in `docs/src/_includes/partials/header.njk`.
- Added docs stylesheet swapping in `docs/src/_includes/layouts/base.njk`.
- Added docs style entrypoints for all non-default styles:
- `docs/css/style-nova.css`
- `docs/css/style-maia.css`
- `docs/css/style-lyra.css`
- `docs/css/style-mira.css`
- `docs/css/style-luma.css`
- `docs/css/style-sera.css`
- `docs/css/style-rhea.css`
- Added Basecoat style files for all eight upstream styles:
- `src/css/styles/vega.css`
- `src/css/styles/nova.css`
- `src/css/styles/maia.css`
- `src/css/styles/lyra.css`
- `src/css/styles/mira.css`
- `src/css/styles/luma.css`
- `src/css/styles/sera.css`
- `src/css/styles/rhea.css`
## Button Status
Button is the only component with style-pack sections currently present.
Files involved:
- `src/css/components/button.css`
- `src/css/styles/vega.css`
- `src/css/styles/nova.css`
- `src/css/styles/maia.css`
- `src/css/styles/lyra.css`
- `src/css/styles/mira.css`
- `src/css/styles/luma.css`
- `src/css/styles/sera.css`
- `src/css/styles/rhea.css`
- `docs/src/components/button.md`
Current button work includes:
- Shared button CSS moved toward structural rules.
- Visual rules moved into style files.
- `xs` button and icon size classes added.
- Icon-aware padding mapped with Basecoat selectors using `:has(> svg:first-child)` and `:has(> svg:last-child)`.
- All eight style files have Button sections.
- Docs include `btn-xs-outline` and `btn-xs-icon-outline` examples.
Button should remain `in-progress` until browser-audited across light/dark and all eight styles. Button-group adjacency is separate and should be handled during `button-group`.
## Current Component Status
- `button`: in progress / pending visual audit
- Everything else: pending
No component besides Button should be considered migrated.
## Issues Encountered
- The original migration plan assumed only five styles. Upstream now has eight.
- The first button attempt mixed old Basecoat visual rules with new style-pack rules, causing broken rendering.
- Some docs style entrypoints need `src/css/base/base.css` imported first so Tailwind can resolve semantic utilities like `focus-visible:border-ring`.
- Style switching should remove the override stylesheet `href` for Vega instead of setting `href=""`.
- Sidebar dropdown width was a tangent. The user explicitly said not to modify generic CSS for that; handle width with a Tailwind class only when that task is active.
## Things Learned
- Shadcn/ui icon-aware button padding is CSS-owned, not React-owned.
- Upstream uses data hooks like `has-data-[icon=inline-start]:pl-*`.
- Basecoat should map that to its own markup, currently `:has(> svg:first-child)` and `:has(> svg:last-child)`.
- Blind copy is not viable because upstream uses `cn-*` class composition while Basecoat uses explicit classes like `btn-xs-icon-outline`.
## Build And Validation Commands
```sh
npm run build
npm run docs:build
npm run docs:dev
```
Use `npm run docs:dev` for manual browser review.
## Remaining Work
1. Run build validation after the latest Luma/Sera/Rhea wiring.
2. Browser-check `/components/button` for all eight styles in light and dark mode.
3. Update Button tracker status only after visual audit.
4. Migrate `button-group` next because it interacts with button radius and adjacency.
5. Continue component-by-component using `migration-tracker.md`.
## Current Risks
- Button may still have visual deltas from upstream until audited.
- Docs style override assets may duplicate base CSS because they import base utilities for Tailwind compilation.
- The package does not currently generate separate style-specific CDN bundles beyond split style exports.
- The worktree includes unrelated sidebar template changes; do not revert or fold them into style migration unless explicitly requested.
-46
View File
@@ -1,46 +0,0 @@
# Basecoat Style Migration Tracker
Track migration of Basecoat components against the latest shadcn/ui v4 component source and all eight style packs.
Upstream source root: `../_sandbox/shadcn-ui`
Upstream style files: `apps/v4/registry/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
Legend:
- `pending`: not started
- `in-progress`: actively being migrated
- `done`: style-pack coverage implemented for current scope
- `deferred`: intentionally postponed
| Component | Status | Basecoat CSS | Upstream Base | Upstream Styles | Notes |
| --- | --- | --- | --- | --- | --- |
| alert | done | `src/css/components/alert.css` | `apps/v4/registry/bases/base/ui/alert.tsx` | all 8 `style-*.css` | Shared CSS now keeps alert structure only. All eight style files map upstream alert, title, description, action, and destructive/default variants onto Basecoat selectors. Docs include action, custom colors, and RTL. |
| badge | done | `src/css/components/badge.css` | `apps/v4/registry/bases/base/ui/badge.tsx` | all 8 `style-*.css` | Shared CSS now keeps badge structure only. All eight style files map upstream default, secondary, destructive, outline, ghost, and link variants. Docs include custom colors and RTL directional icon guidance. |
| button | done | `src/css/components/button.css` | `apps/v4/registry/bases/base/ui/button.tsx` | all 8 `style-*.css` | Standalone button rules are mapped across all eight styles, including xs sizing and icon-aware padding. Icon-aware padding now uses logical `ps`/`pe` utilities for RTL. Drift fixed: Maia base radius now uses upstream `rounded-4xl`. Docs include RTL guidance; directional icons must opt into `rtl:rotate-180`. |
| button-group | done | `src/css/components/button-group.css` | `apps/v4/registry/bases/base/ui/button-group.tsx` | all 8 `style-*.css` | Shared orientation/focus/adjacency structure remains in component CSS. Horizontal adjacency uses logical start/end border and radius rules for RTL. Style files cover grouped edge radius, nested group gap, text segment styling, separators, and Luma/Sera/Rhea outline input/select border coupling mapped to Basecoat selectors. Docs aligned with upstream sections where applicable and include RTL guidance. |
| card | done | `src/css/components/card.css` | `apps/v4/registry/bases/base/ui/card.tsx` | all 8 `style-*.css` | Shared CSS now keeps semantic card structure. All eight style files map upstream card root, header, title, description, content, footer, image, and `data-size="sm"` styling onto Basecoat selectors. Intentional divergence: card overflow remains visible because Basecoat overlays are inline rather than portalled like shadcn/Radix. Docs include size and RTL. |
| checkbox | done | `src/css/components/checkbox.css` | `apps/v4/registry/bases/base/ui/checkbox.tsx` | all 8 `style-*.css` | Shared CSS now keeps native checkbox structure and masked checkmark only. All eight style files map upstream checkbox root and indicator visuals onto Basecoat native checkbox selectors using `:checked` instead of shadcn `data-checked`. Docs aligned with upstream sections: checked state, invalid, basic, description, disabled, group, table, and RTL. |
| collapsible | deferred | `src/css/components/collapsible.css` | `apps/v4/registry/bases/base/ui/collapsible.tsx` | n/a | Basecoat already ships native `details`/`summary` enhancement CSS. Do not port shadcn/ui Collapsible as a JS component unless a real controlled-state need appears. TODO: add a `Disclosure` docs page for the native pattern with default, open, icon, accordion/group, and RTL examples. |
| combobox | done | `src/css/components/combobox.css` | `apps/v4/registry/bases/base/ui/combobox.tsx` | all 8 `style-*.css` | Added dedicated input-first Combobox CSS, JS, Nunjucks macro, and Jinja macro. All eight style files map upstream combobox content, list, empty state, labels, items, active state, separators, chips, chip remove, and trigger/input visuals onto Basecoat selectors. Intentional divergence: Basecoat uses raw semantic HTML and vanilla JS instead of Base UI Combobox primitives; single selection stores text in the visible input while options can render custom HTML via `data-label`; multiple selection uses chips plus a real input and stores a JSON array in the hidden input. Docs include basic, multiple, groups, custom items, invalid, disabled, auto-highlight, top side, and RTL. |
| command | done | `src/css/components/command.css` | `apps/v4/registry/bases/base/ui/command.tsx` | all 8 `style-*.css` | Shared CSS now keeps command/dialog structure, filtering visibility, empty state, shortcut/indicator slots, and active item behavior only. All eight style files map upstream command root, dialog, input wrapper, input, list, empty state, group, heading, separator, item, active state, and shortcut visuals onto Basecoat selectors. Intentional divergence: Basecoat implements command behavior with vanilla JS and native `<dialog>` rather than `cmdk` and portalled shadcn/ui Dialog. Docs aligned with upstream sections: about, composition, basic, shortcuts, groups, scrollable, RTL, and API guidance. |
| dialog | done | `src/css/components/dialog.css` | `apps/v4/registry/bases/base/ui/dialog.tsx` | all 8 `style-*.css` | Shared CSS now keeps native dialog mechanics, backdrop/open transitions, centered content layout, structural header/body/footer, and close-button structure only. All eight style files map upstream overlay, content, close position, header, footer, title, and description visuals onto Basecoat `.dialog` selectors. Intentional divergence: Basecoat uses the native `<dialog>` element and `showModal()` instead of shadcn/ui's portalled Base UI Dialog. Docs aligned with upstream sections: composition, custom close button, no close button, sticky footer, scrollable content, RTL, and API guidance. |
| dropdown-menu | done | `src/css/components/dropdown-menu.css` | `apps/v4/registry/bases/base/ui/dropdown-menu.tsx` | all 8 `style-*.css` | Shared CSS now keeps structure, roles, disabled states, shortcut/indicator slots, and fallback hover only. All eight style files map upstream content, item, checkbox/radio item, indicator, label, separator, shortcut, destructive, and inset visuals onto Basecoat role/data selectors. Intentional divergence: Basecoat dropdown content remains inline-positioned and does not implement upstream submenus/avatar/complex nested examples yet. Docs aligned with upstream sections for basic, shortcuts, icons, checkboxes, radio, destructive, RTL, and API guidance. |
| empty | done | `src/css/components/empty.css` | `apps/v4/registry/bases/base/ui/empty.tsx` | all 8 `style-*.css` | Added lightweight `.empty` root API using semantic `header`, `figure`, `section`, and `footer` children instead of shadcn slot classes. All eight style files map upstream empty root, header, media/icon, title, description, and content visuals onto Basecoat selectors. Docs now treat Empty as a real Basecoat component and include outline, avatar, avatar group, input group, and RTL examples. |
| field | done | `src/css/components/field.css` | `apps/v4/registry/bases/base/ui/field.tsx` | all 8 `style-*.css` | Shared CSS now covers field, fieldset, semantic field groups, semantic descriptions/errors, and field-separator structure. All eight style files map upstream field visuals onto existing Basecoat selectors, including `cn-field-label` checked/card behavior via `.field > label` and `label:has(> .field)`. Docs include semantic field groups, separator, choice card, responsive layout, and RTL. |
| input | done | `src/css/components/input.css` | `apps/v4/registry/bases/base/ui/input.tsx` | all 8 `style-*.css` | Shared CSS now keeps structural input behavior only. All eight style files map upstream input visuals onto Basecoat `.input` and `.field` selectors. Docs aligned with upstream sections where applicable: basic, field, field group, disabled, invalid, file, inline, grid, required, badge, input group, button group, and form. RTL is supported through native direction handling and logical utility usage in examples. |
| input-group | done | `src/css/components/input-group.css` | `apps/v4/styles/base-*/ui/input-group.tsx` | all 8 `style-*.css` | Added lightweight `.input-group` root API. Children remain semantic native controls and elements; optional `data-align="inline-start|inline-end|block-start|block-end"` maps upstream addon placement without shadcn slot classes. `data-control` is the escape hatch for custom non-native controls. |
| item | done | `src/css/components/item.css` | `apps/v4/registry/bases/base/ui/item.tsx` | all 8 `style-*.css` | Added lightweight `.item` and `.item-group` APIs using semantic `figure`, `section`, `aside`, `header`, and `footer` children instead of shadcn slot classes. All eight style files map upstream item variants, sizes, media, content, title, description, actions, header/footer, group, and separator visuals onto Basecoat selectors. Docs now use the component API and include variants, sizes, icon, avatar, image, group, header, link, and RTL examples. |
| kbd | done | `src/css/components/kbd.css` | `apps/v4/registry/bases/base/ui/kbd.tsx` | all 8 `style-*.css` | Kept `kbd` as the public component and dropped `kbd-group`; use plain inline wrappers for grouped keys. Docs include button, input-group, and RTL examples. |
| label | done | `src/css/components/label.css` | `apps/v4/registry/bases/base/ui/label.tsx` | all 8 `style-*.css` | Shared CSS now keeps label structure and disabled behavior. All eight style files map upstream label visuals. Sera control-label exceptions are mapped with Basecoat native input selectors instead of shadcn peer data-slot selectors. Docs include RTL. |
| native-select | done | `src/css/components/native-select.css` | `apps/v4/registry/bases/base/ui/native-select.tsx` | all 8 `style-*.css` | Shared CSS now keeps native select structure only. All eight style files map upstream native select visuals onto Basecoat `select.select` and `.field select`, using a CSS background chevron instead of upstream's wrapper icon element. Intentional divergence: direct selects stay `w-fit` by default because Basecoat has no `w-fit` wrapper; width utilities remain supported. Docs split Native Select from custom Select and include groups, disabled, invalid, size, RTL, and API guidance. |
| popover | done | `src/css/components/popover.css` | `apps/v4/registry/bases/base/ui/popover.tsx` | all 8 `style-*.css` | Shared CSS now keeps positioning, visibility, side, and align behavior only. All eight style files map upstream popover content/header/title/description visuals onto Basecoat `[data-popover]` and semantic header selectors. Intentional divergence: Basecoat popover remains inline-positioned relative to `.popover` rather than portalled through Base UI; animation utilities from upstream are omitted because this Tailwind setup does not include shadcn animation utilities. Docs aligned with upstream sections: composition, basic, align, form, RTL, and API guidance. |
| radio | done | `src/css/components/radio.css` | `apps/v4/registry/bases/base/ui/radio-group.tsx` | all 8 `style-*.css` | Shared CSS now keeps native radio structure and checked dot only. All eight style files map upstream radio group/item/indicator visuals onto Basecoat native radio selectors using `:checked` instead of shadcn `data-checked`. Docs aligned with upstream sections: checked state, invalid, basic, description, choice card, fieldset, disabled, invalid, and RTL. |
| range | done | `src/css/components/range.css` + `src/js/range.js` | `apps/v4/registry/bases/base/ui/slider.tsx` | all 8 `style-*.css` | Shared CSS keeps native range structure and gradient fill. Added `range.js` to sync `--slider-value`. All eight style files map upstream slider track/thumb visuals onto native range pseudo-elements. Intentional divergence: Basecoat uses native single-thumb range inputs, so upstream multi-thumb and vertical slider examples are not supported. Docs updated with default, controlled label, disabled, RTL, and divergence note. |
| select | done | `src/css/components/select.css` | `apps/v4/registry/bases/base/ui/select.tsx` | all 8 `style-*.css` | Shared CSS now keeps custom select structure, listbox behavior selectors, selected checkmark background, and empty state only. All eight style files map upstream trigger, value, content, label, group, item, active state, and separator visuals onto Basecoat selectors. Intentional divergences: Basecoat keeps inline popover positioning below the trigger rather than shadcn/ui's selected-item-over-trigger alignment and retains multiselect as Basecoat API surface. Combobox-specific search-header support has been removed from Select and moved to the dedicated Combobox component. Docs aligned with upstream sections where applicable: align, groups, scrollable, disabled, invalid, RTL, plus Basecoat multiselect. |
| sidebar | done | `src/css/components/sidebar.css` | `apps/v4/registry/bases/base/ui/sidebar.tsx` | `style-*.css` | Mapped upstream sidebar visuals onto Basecoat's simpler semantic sidebar. Intentional differences: no React provider, rail, inset/floating variants, icon-only collapse, menu actions, badges, or sidebar skeleton API. |
| skeleton | done | `src/css/components/skeleton.css` | `apps/v4/registry/bases/base/ui/skeleton.tsx` | all 8 `style-*.css` | Added dedicated `skeleton` class. All eight style files map upstream skeleton visuals. Docs now use `skeleton` instead of raw utility-only examples and include avatar, card, text, form, table, and RTL examples. |
| switch | done | `src/css/components/switch.css` | `apps/v4/registry/bases/base/ui/switch.tsx` | all 8 `style-*.css` | Shared CSS now keeps native checkbox-as-switch structure and pseudo-thumb only. All eight style files map upstream switch track/thumb visuals onto Basecoat native switch selectors using `:checked`, `data-size`, and explicit `:dir(rtl)` thumb transforms. Docs aligned with upstream sections: checked state, invalid, basic, description, choice card, disabled, invalid, size, and RTL. |
| table | done | `src/css/components/table.css` | `apps/v4/registry/bases/base/ui/table.tsx` | all 8 `style-*.css` | Added `table-container` and mapped upstream table root, header, body, footer, row, cell, head, and caption styles across all eight style files using logical alignment. Docs include footer, actions, and RTL. |
| tabs | done | `src/css/components/tabs.css` | `apps/v4/registry/bases/base/ui/tabs.tsx` | all 8 `style-*.css` | Shared CSS now keeps tabs layout, role structure, and panel structure only. All eight style files map upstream default and line variants, horizontal/vertical orientation, active state, icon sizing, and content text styles onto Basecoat role selectors. JS now skips disabled tabs and supports vertical ArrowUp/ArrowDown navigation. Docs aligned with upstream sections: composition, line, vertical, disabled, icons, RTL, and API guidance. |
| textarea | done | `src/css/components/textarea.css` | `apps/v4/registry/bases/base/ui/textarea.tsx` | all 8 `style-*.css` | Shared CSS now keeps structural textarea behavior only. All eight style files map upstream textarea visuals onto Basecoat `.textarea` and `.field` selectors. Docs aligned with upstream sections where applicable: field, disabled, invalid, button, and form. RTL is supported through native direction handling. |
| toast | done | `src/css/components/toast.css` | `apps/v4/registry/bases/base/ui/sonner.tsx` | all 8 `style-*.css` | Shared CSS keeps toaster positioning, toast lifecycle layout, icons/content/footer structure, and hide animation. All eight style files map upstream Sonner toast radius onto Basecoat `.toast-content`. Intentional divergence: Basecoat keeps its vanilla JS toast API and does not depend on Sonner. |
| tooltip | done | `src/css/components/tooltip.css` | `apps/v4/registry/bases/base/ui/tooltip.tsx` | all 8 `style-*.css` | Shared CSS keeps CSS-only tooltip trigger, positioning, visibility, side, align, and logical inline side behavior. All eight style files map upstream tooltip content radius/spacing/typography and optional arrow radius onto Basecoat `data-tooltip` selectors. Intentional divergence: Basecoat tooltips are text-only CSS tooltips and are not portalled composed content like upstream. Docs updated with sides, disabled trigger wrapper, link, icon button, RTL, and divergence note. |
+4 -4
View File
@@ -20,7 +20,7 @@
"lucide-static": "^1.17.0",
"nunjucks": "^3.2.4",
"prettier": "^3.5.3",
"reallysimpledocs": "^1.0.0",
"reallysimpledocs": "^1.0.1",
"tailwindcss": "^4.1.17",
"terser": "^5.42.0",
"wrangler": "^4.50.0"
@@ -7823,9 +7823,9 @@
"license": "MIT"
},
"node_modules/reallysimpledocs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/reallysimpledocs/-/reallysimpledocs-1.0.0.tgz",
"integrity": "sha512-P4qdwlWKcZv+T4FLcjGwuNG+m4EF8K97DCBA7ZtvODEVJMe4t9d9C3cxXbxgCP9fDRflgwEIQi9ruM4ZJWFI8Q==",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/reallysimpledocs/-/reallysimpledocs-1.0.1.tgz",
"integrity": "sha512-a0ekB68JP/khU8MXnwEql/jyO+NUi25EyfDgtlIQCpRFfuUgsY9b0U1eewBpsmUfxznqvNG4oBkUcRBfydcM2g==",
"dev": true,
"dependencies": {
"@astrojs/markdown-remark": "^7.2.0",
+1 -1
View File
@@ -49,7 +49,7 @@
"lucide-static": "^1.17.0",
"nunjucks": "^3.2.4",
"prettier": "^3.5.3",
"reallysimpledocs": "^1.0.0",
"reallysimpledocs": "^1.0.1",
"tailwindcss": "^4.1.17",
"terser": "^5.42.0",
"wrangler": "^4.50.0"
-133
View File
@@ -1,133 +0,0 @@
# Basecoat Multi-Style + Theme Refactor Plan
## Goals
- Support the current shadcn/ui visual packs: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, `rhea`.
- Keep current CDN and Tailwind/NPM usage working.
- Keep Basecoat's own class API (`btn`, `dialog`, `popover`, etc.).
- Split CSS into base tokens/utilities, component structure, style-pack visuals, and aggregate outputs.
- Make custom token themes, including TweakCN-style themes, predictable by loading them after Basecoat CSS.
## Current Upstream Reference
- Local repo: `../_sandbox/shadcn-ui`
- Style registry: `../_sandbox/shadcn-ui/apps/v4/registry/styles.tsx`
- Style files: `../_sandbox/shadcn-ui/apps/v4/registry/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
- Base components: `../_sandbox/shadcn-ui/apps/v4/registry/bases/base/ui/<component>.tsx`
## Target CSS Architecture
1. `src/css/base/base.css`
- base layer, default token fallbacks, and semantic utilities needed by CDN users
2. `src/css/components/*.css`
- Basecoat component selectors and shared structural behavior
3. `src/css/styles/*.css`
- one file per style pack: `vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, `rhea`
- component visuals: size, spacing, radius, typography, shadows, focus rings, variant colors when style-owned
4. Aggregates
- `src/css/basecoat.css`: backward-compatible Basecoat default aggregate, currently Vega
- `src/css/basecoat-<style>.css`: standalone Tailwind source bundle per style
- `src/css/basecoat-<style>.cdn.css`: standalone CDN source bundle per style
- `src/css/basecoat.all.css`: explicit all-in-one Tailwind source
- `src/css/basecoat.cdn.css`: CDN build entry
No `.style-*` wrapper is part of the Basecoat public contract for style selection. Users choose a style by importing a standalone style bundle or using a style-specific generated CDN asset. Docs switch by swapping the single active full stylesheet URL.
Do not load Vega/default first and then layer another style pack on top. Split files under `src/css/styles/*.css` are source organization and advanced composition only. They should map upstream style intent directly and avoid defensive resets whose only purpose is undoing another style pack.
## Per-Component File Checklist
For every component, check these files before editing:
- Basecoat component CSS: `src/css/components/<component>.css`
- Basecoat templates/macros if relevant: `src/nunjucks/*.njk`, `src/jinja/*.html.jinja`
- Basecoat docs examples: `docs/src/components/<component>.md`
- Upstream base component: `../_sandbox/shadcn-ui/apps/v4/registry/bases/base/ui/<component>.tsx`
- Upstream docs page: `../_sandbox/shadcn-ui/apps/v4/content/docs/components/{base,radix}/<component>.mdx`
- Upstream style packs: `../_sandbox/shadcn-ui/apps/v4/registry/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
- Basecoat style packs: `src/css/styles/{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
## Component Migration Workflow
1. Review current Basecoat CSS, markup, templates, and docs for the component.
2. Review the upstream base component and all eight upstream style files.
3. Decide what is shared structure versus style-pack-owned visual rules.
4. Remove outdated visual rules from shared component CSS when they are now style-owned.
5. Map upstream style intent onto Basecoat selectors. Do not port `cn-*` selectors.
6. Audit RTL support using upstream `*-rtl` examples and generated `ui-rtl` code when present.
7. Prefer logical utilities/properties (`ps`, `pe`, `rounded-s`, `rounded-e`, `border-s`, `start`, `end`) over duplicated `:dir(rtl)` branches.
8. Audit each style as a standalone full bundle, not as an override layered on another style.
9. Check state selectors during that audit: `focus-visible`, `aria-invalid`, `hover`, disabled, open, selected, checked, and pressed states.
10. Update the component section in all eight Basecoat style files.
11. Document non-trivial deltas as `intentional`, `drift fixed`, or `deferred`.
12. Align the component docs with the current upstream docs page:
- equivalent examples
- matching labels/anchors where reasonable
- Basecoat-specific differences and extras
- class/API reference
- explicit notes for unsupported/deferred upstream features
- RTL section when supported, or explicit RTL deferral
13. Update `migration-tracker.md`.
14. Run `npm run build`.
15. Run `npm run docs:build` when docs or docs style assets change.
16. Manually verify the docs page in light/dark, RTL, and all eight styles.
Do not mark a component done because CSS compiles. It needs a visual/state check.
## Packaging Contract
- Keep `@import "basecoat-css";` as the Basecoat backward-compatible default import. It currently resolves to Vega; this is not the upstream shadcn/ui generated default.
- Keep existing default CDN and JS bundle paths.
- Export standalone style bundles from `packages/css` as `basecoat-css/<style>` and `basecoat-css/<style>.css`.
- Export split style files from `packages/css` as `basecoat-css/styles/<style>` for advanced composition.
- Generate style-specific CDN assets for every style.
- Custom themes should load after Basecoat styles so their `:root` and `.dark` tokens override defaults.
## Component Migration Order
1. `button`
2. `button-group`
3. `input`
4. `textarea`
5. `native-select`
6. `select`
7. `checkbox`
8. `radio`
9. `switch`
10. `range`
11. `label`
12. `field`
13. `card`
14. `alert`
15. `badge`
16. `table`
17. `tabs`
18. `popover`
19. `dropdown-menu`
20. `dialog`
21. `command`
22. `sidebar`
23. `toast`
24. `tooltip`
25. `collapsible` (deferred: native `details`/`summary`; add `Disclosure` docs page)
26. `kbd`
## Current Status
- CSS split exists.
- Docs style switcher exists.
- Button and Button Group are migrated for current scope and tracked in `migration-tracker.md`.
- No other component should be considered migrated.
## TODO
- Add a `Disclosure` docs page for Basecoat's native `details`/`summary` pattern.
- Include examples for default, open by default, icon/chevron, accordion/group behavior, and RTL.
- Keep shadcn/ui `Collapsible` deferred unless Basecoat needs controlled JS state or animation hooks beyond native disclosure.
## Risks
- Selector drift between Basecoat markup and upstream shadcn/ui assumptions.
- Incorrectly leaving visual rules in shared component CSS.
- Bundle growth from style-specific assets.
- Docs style assets need base semantic utilities available during Tailwind compilation.
-277
View File
@@ -1,277 +0,0 @@
# Basecoat docs migration to latest ReallySimpleDocs
## Purpose
Migrate the Basecoat docs site to the latest local ReallySimpleDocs integration in `../reallysimpledocs`.
This plan is for the next agent. It is based on the current Basecoat repo at `/Users/hunvreus/Workspace/basecoat` and the current RSD repo at `/Users/hunvreus/Workspace/reallysimpledocs`.
## Current state
- Basecoat depends on RSD through `package.json`: `reallysimpledocs: "file:../reallysimpledocs"`.
- Basecoat docs source is already in `docs/src` and is now mostly `.mdx`.
- RSD now supports Markdown and MDX pages from `docsDir`, with default MDX components available without imports.
- Basecoat config already points RSD at source docs:
- `docsDir: "./docs/src"`
- `routeBase: "/"`
- `style: "vega"`
- `components.Head: "./docs/src/site/StyleHead.astro"`
- `components.ContentHeader: "./docs/src/site/ContentHeader.astro"`
- Latest RSD no longer has a `js` option. It always inserts managed JavaScript for theme initialization, Basecoat JS, copy-code behavior, copy-page behavior, search, and TOC state.
- The old generated-docs flow is no longer the main path. `docs/generated/**` is ignored and should not be hand-edited.
## Current blocker
`npm run docs:build` currently fails after `npm run build` succeeds.
Observed failure:
```text
[@tailwindcss/vite:generate:build] Can't resolve
/Users/hunvreus/Workspace/basecoat/node_modules/reallysimpledocs/src/css/components.css
in /Users/hunvreus/Workspace/basecoat/.astro/reallysimpledocs/styles.css
```
Cause:
- `astro.config.mjs` has a custom `basecoatDocsStyles()` integration that writes `.astro/reallysimpledocs/styles.css`.
- That custom stylesheet imports private RSD internals that no longer exist in latest RSD:
- `node_modules/reallysimpledocs/src/css/components.css`
- `node_modules/reallysimpledocs/src/css/sources.css`
- Basecoat style-switcher assets also import removed private RSD style files:
- `docs/src/assets/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
- each imports `node_modules/reallysimpledocs/src/css/styles/<style>.css`
Latest RSD no longer owns Basecoat style files. With managed CSS enabled, it imports public `basecoat-css` entrypoints and its own small CSS files:
- `basecoat-css/base`
- `basecoat-css/styles/<style>`
- `reallysimpledocs/css`
- `reallysimpledocs/css/styles/<style>`
Because Basecoat needs live style switching, Basecoat docs should set `css: false` and own the full docs stylesheet pipeline. Keep RSD-managed JavaScript on; there is no `js: false` option anymore.
## Migration target
Basecoat should stop depending on private RSD source CSS paths except, if strictly necessary, RSD's own stable small CSS files.
The docs site should use:
- Basecoat's own generated style bundles for Basecoat component visuals.
- `css: false` in the RSD integration, so Basecoat controls docs CSS and style switching.
- RSD-managed JavaScript, always on.
- RSD's integration for routing, layout, MDX, search, Markdown exports, `llms.txt`, and `llms-full.txt`.
- RSD component overrides for site-specific chrome.
- No `site.repository`-style UI metadata. Header actions belong in `ContentHeader`.
## Work plan
### 1. Remove the custom RSD stylesheet writer
Edit `astro.config.mjs`.
Remove:
- `fs`, `path`, and `fileURLToPath` imports if they become unused.
- `rsdCssPath()`.
- `basecoatDocsStyles()`.
- `basecoatDocsStyles()` from `integrations`.
Do not write `.astro/reallysimpledocs/styles.css` manually. Latest RSD already generates that virtual stylesheet.
Keep the RSD integration options:
```js
reallySimpleDocs({
docsDir: "./docs/src",
routeBase: "/",
css: false,
components: {
Head: "./docs/src/site/StyleHead.astro",
ContentHeader: "./docs/src/site/ContentHeader.astro",
},
site: { ... },
})
```
### 2. Move Basecoat docs CSS to owned style assets
Do not let RSD generate the docs stylesheet for Basecoat. Set `css: false`, then make `docs/src/assets/styles/style-*.css` the full docs stylesheets that `StyleHead.astro` swaps.
Do not import removed RSD CSS files from `docs/src/assets/styles/style-*.css`.
Recommended target for each style asset:
```css
@import "tailwindcss" source(none);
@reference "tailwindcss";
@reference "../../../../src/css/base/base.css";
@import "../../../../src/css/basecoat-vega.css";
@import "reallysimpledocs/css";
@import "reallysimpledocs/css/styles/vega";
```
Use the matching `basecoat-<style>.css` file for each style.
Use the matching `reallysimpledocs/css/styles/<style>` file for RSD's style-specific preview and code-surface rules.
Remove this line from every style asset:
```css
@import "../../../../node_modules/reallysimpledocs/src/css/styles/<style>.css";
```
`reallysimpledocs/css` is the public shared RSD CSS export. `reallysimpledocs/css/styles/<style>` provides the matching RSD style-specific CSS without importing Basecoat again.
Do not reintroduce removed `components.css`, `sources.css`, or `styles/*`.
### 3. Keep the style switcher, but make it compatible with latest RSD
Files:
- `docs/src/site/StyleHead.astro`
- `docs/src/site/ContentHeader.astro`
- `src/pages/index.astro`
Current behavior:
- Loads one docs style asset based on `localStorage.styleVariant`.
- Adds `data-style-variant` to `<html>`.
- Swaps `<link id="docs-style-variant">`.
Keep this behavior for Basecoat's style demo. With `css: false`, RSD's `style` option is unnecessary for Basecoat docs; Basecoat's style switcher owns the active stylesheet.
Audit duplication:
- Make sure the page does not load two competing full Basecoat style bundles in a way that makes non-Vega styles override Vega instead of standing alone.
- If duplicates are unavoidable during migration, document the temporary state in this file before handing off.
### 4. Fix navigation shape only if RSD rejects it
`docs/src/docs.json` currently uses item objects with `type: "item"`.
Latest RSD accepts page objects by `slug` and link objects by `url`; it does not require `type: "item"` for page/link entries based on current docs. Do not mass-rewrite navigation unless the build or runtime proves it is needed.
If there is a failure, normalize entries to:
```json
{ "slug": "installation", "label": "Installation", "icon": "download" }
```
and external links to:
```json
{ "label": "GitHub", "url": "https://github.com/hunvreus/basecoat", "icon": "github" }
```
Note: existing inline SVG icons in `docs.json` may or may not be supported by current RSD's icon pipeline. Verify before changing.
### 5. Verify MDX docs against current RSD components
Basecoat docs use RSD components heavily:
- `Preview`
- `Code`
- `CodeGroup`
- `Callout`
- `Steps`
- `Step`
Latest RSD makes common components available by default in MDX. Do not add imports unless a page fails.
Known special case:
- `docs/src/components/chart.mdx` imports `../site/chart-examples.js?url`.
Verify that MDX import still works after CSS fixes.
### 6. Validate generated outputs and routes
Run from `/Users/hunvreus/Workspace/basecoat`:
```bash
npm run build
npm run docs:build
```
Expected docs outputs include:
- `/index.html`
- component pages under `/components/.../index.html`
- `/search-index.json`
- per-page Markdown exports such as `/installation.md`
- `/llms.txt`
- `/llms-full.txt`
Then run:
```bash
npm run docs:dev
```
Browser-check:
- desktop and mobile widths
- search dialog
- Markdown/AI links
- style switcher for all eight styles
- dark mode
- component previews using JS behavior:
- dropdown menu
- select
- combobox
- command
- dialog
- tabs
- toast
- chart
### 7. Clean up stale docs once build passes
Update or remove outdated handoff text that says RSD does not support MDX. This file has already been updated for the latest RSD state.
Do not edit generated docs:
- `docs/generated/**`
- `dist/**`
- `packages/*/dist/**`
If build scripts regenerate committed source CSS entrypoints, use the scripts and review the generated source diffs before committing.
## Files likely touched
- `astro.config.mjs`
- `docs/src/assets/styles/style-vega.css`
- `docs/src/assets/styles/style-nova.css`
- `docs/src/assets/styles/style-maia.css`
- `docs/src/assets/styles/style-lyra.css`
- `docs/src/assets/styles/style-mira.css`
- `docs/src/assets/styles/style-luma.css`
- `docs/src/assets/styles/style-sera.css`
- `docs/src/assets/styles/style-rhea.css`
- Maybe `docs/src/site/StyleHead.astro`
- Maybe `docs/src/site/ContentHeader.astro`
- Maybe `docs/src/docs.json`
## Do not do
- Do not restore `basecoatDocsStyles()` by copying newer RSD internals.
- Do not import RSD files that are not public or intentionally stable.
- Do not add or use `js: false`; latest RSD always manages JavaScript.
- Do not reintroduce a generated `docs/generated` pipeline unless explicitly requested.
- Do not put GitHub/header actions into `site` metadata.
- Do not hand-edit build outputs.
## Open questions for the implementation agent
- Should inline SVG icons in `docs/src/docs.json` be kept, or should they move to Lucide icon names plus header/footer overrides?
## Recommended first patch
Start with the smallest build-fixing patch:
1. Delete `basecoatDocsStyles()` from `astro.config.mjs`.
2. Add `css: false` to the RSD integration options.
3. Remove all `node_modules/reallysimpledocs/src/css/styles/<style>.css` imports from `docs/src/assets/styles/style-*.css`.
4. Import Basecoat's own full style bundle in each style asset, plus RSD's own CSS through a public export if available.
5. Run `npm run docs:build`.
6. If layout CSS is missing, fix that through a public RSD CSS export instead of private source imports.