Token导航 LogoToken导航TokenDH.com
前端设计只读github未标认证来源可访问clear审计通过

storybook-setup故事书设置

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

3,143

周安装

135

GitHub Stars

32

下载量

1,102
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:storybook-setup(故事书设置)
来源仓库:https://github.com/patricio0312rev/skills
仓库路径:skills/storybook-setup
安装命令:
npx skills add https://github.com/patricio0312rev/skills --skill storybook-setup
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/patricio0312rev/skills --skill storybook-setup

简介

用于辅助前端页面、组件、样式和交互逻辑的开发与维护,帮助提升前端开发效率和质量。

  • 适用于 React、Next.js、Vue、Tailwind、CSS 等相关技术的开发场景。
  • 能够生成或审查前端代码,整理组件结构,定位布局和性能问题。
  • 使用时需要结合项目现有设计系统、路由和构建方式,避免生成孤立片段;涉及页面改动时应配合本地预览和构建检查确认视觉效果。
  • 可结合来源仓库和原始 README 继续核验具体用法和实现细节。

SKILL.md

Storybook Setup

Configure Storybook for comprehensive component documentation and testing.

Core Workflow

  1. Initialize Storybook: Setup with framework
  2. Configure addons: Controls, actions, a11y
  3. Write stories: Document components
  4. Add documentation: MDX pages
  5. Setup testing: Visual regression
  6. Deploy docs: Static hosting

Installation

# Initialize Storybook
npx storybook@latest init

# Or with specific framework
npx storybook@latest init --type react
npx storybook@latest init --type nextjs
npx storybook@latest init --type vue3

Configuration

Main Configuration

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  stories: [
    '../src/**/*.mdx',
    '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)',
  ],

  addons: [
    '@storybook/addon-onboarding',
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@chromatic-com/storybook',
    '@storybook/addon-interactions',
    '@storybook/addon-a11y',
    '@storybook/addon-designs',
    '@storybook/addon-coverage',
  ],

  framework: {
    name: '@storybook/react-vite',
    options: {},
  },

  docs: {
    autodocs: 'tag',
  },

  staticDirs: ['../public'],

  typescript: {
    reactDocgen: 'react-docgen-typescript',
    reactDocgenTypescriptOptions: {
      shouldExtractLiteralValuesFromEnum: true,
      shouldRemoveUndefinedFromOptional: true,
      propFilter: (prop) =>
        prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
    },
  },

  viteFinal: async (config) => {
    // Customize Vite config
    return config;
  },
};

export default config;

Preview Configuration

// .storybook/preview.ts
import type { Preview } from '@storybook/react';
import { themes } from '@storybook/theming';
import '../src/styles/globals.css';

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
    backgrounds: {
      default: 'light',
      values: [
        { name: 'light', value: '#ffffff' },
        { name: 'dark', value: '#1a1a1a' },
        { name: 'gray', value: '#f5f5f5' },
      ],
    },
    layout: 'centered',
    docs: {
      theme: themes.light,
    },
    a11y: {
      config: {
        rules: [
          { id: 'color-contrast', enabled: true },
          { id: 'label', enabled: true },
        ],
      },
    },
    viewport: {
      viewports: {
        mobile: {
          name: 'Mobile',
          styles: { width: '375px', height: '667px' },
        },
        tablet: {
          name: 'Tablet',
          styles: { width: '768px', height: '1024px' },
        },
        desktop: {
          name: 'Desktop',
          styles: { width: '1440px', height: '900px' },
        },
      },
    },
  },
  globalTypes: {
    theme: {
      description: 'Global theme',
      defaultValue: 'light',
      toolbar: {
        title: 'Theme',
        icon: 'circlehollow',
        items: ['light', 'dark'],
        dynamicTitle: true,
      },
    },
  },
  decorators: [
    (Story, context) => {
      const theme = context.globals.theme;
      return (
        <div className={theme === 'dark' ? 'dark' : ''}>
          <div className="bg-white dark:bg-gray-900 p-4">
            <Story />
          </div>
        </div>
      );
    },
  ],
};

