/sub-packages/styleguide/CLAUDE.md
CLAUDE.md at /sub-packages/styleguide/CLAUDE.md
Path: sub-packages/styleguide/CLAUDE.md
Styleguide
Custom Preact-native component styleguide for Takazudo Modular. Replaces the old astrobook (which used @astrojs/react and broke after the Preact migration).
Architecture
Astro 6 + @astrojs/preact with compat mode. Each story variant renders in its own iframe via a preview route — providing full CSS isolation (like Storybook’s preview iframe pattern).
/ → Homepage (category listing)
/tokens/ → Design token preview
/[slug]/ → Story page (iframes per variant)
/preview/[slug]/[variant]/ → Single variant rendered in isolation (iframe target)
Why iframes
Components render inside iframes so they get the full design system CSS in isolation. The styleguide chrome (sidebar, controls) doesn’t leak into component rendering. Token tweaker panels inject CSS variable overrides into iframes via iframe.contentDocument.documentElement.style.setProperty().
Tailwind CSS scanning
Since components render via client:only="preact" (client-side only), Tailwind v4’s Vite plugin can’t see them in the server module graph. The @source directives in src/styles/global.css explicitly tell Tailwind to scan the root project’s component directories.
Story Format
Stories use a custom format (not Storybook CSF). Each *.stories.tsx file exports:
meta (required)
export const meta = {
title: 'Category/ComponentName',
};
title determines sidebar category (before /) and display name (after /).
Variants (required)
Each named export (except meta and controls) is a variant. Use arrow functions:
export const Default = () => <ActionButton>Click me</ActionButton>;
export const Disabled = () => <ActionButton disabled>Disabled</ActionButton>;
export const Loading = () => <ActionButton loading>Loading...</ActionButton>;
controls (optional)
Declares dynamic props that users can tweak in real-time via a controls panel below each variant preview. Changes are sent via postMessage to the iframe — no reload.
export const controls = {
label: { type: 'text', default: '入荷通知を受け取る' },
disabled: { type: 'boolean', default: false },
loading: { type: 'boolean', default: false },
size: { type: 'select', options: ['sm', 'md', 'lg'], default: 'md' },
count: { type: 'number', default: 1, min: 0, max: 10, step: 1 },
color: { type: 'color', default: '#ea580c' },
};
Control types: text, boolean, number, select, color
When controls are declared, the Default variant should accept props:
export const Default = (props: Record<string, unknown>) => (
<ActionButton
disabled={props.disabled as boolean}
loading={props.loading as boolean}
>
{props.label as string}
</ActionButton>
);
Other variants can remain static — they demonstrate specific states.
MSW support (optional)
For components that need API mocking (e.g., notify dialogs), add parameters.msw.handlers to meta:
export const meta = {
title: 'Notify/ReservationDialog',
parameters: { msw: { handlers: [mockReservationHandler] } },
};
Flat Props Pattern
Components should accept flat, simple props instead of complex nested objects. This makes stories easy to write and the styleguide previews straightforward.
// Component accepts flat props
export interface ArticleListItemProps {
title: string;
imageSlug: string;
date: string;
tags: string[];
href: string;
}
// Adapter function for page-level usage (exported from same file)
export function articleSummaryToListItemProps(article: ArticleSummary): ArticleListItemProps {
return { title: article.frontmatter.title, ... };
}
// Story uses flat props directly — simple
export const Default = () => (
<ArticleListItem title="My Article" imageSlug="product-front" date="2024-06-01" ... />
);
Token Tweaker Panels
Two floating panels for live token tweaking:
| Panel | Toggle | Target | What it tweaks |
|---|---|---|---|
| Component Tokens (green) | Top-right green circle | Iframes only | Palette colors (p0-p15) + semantic mapping |
| Styleguide UI (orange) | Top-right orange circle | Page root only | Color + spacing + typography tokens |
Commands
pnpm styleguide:dev # Dev server (port 44322)
pnpm styleguide:dev:net # Dev server with network access
pnpm styleguide:build # Production build
Key Files
| File | Purpose |
|---|---|
src/data/stories.ts | Auto-discovers stories via import.meta.glob, builds category tree |
src/data/control-types.ts | ControlDef and ControlsMap type definitions |
src/data/zmod-tokens.ts | Token definitions for tweak panels |
src/components/variant-preview.tsx | Iframe container with viewport switcher, controls panel, auto-height |
src/components/variant-renderer.tsx | Renders a single variant inside iframe, listens for postMessage |
src/components/controls-panel.tsx | Dynamic prop controls UI |
src/components/color-tweak-panel.tsx | Palette + semantic color tweaker (→ iframes) |
src/components/token-tweak-panel.tsx | Spacing + typography + color tweaker (→ page root) |
src/lib/iframe-registry.ts | Manages CSS variable overrides across all iframes |
src/mocks/ | Mock components (ResponsiveImage, next/link, server-only, etc.) |
src/pages/preview/[...path].astro | Dynamic preview route (iframe target) |