| # AGENTS.md |
| |
| Guidance for AI coding agents working in this repository. Tool-agnostic; `CLAUDE.md` points here. |
| |
| Bootstrap v6.0.0-alpha1 — CSS/JS framework. |
| Sass source in `scss/`, TypeScript source in `js/src/`, docs site in `site/` (Astro 5 + MDX). |
| |
| ## Quick commands |
| |
| - `npm start` — dev server (watch + Astro on port 9001) |
| - `npm run dist` — full CSS + JS build |
| - `npm run css` — compile, prefix, minify CSS |
| - `npm run js` — compile + minify JS |
| - `npm run css-lint` / `npm run js-lint` — lint |
| - `npm run docs-build` — build docs site |
| - `npm test` — full test suite (lint + dist + tests + docs) |
| |
| ## Writing style |
| |
| Use ASD-STE100 Simplified Technical English for all prose: replies to the user, docs, code comments, commit messages, and PR text. |
| |
| - Write short sentences. Use approximately 20 words or fewer. |
| - Give one instruction per sentence. |
| - Use the active voice. Name the actor. |
| - Use simple verbs. Do not use a complex verb when a simple one works. |
| - Use one term for one thing. Keep terms the same across the project. |
| - Keep paragraphs short. Cover one topic per paragraph. |
| |
| ## Reply length |
| |
| Be extremely brief. Report the result, not the journey. |
| |
| - Target 75 words or fewer. Hard cap 150 words, and only for a genuinely multi-part answer. |
| - Answer in the first sentence. Then stop. |
| - Give one supporting fact per claim, at most. Cut the rest. |
| - Do not narrate your process, tool calls, or verification steps. Report a check only when it failed or changed the outcome. |
| - Do not restate the work you just did. The user reads the diff, the commit, and the PR. |
| - State a finding once. Never repeat it in a summary or closing line. |
| - No headings. No tables. Use a list of 5 items or fewer only when the answer is a real list. |
| - Cut praise, apologies, hedging, and filler such as "great question" or "worth noting". |
| - Do not explain what you did not do, or list caveats the user did not ask about. |
| - Do not offer next steps unless the user asks or the work is blocked. |
| - Expand only when the user asks for detail, or asks you to teach. |
| |
| ## Teaching |
| |
| Act as a teacher for JavaScript, TypeScript, React, and all JavaScript-family topics. |
| |
| - When the work hits a new problem, concept, or language feature, stop and explain it. |
| - Keep each explanation short and plain. Define jargon on first use. |
| - Use a small code example when it makes the idea clear. |
| - Assume strong HTML/CSS knowledge. Do not assume deep JS internals knowledge. |
| |
| ## SCSS conventions |
| |
| - Variable naming: `$component-state-property-size` (e.g., `$nav-link-disabled-color`) |
| - Module system: `@use` / `@forward` only — never `@import` |
| - Token system: component tokens are SCSS maps of CSS custom properties, merged via `defaults()`, output via `@include tokens($map)` on the component root selector |
| - Disallowed: raw `border-radius` / `transition` properties (use mixins), `lighten()` / `darken()`, `border: none` / `outline: none` |
| - Order: `@use` → `@forward` → `$variables` → `--custom-properties` → declarations → rules |
| - Variables use `!default` (except locals) |
| - CSS layers: `colors, theme, config, root, reboot, layout, content, forms, components, custom, helpers, utilities` |
| - Logical properties: prefer `padding-inline-start` over `padding-left`, etc. |
| - Modern CSS: `color-mix()`, `light-dark()`, range media queries (`@media (width >= 1024px)`) |
| - Doc markers: `// scss-docs-start name` / `// scss-docs-end name` for docs extraction |
| |
| ## JavaScript/TypeScript conventions |
| |
| - Source is TypeScript (`js/src/**/*.ts`, entry `js/src/index.ts`); ESM-only, no semicolons, 2-space indent |
| - Imports use `.js` extensions (standard TS ESM style); Rolldown resolves them to `.ts` via `resolve.extensionAlias`, Vitest via the `tsResolve` plugin in `js/tests/vitest.config.mts` |
| - Dist builds use Rolldown (`build/rolldown.config.mjs`, `build/build-plugins.mjs`) with built-in TS transforms; `build/browser-targets.mjs` derives the browser floors from `.browserslistrc` at build time, so there is nothing to keep in sync. Rollup and Babel are gone from the repo — Vitest transforms the specs itself |
| - Strict tsconfig with `verbatimModuleSyntax` + `erasableSyntaxOnly`; `tsc` only type-checks and emits `.d.ts` (`npm run js-typecheck`, `npm run js-emit-types`) |
| - Components extend `BaseComponent` (which extends `Config`); per-component config `type XxxConfig` typed off `Default`, refined on the class via `protected declare _config: XxxConfig` |
| - Instance fields use `declare` (no runtime emit); constructor `element` param stays optional to keep `typeof Component` assignable to `typeof BaseComponent` |
| - Every `_`-prefixed instance member is `protected` (never `private`, so subclasses keep access); public API methods and statics stay public. This keeps the internals out of the published `.d.ts` surface |
| - Constants: `NAME`, `DATA_KEY`, `EVENT_KEY`, `VERSION` |
| - DOM utilities via `dom/event-handler.ts`, `dom/selector-engine.ts`, `dom/manipulator.ts` |
| - Floating UI for positioning (dropdown, tooltip, popover) |
| - Tests: Vitest browser mode (real Chromium via Playwright), config in `js/tests/vitest.config.mts`, specs in `js/tests/unit/*.spec.js` (plain JS, bundled against the TS sources). `js/tests/vitest-setup.js` maps the Jasmine API the specs are written against onto Vitest — note `spyOn` stubs by default, unlike `vi.spyOn`. Async specs return a promise; Vitest 4 dropped `done`. Coverage is Istanbul over all of `js/src`, thresholds 90/88/90/90 |
| - Type-level API tests in `js/tests/types/` — `api.ts` checks the source (`npm run js-typecheck`), `consumer.ts` checks the shipped `js/dist/*.d.ts` through the package `exports` map (`npm run js-typecheck-dist`, after the build). Keep the two in sync |
| |
| ## Docs conventions |
| |
| - Astro 5 + MDX in `site/src/content/docs/` |
| - Frontmatter schema: `title` (required), `description` (required), `toc`, `aliases`, `added`, `mdn`, `reference`, etc. |
| - Shortcodes: `Example`, `Callout`, `Code`, `Details` |
| - Internal links: `[[docsref:/path/]]` |
| - JS component "Dependencies" tables are auto-generated — add a `### Dependencies` heading with `<JsDependencies component="<js-src-basename>" />` (before `### Options`) on any doc for a `js/src/*.ts` component. The table is derived at build time by walking the component's import graph in `site/src/libs/js-dependencies.ts`; never hand-write the file list. When a new source file or third-party package enters the graph, add its human-readable label to `FILE_DESCRIPTIONS` / `PACKAGE_DESCRIPTIONS` in that lib (the build throws if a label is missing). |
| |
| ## Formatting |
| |
| - 2 spaces, UTF-8, LF line endings, trim trailing whitespace, final newline |
| - Preserve smart punctuation (curly apostrophes U+2019, curly quotes) — never replace with ASCII equivalents |
| - Use `StrReplace` for targeted edits; avoid full-file rewrites on MDX files to protect typography |
| |
| ## Workflow |
| |
| - Validate after changes: `npm run css-lint`, `npm run js-lint`, `npm run dist`, `npm run docs-build` |
| - Keep config files in sync: `config.yml`, `site/src/libs/config.ts` (Zod schema), `build/rolldown.config.mjs`, `build/generate-sri.mjs`, `package.json` |
| - For rebases/conflicts: favor base branch structure, layer feature changes on top |
| |
| ## Commits & PRs |
| |
| - Commit messages: direct, succinct prose explaining why the change was made. |
| - PR descriptions: direct bulleted lists, minimal fluff — one bullet per notable change. |
| - Reference related issues/PRs explicitly with `Fixes #{issue}`, `Closes #{issue}`, or `Supersedes #{pr}`. |
| - No "Test plan" section and no extra headings — just the bullets and the references. |
| |
| ## Do not edit |
| |
| Built output in `dist/`, `_site/`, `js/dist/` — these are generated. |