Files
basecoat/AGENTS.md
T

178 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Basecoat – Agent Guide
## What is Basecoat?
Basecoat is a vanilla JavaScript/HTML/CSS port of shadcn/ui components. It reuses shadcn/ui's design patterns and Tailwind CSS classes while maintaining semantic HTML, native browser elements, and full accessibility (ARIA attributes, proper hierarchies, keyboard navigation). The goal is to provide shadcn-quality components without React dependencies.
## Quickstart
- Install deps: `npm i`
- Dev docs server: `npm run docs:dev`
- Build CSS/JS: `npm run build`
- Build static docs: `npm run docs:build`
## What to edit (and what not)
- Edit sources only:
- `src/css/base/base.css` – Shared base layer, tokens, and semantic utility classes
- `src/css/components/*.css` – Component CSS classes (Tailwind + custom)
- `src/css/styles/style-*.css` – Style-pack overrides (`vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, `rhea`)
- `src/css/basecoat.css` – Aggregate CSS entrypoint
- `src/js/*.js` – Individual component JS files (kebab-case, ESM) + `basecoat.js` (component registry)
- `src/nunjucks/*.njk` and `src/jinja/*.html.jinja` – Component template macros
- `docs/src/components/*.njk` – Component documentation pages with examples
- `docs/src/_includes/` – Layout templates, partials, and navigation
- Do not edit build outputs:
- `packages/*/dist` – built CSS/JS bundles
- `_site/` – generated docs site
## Project layout
- Workspaces: root npm workspace with publishable packages in `packages/*`.
- Packages:
- `packages/css` – built CSS and JS bundles under `dist/`.
- `packages/cli` – CLI; distributed assets live under `dist/`.
- Docs site: `docs/src` (Eleventy); output goes to `_site/`.
## Style system
- Basecoat keeps its own component class API (`btn`, `dialog`, `popover`, etc.). Do not introduce shadcn `cn-*` classes into Basecoat source.
- Shadcn/ui style packs are used as reference material, but must be mapped onto Basecoat markup and selectors.
- Style-pack architecture is one file per style:
- `src/css/styles/style-vega.css`
- `src/css/styles/style-nova.css`
- `src/css/styles/style-maia.css`
- `src/css/styles/style-lyra.css`
- `src/css/styles/style-mira.css`
- `src/css/styles/style-luma.css`
- `src/css/styles/style-sera.css`
- `src/css/styles/style-rhea.css`
- Default aggregate and CDN behavior should resolve to Vega unless explicitly changed.
- Non-default styles should be selected by importing the relevant style file or using a style-specific bundled asset, not by introducing shadcn internal selector conventions.
- During migration, each component must be reviewed in two layers:
- shared/base component CSS
- style-pack CSS overrides
- Do not assume existing Basecoat component CSS is still the right baseline. Reassess shared rules vs style-owned rules component by component.
- When Basecoat differs from upstream shadcn/ui, classify the difference as either intentional or drift, and prefer explicit decisions over silent divergence.
## Component migration workflow
For each component migration, follow this sequence:
1. Review the current Basecoat component CSS and markup/templates first.
2. Review the latest upstream shadcn/ui base component source for the equivalent component.
3. Review the relevant sections in all eight upstream style packs (`vega`, `nova`, `maia`, `lyra`, `mira`, `luma`, `sera`, `rhea`).
4. Decide what belongs in shared Basecoat component CSS versus what belongs in style-pack CSS.
5. Keep Basecoat selectors and markup. Do not port shadcn `cn-*` selectors directly.
6. Remove outdated Basecoat visual rules from the shared component CSS if those rules are now style-owned.
7. Implement or update the component section in:
- `src/css/components/<component>.css`
- `src/css/styles/style-vega.css`
- `src/css/styles/style-nova.css`
- `src/css/styles/style-maia.css`
- `src/css/styles/style-lyra.css`
- `src/css/styles/style-mira.css`
- `src/css/styles/style-luma.css`
- `src/css/styles/style-sera.css`
- `src/css/styles/style-rhea.css`
8. Document any non-trivial difference from upstream as either:
- intentional
- drift fixed
- deferred
9. Update the migration tracker entry for the component.
10. Run `npm run build` after each component migration.
11. Manually verify the component in docs for:
- light and dark mode
- all supported variants and sizes
- interaction states (`hover`, `focus`, `disabled`, `aria-invalid`, open/selected states when relevant)
Per-component file checklist:
1. Basecoat component CSS: `src/css/components/<component>.css`
2. Basecoat templates/macros if relevant: `src/nunjucks/*.njk`, `src/jinja/*.html.jinja`
3. Basecoat docs page: `docs/src/components/<component>.njk`
4. Upstream base component: `../_sandbox/shadcn-ui/apps/v4/registry/bases/base/ui/<component>.tsx`
5. Upstream styles: `../_sandbox/shadcn-ui/apps/v4/registry/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
6. Basecoat styles: `src/css/styles/style-{vega,nova,maia,lyra,mira,luma,sera,rhea}.css`
## Conventions
- ESM everywhere (`import`/`export`).
- Prettier defaults (2 spaces; single quotes per file preference).
- Filenames for assets: kebab-case (e.g., `dropdown-menu.js`, `basecoat.cdn.css`).
- JS naming: `camelCase` for vars/functions; `PascalCase` for DOM classes and exported component names when applicable.
## Design Principles
- **Minimal code**: Prefer native HTML elements and browser behavior over JavaScript abstractions
- **Accessibility-first**: Semantic HTML, proper ARIA attributes, keyboard navigation
- **CSS patterns**:
- Use `border` for lines/separators (not `background` on `<hr>`)
- Use `:is()` and `:has()` for compact selectors
- Use `isolation: isolate` to contain z-index stacking contexts
- Use `data-*` attributes for styling states, `aria-*` for accessibility semantics
- **Component patterns**:
- Dialog variants use wrapper classes (e.g., `.command-dialog` wraps `.command`)
- JavaScript components register with `window.basecoat.register()`
- Emit custom events for user actions (e.g., `command:select`)
- Filter disabled options (`aria-disabled="true"`) from all interactions
- **When NOT to create a component**:
- If it's just composition of existing elements (users can do it with standard HTML/Tailwind)
- If behavior is fully native (e.g., fieldset, legend)
## Adding new components
Before creating a component, ask:
1. Does shadcn/ui have it? → Port it
2. Is it pure composition? → Document pattern, no component
3. Does it need JS behavior? → Create component
4. Is it just CSS? → Add to basecoat.css, document usage
Examples:
- Field/Fieldset: CSS-only patterns (no JS component)
- Empty/Item/Input Group: Pure composition (docs only)
- Command/Select: JS behavior required (full component)
## Common tasks
- Update a component's CSS/JS: Edit `src/css/basecoat.css` and/or `src/js/*.js`.
- Update a component's CSS/JS: Edit the relevant file in `src/css/components/*.css`, `src/css/styles/style-*.css`, and/or `src/js/*.js`.
- Update a component template: Edit `src/nunjucks/*.njk` and/or `src/jinja/*.html.jinja`.
- Add a new component: Create JS, CSS, templates, and docs page under `docs/src/components/*.njk`.
- Update navigation: Edit files in `docs/src/_includes/partials/`.
## Testing
No automated testing configured. User validates manually via the docs site (`npm run docs:dev`).
## Commits and PRs
- Commits: concise, imperative (≤72 chars), optional scope.
- Example: `select: prevent change event on init`.
- PRs: include description, linked issues (e.g., `Closes #123`), and before/after screenshots or code snippets for visual/behavioral changes.
- Keep PRs focused; update docs examples when components or APIs change.
## Environment and tooling
- Node 18+ recommended.
- Eleventy config: `.eleventy.js`.
- Tailwind via `@tailwindcss/cli` v4.
- Build uses Tailwind CLI and `terser`; both are provided via devDependencies.
## Git workflow
- `.gitattributes` configures merge strategies for generated files
- `docs/src/assets/styles.css` auto-resolves to incoming changes (regenerated by Tailwind)
- Always run `npm run build` before publishing packages
## Publishing packages
1. Bump version in root `package.json`
2. Run `npm run build` to generate dist files
3. Run `npm publish --workspaces` to publish both packages
## Package references
- `packages/css` usage and details: see `packages/css/README.md`.
- `packages/cli` usage and details: see `packages/cli/README.md`.