export default preview;

Writing Stories

Component Story Format (CSF3)

// src/components/Button/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import { Button } from './Button';

const meta = {
  title: 'Components/Button',
  component: Button,
  parameters: {
    layout: 'centered',
    docs: {
      description: {
        component: 'A versatile button component with multiple variants and sizes.',
      },
    },
  },
  tags: ['autodocs'],
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'outline', 'ghost'],
      description: 'Visual style variant',
      table: {
        type: { summary: 'string' },
        defaultValue: { summary: 'primary' },
      },
    },
    size: {
      control: 'radio',
      options: ['sm', 'md', 'lg'],
      description: 'Button size',
    },
    disabled: {
      control: 'boolean',
      description: 'Disable the button',
    },
    loading: {
      control: 'boolean',
      description: 'Show loading state',
    },
    children: {
      control: 'text',
      description: 'Button content',
    },
  },
  args: {
    onClick: fn(),
    children: 'Button',
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

// Basic stories
export const Primary: Story = {
  args: {
    variant: 'primary',
  },
};

export const Secondary: Story = {
  args: {
    variant: 'secondary',
  },
};

export const Outline: Story = {
  args: {
    variant: 'outline',
  },
};

export const Ghost: Story = {
  args: {
    variant: 'ghost',
  },
};

// Size variants
export const Small: Story = {
  args: {
    size: 'sm',
  },
};

export const Large: Story = {
  args: {
    size: 'lg',
  },
};

// States
export const Disabled: Story = {
  args: {
    disabled: true,
  },
};

export const Loading: Story = {
  args: {
    loading: true,
  },
};

// With icons
export const WithIcon: Story = {
  args: {
    children: (
      <>
        <PlusIcon className="mr-2 h-4 w-4" />
        Add Item
      </>
    ),
  },
};

// All variants showcase
export const AllVariants: Story = {
  render: () => (
    <div className="flex flex-wrap gap-4">
      <Button variant="primary">Primary</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
    </div>
  ),
};

Interactive Stories

// src/components/Form/Form.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent, expect, fn } from '@storybook/test';
import { Form } from './Form';

const meta: Meta<typeof Form> = {
  title: 'Components/Form',
  component: Form,
  args: {
    onSubmit: fn(),
  },
};

export default meta;
type Story = StoryObj<typeof meta>;

export const FilledForm: Story = {
  play: async ({ canvasElement, args }) => {
    const canvas = within(canvasElement);

    // Fill out the form
    const emailInput = canvas.getByLabelText('Email');
    await userEvent.type(emailInput, 'test@example.com', { delay: 50 });

    const passwordInput = canvas.getByLabelText('Password');
    await userEvent.type(passwordInput, 'password123', { delay: 50 });

    // Submit the form
    const submitButton = canvas.getByRole('button', { name: /submit/i });
    await userEvent.click(submitButton);

    // Assert the form was submitted
    await expect(args.onSubmit).toHaveBeenCalled();
  },
};

export const ValidationError: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);

    // Submit without filling
    const submitButton = canvas.getByRole('button', { name: /submit/i });
    await userEvent.click(submitButton);

    // Check for error messages
    await expect(canvas.getByText('Email is required')).toBeInTheDocument();
  },
};

MDX Documentation

{/* src/components/Button/Button.mdx */}
import { Meta, Story, Canvas, Controls, ArgTypes } from '@storybook/blocks';
import * as ButtonStories from './Button.stories';
import { Button } from './Button';

<Meta of={ButtonStories} />

# Button

The Button component is used to trigger actions or navigation.

## Import

import { Button } from '@/components/Button';


## Usage

## Variants

Buttons come in four variants to communicate different levels of emphasis.

### Primary

Use for primary actions that are the main call to action on a page.

### Secondary

Use for secondary actions that complement the primary action.

### Outline

