skills/mine/storybook-stories/SKILL.md
Create, update, or refactor Storybook stories following the project's standard patterns. Use when adding stories for new components, updating existing stories, or fixing Storybook-related issues. Don't use for component implementation itself, design-system token changes, end-to-end browser tests, or non-Storybook documentation.
npx skillsauth add pedronauck/skills storybook-storiesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill enforces consistent Storybook story creation patterns across the application. It ensures that all components have proper documentation, interactive examples, and follow the established project structure.
<critical_component_usage> MANDATORY: Always Use Base UI Components from @agh/ui
CRITICAL REQUIREMENTS:
@agh/ui package (packages/ui)@.cursor/rules/react.mdc and @.cursor/rules/shadcn.mdcbg-background, text-foreground, border-border) instead of explicit colors@agh/uibg-white, text-black) - always use design tokenstags: ["autodocs"] or enable Storybook autodocs on any story meta (packages/ui, web/src/components/ui, or web/src/systems/**). Use parameters.docs.description.component, JSDoc on stories, and the Docs addon manually if needed.Available Base Components:
All components from packages/ui/src/components are available via @agh/ui:
packages/ui/src/index.ts for complete list of exportsDesign System Rules:
@.cursor/rules/react.mdc@.cursor/rules/shadcn.mdcbg-background, text-foreground, border-border, etc.
</critical_component_usage>File Location & Naming
stories/ folder within the same category folder as the component.src/components/base/accordion.tsx -> src/components/base/stories/accordion.stories.tsx.packages/ui/.storybook for packages/ui/src/components/*.stories.tsxweb/.storybook for web/src/components/ui/**/*.stories.tsx and web/src/systems/**/components/stories/*.stories.tsxComponent Imports
@agh/uiimport { Button, Card, Dialog } from "@agh/ui";packages/ui/src/index.ts to see available components before creating new onesMeta Configuration
components/custom/ComponentName or components/ui/ComponentName.component in the meta object.parameters.layout to "centered" by default.parameters.docs.description.component to describe the component.decorators if the component requires a specific container width or context.const meta: Meta<typeof Component> = { ... }tags: ["autodocs"] to meta (any layer). Autodocs inflates generated docs noise and is forbidden in this repo.web system stories may rely on the shared QueryClient + router + MSW decorators from web/.storybook/preview.ts; prefer those global decorators over per-story provider duplication.Story Definition
type Story = StoryObj<typeof meta>;.Default story as the primary example.args property, even if empty: args: {}systems/<name>/<ComponentName>.Render vs Args
render functions for compound components (like Accordion, Dialog, Select) that require children composition.args for simple components (like Button, Badge) where props define the variation.render, include args: {} propertyDesign System Compliance
bg-background, text-foreground, border-borderbg-white, text-black, border-gray-200@.cursor/rules/shadcn.mdcimport type { Meta, StoryObj } from "@storybook/react";
import { Button, Card, CardHeader, CardTitle, CardContent } from "@agh/ui";
import { MyCustomComponent } from "./my-custom-component";
const meta: Meta<typeof MyCustomComponent> = {
title: "components/custom/MyCustomComponent",
component: MyCustomComponent,
parameters: {
layout: "centered",
docs: {
description: {
component: "A custom component that composes base UI components from @agh/ui.",
},
},
},
// Optional decorator using design tokens
decorators: [
Story => (
<div className="w-[400px] p-4 bg-background border border-border rounded-lg">
<Story />
</div>
),
],
};
export default meta;
type Story = StoryObj<typeof meta>;
/**
* Default usage showing the standard behavior
* Uses base Button and Card components from @agh/ui
*/
export const Default: Story = {
args: {},
render: () => (
<Card>
<CardHeader>
<CardTitle>My Custom Component</CardTitle>
</CardHeader>
<CardContent>
<MyCustomComponent>
<Button variant="default">Action</Button>
</MyCustomComponent>
</CardContent>
</Card>
),
};
/**
* Variation with specific props
* All styling uses design tokens (bg-background, text-foreground, etc.)
*/
export const WithVariant: Story = {
args: {},
render: () => (
<div className="bg-card border border-border rounded-lg p-4">
<MyCustomComponent variant="secondary">
<Button variant="outline">Secondary Action</Button>
</MyCustomComponent>
</div>
),
};
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "@agh/ui";
const meta: Meta<typeof Button> = {
title: "components/ui/Button",
component: Button,
parameters: {
layout: "centered",
docs: {
description: {
component: "A button component with multiple variants and sizes.",
},
},
},
};
export default meta;
type Story = StoryObj<typeof meta>;
/**
* Default button with standard styling
*/
export const Default: Story = {
args: {
children: "Button",
variant: "default",
size: "default",
},
};
/**
* All variants using design tokens
*/
export const AllVariants: Story = {
args: {},
render: () => (
<div className="flex flex-wrap gap-4 bg-background p-4 rounded-lg">
<Button variant="default">Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="muted">Muted</Button>
</div>
),
};
Do not use Storybook autodocs. Never set tags: ["autodocs"] on meta for packages/ui, web/src/components/ui, or web/src/systems/** stories. Rationale: autodocs-generated pages add noise and duplicate what we already express with concise stories, parameters.docs.description.component, and per-story JSDoc. If a component needs richer prose, write it in the description fields and keep the canvas as the source of truth.
Story Count Guidelines:
@agh/ui for existing components before creating new ones@agh/uibg-background, text-foreground, etc.) instead of explicit colorsrender function sets up the component in a way that allows interaction (e.g., not force-controlled unless necessary)meta: const meta: Meta<typeof Component>args: {} in all stories, even when using custom render functions@.cursor/rules/react.mdc@.cursor/rules/shadcn.mdc❌ Creating components from scratch when base components exist:
// ❌ BAD: Creating a button from scratch
export const Bad: Story = {
render: () => <button className="bg-blue-500 text-white px-4 py-2 rounded">Click me</button>,
};
// ✅ GOOD: Using base Button from @agh/ui
import { Button } from "@agh/ui";
export const Good: Story = {
args: {},
render: () => <Button variant="default">Click me</Button>,
};
❌ Enabling autodocs on meta:
// ❌ BAD: autodocs tag (forbidden in this repo)
const meta: Meta<typeof Button> = {
title: "ui/Button",
component: Button,
tags: ["autodocs"],
};
// ✅ GOOD: no autodocs tag; describe the component in parameters.docs
const meta: Meta<typeof Button> = {
title: "ui/Button",
component: Button,
parameters: {
layout: "centered",
docs: {
description: {
component: "Primary action button with variants and sizes.",
},
},
},
};
❌ Using explicit colors instead of design tokens:
// ❌ BAD: Using explicit colors
<div className="bg-white text-black border-gray-200">
// ✅ GOOD: Using design tokens
<div className="bg-background text-foreground border-border">
❌ Missing args property:
// ❌ BAD: Missing args property
export const Bad: Story = {
render: () => <Button>Click</Button>,
};
// ✅ GOOD: Including args property
export const Good: Story = {
args: {},
render: () => <Button>Click</Button>,
};
❌ Missing explicit type annotation:
// ❌ BAD: Type inference
const meta = {
title: "Components/Button",
component: Button,
} satisfies Meta<typeof Button>;
// ✅ GOOD: Explicit type annotation
const meta: Meta<typeof Button> = {
title: "Components/Button",
component: Button,
};
❌ Over-engineering stories with unnecessary examples:
// ❌ BAD: Too many stories with similar variations
export const Default: Story = { ... };
export const WithIcon: Story = { ... };
export const WithIconLeft: Story = { ... };
export const WithIconRight: Story = { ... };
export const WithLongText: Story = { ... };
export const WithShortText: Story = { ... };
export const Disabled: Story = { ... };
export const Loading: Story = { ... };
export const WithTooltip: Story = { ... };
export const InCard: Story = { ... };
export const InDialog: Story = { ... };
// ... 10+ stories for a simple button
// ✅ GOOD: Concise, focused stories
export const Default: Story = {
args: {
children: "Button",
variant: "default",
},
};
export const Variants: Story = {
args: {},
render: () => (
<div className="flex gap-2">
<Button variant="default">Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
</div>
),
};
export const Disabled: Story = {
args: {
children: "Disabled",
disabled: true,
},
};
// Only 3 stories covering essential use cases
❌ Over-complicated mock data or scenarios:
// ❌ BAD: Unnecessarily complex mock data
const mockUsers = [
{ id: "1", name: "John Doe", email: "[email protected]", role: "admin", avatar: "...", lastLogin: "...", permissions: [...], metadata: {...} },
{ id: "2", name: "Jane Smith", email: "[email protected]", role: "user", avatar: "...", lastLogin: "...", permissions: [...], metadata: {...} },
// ... 10 more users with full data
];
// ✅ GOOD: Minimal, realistic data
const mockUsers = [
{ id: "1", name: "John Doe", email: "[email protected]" },
{ id: "2", name: "Jane Smith", email: "[email protected]" },
];
development
Deep review of branch diffs, working trees, or GitHub PRs at any size. Use when the user asks for CodeRabbit-grade review, an incremental re-review after new pushes, publication of findings to a PR, a cross-LLM peer-review verdict round, or conformance review against spec artifacts. Don't use for applying fixes, reviewing specs or PRDs as documents, or quick single-file feedback.
tools
Orchestrate Claude and Codex worker TUIs from a controller agent through herdr panes and the herdr socket CLI. Use when delegating bounded tasks to herdr worker panes, running user-activated plan-first delegations (Claude Code plan mode, Codex Plan mode), waiting on native agent status (idle, working, blocked, done), or verifying worker reports. Workers launch as interactive TUIs via herdr agent start — never through headless runners (compozy exec, claude -p, codex exec). Not for cmux workspaces (see cmux-orchestration) and not for end-user herdr control.
tools
TanStack Query, Router, and Form patterns for React. Use when writing useQuery/queryOptions, mutations, caching, file-based routes, search params, loaders, or TanStack Form validation. Don't use for TanStack Start, TanStack DB/collections, Zustand client state, or non-TanStack routing.
development
Use when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.