本文へ移動
cccskills
無料GitHub で公開

format-storybook

Structure and organize Storybook files for scalability using battle-tested patterns. Based on "A Storybook format that scales with you" by Cassondra Roberts. Always use this skill when creating or editing any Storybook story file, writing template files, organizing a component library, setting up visual regression tests with Chromatic, or when the user asks anything about Storybook — even casual questions about file structure, controls, args, or how to document a component.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skillsスター 16(GitHub 16 + cccskills 0)
連携ツールFigma

実行スコア 未検証

インストール方法を見る

含まれるファイル(6)

  • SKILL.md10.4 KB
  • evals/evals.json5.1 KB
  • evals/files/tag.stories.js585 B
  • references/article.md1.5 KB
  • references/lit-templates.md2.0 KB
  • references/storybook-docs.md2.0 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Format Storybook

Based on "A Storybook format that scales with you" by Cassondra Roberts.

This skill provides patterns and conventions for building maintainable Storybook implementations that scale with your component library.

Core Principles

  1. Compose, don't duplicate - Import child component templates instead of copying markup
  2. Consistency over perfection - Pick patterns and stick with them across your library
  3. Progressive disclosure - Provide sensible defaults with optional controls for edge cases
  4. Self-documenting structure - Organize files so the architecture is immediately clear

File Structure

Keep Storybook assets close to component source files:

component/
├── component.js
├── component.css
└── stories/
    ├── component.stories.js    # Story definitions, controls, config
    ├── template.js              # Reusable render functions
    ├── component.docs.mdx       # [Optional] Documentation
    └── component.test.js        # [Optional] Visual regression grids

Story File Structure

Default Export

Every story file needs a default export with metadata:

export default {
  title: "Components/Button",           // Sidebar hierarchy
  component: "Button",                  // Component name
  argTypes: { /* control definitions */ },
  args: { /* default values */ },
  parameters: { /* additional config */ },
  tags: [ /* organizational tags */ ]
};

Organizing Controls

Group controls into logical categories for easy navigation:

  • State - Interactive states (focused, open, disabled)
  • Variant - Design variations (size, appearance)
  • Content - Text, images, nested components
  • Advanced - Edge cases and specialized configs
argTypes: {
  size: {
    control: "select",
    options: ["sm", "md", "lg"],
    description: "The size of the button",
    table: { category: "Variant" }
  },
  isDisabled: {
    control: "boolean",
    description: "Whether the button is disabled",
    table: { category: "State" }
  }
}

Tip: Create shared control files in .storybook/controls/ to reuse across components.

Default Values

Always provide sensible defaults so the primary story renders in a useful state:

args: {
  size: "md",
  isDisabled: false,
  label: "Click me"
}

Avoid meaningless "default" or "normal" options - use undefined instead.

Creating Individual Stories

Use .bind({}) to create stories that inherit from defaults:

export const Default = Template.bind({});
Default.args = {};

export const Disabled = Template.bind({});
Disabled.args = {
  isDisabled: true
};

export const WithIcon = Template.bind({});
WithIcon.args = {
  icon: "settings",
  label: "Settings"
};

Story Naming Conventions

Use concise, descriptive names:

  • ✅ Default - Primary interactive example
  • ✅ With Icon - Optional features
  • ✅ Loading State - Specific states
  • ✅ Error Variant - Edge cases
  • ❌ Button Default - Don't repeat component name

Useful Tags

  • !dev - Hide stories from sidebar (documentation-only stories)
  • !autodocs - Exclude from auto-generated docs
  • Combine both for visual regression testing grids

Template Files

The template.js file contains your rendering logic.

Template Structure

Export a primary Template(args, context) function:

import { html } from "lit";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";

export const Template = (args, context) => {
  const {
    rootClass = "button",
    id,
    testId,
    customClasses = [],
    customStyles = {},
    size = "md",
    isDisabled = false,
    label = "Button"
  } = args;

  return html`
    <button
      class=${classMap({
        [rootClass]: true,
        [`${rootClass}--${size}`]: size,
        [`${rootClass}--disabled`]: isDisabled,
        ...customClasses.reduce((acc, c) => ({ ...acc, [c]: true }), {})
      })}
      style=${styleMap(customStyles)}
      id=${ifDefined(id)}
      data-testid=${ifDefined(testId)}
      ?disabled=${isDisabled}
    >
      ${label}
    </button>
  `;
};