Use for tertiary actions or when you want less visual emphasis.

### Ghost

Use for navigation or very subtle actions.

## Sizes

## States

### Disabled

### Loading

## Props

## Accessibility

- Buttons use the native `<button>` element
- Loading state announces to screen readers
- Focus states are clearly visible
- Disabled buttons maintain proper ARIA attributes

## Design Guidelines

1. Use descriptive button text
2. Limit to one primary button per section
3. Keep button text concise (2-4 words)
4. Use icons to reinforce meaning, not replace text

Testing Integration

Visual Regression with Chromatic

// .storybook/main.ts
const config: StorybookConfig = {
  addons: [
    '@chromatic-com/storybook',
  ],
};
// package.json
{
  "scripts": {
    "chromatic": "chromatic --project-token=$CHROMATIC_PROJECT_TOKEN"
  }
}

Test Runner

npm install @storybook/test-runner -D
// .storybook/test-runner.ts
import type { TestRunnerConfig } from '@storybook/test-runner';
import { getStoryContext } from '@storybook/test-runner';
import { injectAxe, checkA11y } from 'axe-playwright';

const config: TestRunnerConfig = {
  async preVisit(page) {
    await injectAxe(page);
  },
  async postVisit(page, context) {
    // Run accessibility tests
    const storyContext = await getStoryContext(page, context);
    if (!storyContext.parameters?.a11y?.disable) {
      await checkA11y(page, '#storybook-root', {
        detailedReport: true,
        detailedReportOptions: { html: true },
      });
    }
  },
};

export default config;
// package.json
{
  "scripts": {
    "test-storybook": "test-storybook",
    "test-storybook:ci": "test-storybook --ci"
  }
}

Design Tokens Integration

// .storybook/preview.ts
import { ThemeProvider } from 'styled-components';
import { theme } from '../src/styles/theme';

const preview: Preview = {
  decorators: [
    (Story) => (
      <ThemeProvider theme={theme}>
        <Story />
      </ThemeProvider>
    ),
  ],
};
// src/styles/theme.ts (document in Storybook)
export const theme = {
  colors: {
    primary: {
      50: '#eff6ff',
      500: '#3b82f6',
      900: '#1e3a8a',
    },
  },
  spacing: {
    xs: '0.25rem',
    sm: '0.5rem',
    md: '1rem',
    lg: '1.5rem',
    xl: '2rem',
  },
  radii: {
    sm: '0.25rem',
    md: '0.375rem',
    lg: '0.5rem',
    full: '9999px',
  },
};

Publishing

Static Export

// package.json
{
  "scripts": {
    "build-storybook": "storybook build",
    "storybook:serve": "npx http-server storybook-static"
  }
}

GitHub Pages

# .github/workflows/storybook.yml
name: Deploy Storybook

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci
      - run: npm run build-storybook

      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./storybook-static

Best Practices

  1. One component per file: Clear organization
  2. Use autodocs: Generate documentation
  3. Add controls: Interactive exploration
  4. Include a11y addon: Accessibility testing
  5. Write play functions: Interactive tests
  6. Document with MDX: Rich documentation
  7. Use decorators: Consistent context
  8. Visual regression: Catch UI changes

Output Checklist

Every Storybook setup should include:

  • Main configuration with addons
  • Preview with global decorators
  • Stories in CSF3 format
  • Autodocs enabled
  • Controls for all props
  • Accessibility addon
  • Dark mode support
  • Viewport presets
  • MDX documentation
  • Test runner setup
  • CI deployment
  • Static build script

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

26.88%
按下载量换算296

Gemini CLI

23.14%
按下载量换算255

Antigravity

20.33%
按下载量换算224

windsurf

13.76%
按下载量换算152

github-copilot

8.74%
按下载量换算96

Codex

3.91%
按下载量换算43

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

只读

该 Skill 主要提供规则、说明或参考内容,本身偏只读;真正读写文件、联网或执行命令仍取决于宿主 Agent 的任务。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills