Skip to main content

style-system

Render DoomPi web components in a real browser and check their styling against the design tokens. Use when adding or changing a component's visual appearance, adding a story, adjusting styles/tokens.css, or when asked whether a surface looks right, not for non-visual React logic.

Quellinformationen

Repository
AgiFlow/doompi
Letzte Quellaktivität
23. September 2026 um 04:20
Erkannte Sprache von SKILL.md
Englisch
Sterne
42
Forks
4

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
style-system
description
Render DoomPi web components in a real browser and check their styling against the design tokens. Use when adding or changing a component's visual appearance, adding a story, adjusting styles/tokens.css, or when asked whether a surface looks right, not for non-visual React logic.
# Style System `@agimon-ai/style-system` compiles a component with the real theme, screenshots it in a headless browser, and hands the image back. Use it to see a component instead of inferring how it looks from its class list. ## When it earns its cost Reach for it when appearance is the question: a new component, a changed size or tone ladder, an edit to `styles/tokens.css`, or a review that asks whether a surface is correct. Skip it for logic, state, and data changes that do not move a pixel. ## The three tools | Tool | Use | | ------------------------ | ----------------------------------------------------------------------------------------------------------- | | `list-shared-components` | Every component carrying the `style-system` tag. Takes no `--app-path`. | | `get-css-classes` | The tokens the theme actually generates, read from `styles/tokens.css`. | | `get-ui-component` | Compiles one story and returns a screenshot. `--component-name X --app-path <pkg> --story-name Playground`. | Read `get-css-classes` before inventing a class. It reports only `--color-*`, `--text-*`, `--font-*`, `--space-*`, `--spacing` and `--shadow-*`, so `--radius-*` and `--tracking-*` are absent from its output even though they generate utilities. ## Configuration `style-system.config.yaml` at the workspace root holds `defaults` and three presets; each configured package extends one by name. - `packages/core/doompi-web-components` extends `doom-components` - `packages/clients/doompi-web` extends `doom-web-app` - every package with colocated browser components under `src/extensions/**/(frontend)/**/_components` extends `doom-plugin` Resolution is `defaults` then the preset then the project file, replacing whole values per field. There is no upward directory walk: a project config is read only at the exact `--app-path` on the command line. `themePath` is workspace-root relative; `cssFiles` entries are app-relative and must not contain `..`. Keep stories inside a configured package. A story elsewhere resolves to the root config, which is `root: true` and rejects being used as a project config. ### Adding a package A package that renders stories needs three things, all cheap: 1. `style-system.config.yaml` containing `extends: doom-plugin`. 2. `styles/preview.css` importing `tailwindcss` and then `@agimon-ai/doompi-web-components/styles.css`. The library's `styles.css` is a package export, which is how a plugin reaches the palette without a `..` that `cssFiles` forbids. Tailwind has to be imported by hand, because the renderer only injects it for a project that configures no `cssFiles` at all. 3. `react-dom` as a devDependency. Plugin packages carry `react` but usually not `react-dom`, and under pnpm's strict layout the renderer then fails to resolve `react-dom/client` at build time. ## Stories Storybook is not installed. A story is a plain object literal that the renderer parses statically, preferring `Story.render`, then `meta.render`, then `meta.component`. ```tsx import { Thing } from './Thing.tsx'; const meta = { title: 'Components/Thing', component: Thing, tags: ['style-system'], }; export default meta; export const Playground = { render: () => ( <div className="flex flex-col gap-6 bg-doom-bg p-6"> <span className="text-2xs uppercase tracking-widest text-doom-dim">size md</span> <Thing size="md" /> </div> ), }; ``` Rules that make a story renderable: - Never import from `storybook` or `@storybook/*`. Plain object literals only. - `const meta` must be a bare declaration with `export default meta` after it. Writing `export const meta` breaks the render: the renderer finds the default export by looking for the bare declaration and otherwise reports the component as not found in the stories index. `no-default-export` and `direct-export-only` are therefore switched off for `src/components/*.stories.tsx` through an `overrides` block in the library's `vibe-lint.config.yaml`. Theming rules still apply to stories. - `tags: ['style-system']` is what `list-shared-components` looks for. - Relative imports carry their `.tsx` or `.ts` extension. - It must paint with no interaction. Radix overlays need `open` or `defaultOpen`, `Tooltip` needs its provider, and portalled content needs a wrapper tall enough to screenshot. - Show every rung a `cva` ladder declares, so a collapsed step is visible. - A component taking `WebPluginSlotProps` or `ToolMessageRenderProps` gets them from `@agimon-ai/doompi-core/webTesting`, which already exports `slotPropsFixture` and `toolMessagePropsFixture`. A hand-rolled stub drifts silently when the contract changes; the fixture breaks at the type level. Stories live in `src/` and never ship: `files` in `package.json` publishes `dist` and `styles` only. `vitest.config.ts` excludes them from coverage. ## The token scales Type, radius and tracking are closed sets. `no-arbitrary-style-value` in `@agimon-ai/vibe-lint-plugin-doom-web` fails the build on anything outside them. | Scale | Rungs | | -------- | -------------------------------------------------------------------------------- | | Type | `text-2xs` 9px, `text-xs` 10px, `text-sm` 12px, `text-base` 13px, `text-lg` 15px | | Radius | `rounded-xs` 2px, `rounded-sm` 3px, `rounded-md` 5px, `rounded-lg` 10px | | Tracking | `tracking-wide` .08em, `tracking-wider` .14em, `tracking-widest` .18em | | Leading | stock Tailwind steps; the theme adds none | Bare `rounded` is 4px, `rounded-full`, `rounded-none` and `rounded-t`/`rounded-b` do not read `--radius-*` and are unaffected by the scale. Adding a type step means restating its line height too. Overriding `--text-sm` alone leaves Tailwind's default `--text-sm--line-height` in place, pairing a new size with a stale ratio. Colours are `--color-doom-*`. `text-doom-muted` is **not** one of them: the quiet foreground is `text-doom-dim`. A class naming a token that does not exist compiles to nothing and silently inherits, so confirm the name in `get-css-classes`. ## Verifying a change 1. `pnpm vibe-lint check --rules-only <paths>` before editing governed files. 2. Render the affected components and look at the screenshots. 3. `pnpm lint:vibe --preflight-only`. 4. `pnpm exec nx run-many -t lint typecheck build test -p <project>`. Run Nx at `--parallel=3` or lower. Higher parallelism makes lint and typecheck contend on shared build artifacts and report failures that vanish when rerun. To confirm a token really compiles, build the CSS directly. The Tailwind v4 CLI has no `--content` flag; point at sources with `@source "<absolute path>"` inside the input CSS. ## Known quirks - `get-css-classes` lists `--text-*--line-height` entries as though they were classes. Cosmetic; leave them. - The renderer writes scratch Vite builds into `.tmp/` inside the package and never cleans them. Already git-ignored. - The generated wrapper appends `@source` lines for `apps/` and `packages/frontend`, which this repository does not have. Tailwind ignores a missing source silently. - The renderer serves the built page from `file://`, so a Web Worker cannot start: the browser blocks it as an origin `null` script. This bit `PdfPreview`, whose pdfjs import spun up a worker at module scope and so crashed every story in every package that imports the library barrel. The import is now lazy, which fixes the crash. A story that genuinely needs a worker to paint, such as the PDF canvas itself, still cannot: expect the chrome and the error state instead. - A package renders against the library's built `dist`, not its sources. After changing a component, run `nx run @agimon-ai/doompi-web-components:build` before rendering a story from any other package.
Auf GitHub ansehen