Standard Arguments

Accept these common arguments for flexibility:

  • rootClass - Base CSS class
  • id and testId - Identification and testing
  • customClasses - Array of additional classes
  • customStyles - Object of custom CSS properties

Composition Pattern

Import and render nested component templates:

import { Template as Popover } from "@design-system/popover/stories/template.js";
import { Template as Button } from "@design-system/button/stories/template.js";

export const Template = (args, context) => Popover({
  ...args,
  isOpen: true,
  trigger: (passthroughs, ctx) => Button({
    label: "Open Menu",
    ...passthroughs
  }, ctx),
  content: [/* child content */]
}, context);

Lit Directives for Dynamic Behavior

  • classMap - Conditional classes
  • styleMap - Inline style objects
  • ifDefined - Optional attributes (only render when defined)
  • when - Conditional template regions

For interactive examples, use context.updateArgs to toggle state:

onclick=${() => context.updateArgs({ isOpen: !args.isOpen })}

Visual Regression Testing

For tools like Chromatic, create test grids in component.test.js:

import { Template } from "./template.js";

export const TestGrid = {
  render: Template,
  parameters: {
    chromatic: { disableSnapshot: false }
  }
};

export const Default = TestGrid.bind({});
Default.tags = ["!autodocs", "!dev"];
Default.args = {
  // Test-specific args
};

Strategy: Group many states and variants into a single snapshot grid to optimize test runs.

Accessibility

Always provide ARIA attributes through arguments:

argTypes: {
  ariaHasPopup: {
    control: "select",
    options: ["true", "false", "menu", "dialog"],
    table: { category: "Advanced" }
  },
  ariaExpanded: {
    control: "boolean",
    table: { category: "State" }
  }
}

Use ifDefined so they only render when needed:

aria-haspopup=${ifDefined(args.ariaHasPopup)}
aria-expanded=${ifDefined(args.ariaExpanded)}

Documentation and Metadata

Design Links

Connect stories to design files:

parameters: {
  design: {
    type: "figma",
    url: "https://www.figma.com/..."
  }
}

Package Information

Include metadata for documentation:

import packageJson from "../package.json";

export default {
  parameters: {
    packageJson,
    status: { type: "stable" } // or "experimental", "deprecated"
  }
};

Component Status

Use tags to communicate lifecycle:

tags: ["stable", "migrated"]

Setup Recommendations

Path Aliasing

Configure package aliases in Storybook to avoid relative imports:

// .storybook/main.js
export default {
  viteFinal: (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      "@design-system": path.resolve(__dirname, "../packages")
    };
    return config;
  }
};

Use in imports:

// ✅ Good
import { Template } from "@design-system/button/stories/template.js";

// ❌ Avoid
import { Template } from "../../../button/stories/template.js";

Rendering Library (Vanilla Projects)

For projects without a framework, use lit for templates:

npm install lit

Benefits:

  • Lightweight and performant
  • Conditional classes and styles
  • Optional attributes
  • Dynamic rendering utilities

Auto-Generated Titles

Map folder structure to sidebar hierarchy:

// .storybook/main.js
export default {
  stories: [
    {
      directory: '../packages/components',
      files: '*.stories.*',
      titlePrefix: 'Components',
    },
  ],
};

Dos and Don'ts

Do

  • ✅ Import child component templates instead of duplicating markup
  • ✅ Keep template.js focused on the component itself
  • ✅ Categorize controls and set sensible defaults
  • ✅ Hide VRT-only stories from sidebar using tags
  • ✅ Reuse shared controls from a common location
  • ✅ Include proper ARIA attributes
  • ✅ Link to design files in parameters

Don't

  • ❌ Hardcode IDs - use a helper function to generate random IDs
  • ❌ Duplicate markup from nested components
  • ❌ Skip accessibility attributes
  • ❌ Create stories for every possible variant (let users explore via controls)
  • ❌ Use relative imports when aliases are available
  • ❌ Add meaningless "default" or "normal" variant options

Quick Reference

Minimal Story File

import { Template } from "./template.js";

export default {
  title: "Components/Button",
  component: "Button",
  argTypes: {
    size: {
      control: "select",
      options: ["sm", "md", "lg"],
      table: { category: "Variant" }
    }
  },
  args: {
    size: "md",
    label: "Click me"
  }
};

export const Default = Template.bind({});

Minimal Template File

import { html } from "lit";
import { classMap } from "lit/directives/class-map.js";

export const Template = (args) => {
  const { rootClass = "button", size = "md", label = "Button" } = args;
  
  return html`
    <button class=${classMap({
      [rootClass]: true,
      [`${rootClass}--${size}`]: size
    })}>
      ${label}
    </button>
  `;
};

References

Read these when you need more detail than the guidelines above:

  • storybook-docs.md - Read when you need to look up specific Storybook APIs, addon configuration, or testing integrations (Chromatic, test runner)
  • lit-templates.md - Read when you need details on Lit directives (classMap, styleMap, ifDefined, when) or template rendering patterns
  • article.md - Read when you want the philosophy and reasoning behind these patterns, or need comprehensive end-to-end examples

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Style and fully customize the Brightcove video player UI — control bar, play button, progress bar, volume, captions, playlists, responsive sizing, and skins. Use this skill whenever the user mentions Brightcove, video-js player styling, customizing a Brightcove player, changing player colors/layout/controls, embedding a Brightcove player, making it responsive, player skins or themes, Brightcove Studio styling, or working with Brightcove playlists or captions. Also use it when the user is working with `.video-js`, `vjs-*` CSS classes, or `bc()` / `videojs.getPlayer()` / `videojs()` JavaScript APIs.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

Write minimal, accessible web UI without over-engineering, adapting to whatever stack the project uses — React, Vue, Svelte, Angular, web components, or plain HTML. Use this skill on every project and every task that writes or reviews markup or components, builds forms, adds interactive elements like buttons, dialogs, accordions, or tabs, or audits code for accessibility — even when the user never mentions accessibility, and even inside a framework, CMS, or design system. It's non-negotiable regardless of project type, stack, or deadline. About to reach for ARIA attributes, a dialog library, a focus-trap package, or a headless UI component? Use this skill first.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

Define and enforce consistent coding standards across HTML, CSS, and JavaScript. Always use this skill when naming a new class, variable, component, or file; setting up a new project's conventions; choosing a class prefix for a new CSS category; deciding on modifier API names (sizes, shades, hierarchy, breakpoints); or reviewing code for formatting and naming consistency. If you're about to invent a prefix, abbreviation, or modifier name without checking the conventions first, use this skill.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

Create web interfaces with an authentic early-2010s aesthetic. Use this skill when the user wants a 2010s-era, Web 2.0, or retro corporate web look — gradient headers, glossy buttons, skeuomorphic icons, horizontal band layouts, and drop shadows from circa 2010–2014.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

ios-a11y

無料

Implement accessibility in iOS apps using Swift, UIKit, and SwiftUI. Use this skill whenever working on any iOS development task that involves: making UI elements accessible to VoiceOver or other assistive technologies, adding or reviewing accessibility labels/hints/traits/actions/values, supporting Dynamic Type or text scaling, respecting Reduce Motion or reduced transparency preferences, adapting to Dark Mode or increased contrast, building accessible forms and inputs, announcing dynamic content changes, managing focus programmatically, customizing accessibility focus order, supporting external keyboard navigation, or auditing iOS code for accessibility issues. Trigger even when the user only says "SwiftUI" or "UIKit" without mentioning "accessibility" explicitly — if they're building custom controls, modals, forms, lists, or animated views, this skill applies.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

more-css

無料

Write scalable, well-architected CSS using design tokens, cascade layers, and modern organization patterns. Use this skill as the default for any real project — if it has more than a handful of CSS files, multiple components, a team, a design system, or any kind of token or theming setup, this is the right skill.

日本語の概要は準備中です。原文の説明を表示しています。

mikemai2awesome/agent-skills162026年7月31日 更新

mikemai2awesome のスキルをすべて見る

このスキルの問題を報告する