Zum Inhalt

Storybook Cheatsheet

Storybook - Bauen Sie UIs in Isolation

Storybook ist ein Frontend-Workshop für den Bau von UI-Komponenten und Seiten in Isolation. Es hilft Ihnen, schwer zugängliche Zustände und Randfälle zu entwickeln und zu teilen, ohne dass Sie Ihre ganze App ausführen müssen. Tausende von Teams nutzen es für UI Entwicklung, Test und Dokumentation. < p>

generieren

Inhaltsverzeichnis

  • [Installation](#installation
  • (#getting-started)
  • (#writing-stories_)
  • Story Formate
  • Controls & Actions
  • Addons
  • [Konfiguration](#configuration_
  • (Theming)(#theming)
  • Test
  • [Dokumentation](LINK_9__
  • [Bestellung](LINK_10__
  • [Erweiterte Funktionen](#advanced-features
  • [Performance](#performance_
  • [Integration](LINK_13__
  • (#troubleshooting_)
  • Beste Praktiken

Installation

Schneller Start

# Initialize Storybook in existing project
npx storybook@latest init

# Create new project with Storybook
npx create-react-app my-app
cd my-app
npx storybook@latest init

# Start Storybook
npm run storybook
```_

### Manuelle Installation
```bash
# Install Storybook CLI
npm install -g @storybook/cli

# Initialize in project
sb init

# Or specify framework
sb init --type react
sb init --type vue3
sb init --type angular
```_

### Rahmenspezifisches Setup
```bash
# React
npx storybook@latest init --type react

# Vue 3
npx storybook@latest init --type vue3

# Angular
npx storybook@latest init --type angular

# Svelte
npx storybook@latest init --type svelte

# Web Components
npx storybook@latest init --type web-components

# HTML
npx storybook@latest init --type html
```_

### Projektstruktur
my-app/ ├── .storybook/ │ ├── main.js # Main configuration │ └── preview.js # Global settings ├── src/ │ ├── components/ │ │ ├── Button/ │ │ │ ├── Button.js │ │ │ ├── Button.css │ │ │ └── Button.stories.js │ │ └── Header/ │ │ ├── Header.js │ │ └── Header.stories.js │ └── stories/ # Example stories ├── package.json └── README.md
## Erste Schritte

### Grundlegende Geschichte
```javascript
// src/components/Button/Button.stories.js
import { Button } from './Button';

export default {
  title: 'Example/Button',
  component: Button,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
  argTypes: {
    backgroundColor: { control: 'color' },
  },
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
};

export const Secondary = {
  args: {
    label: 'Button',
  },
};

export const Large = {
  args: {
    size: 'large',
    label: 'Button',
  },
};

export const Small = {
  args: {
    size: 'small',
    label: 'Button',
  },
};
```_

### Komponentenbeispiel
```javascript
// src/components/Button/Button.js
import React from 'react';
import PropTypes from 'prop-types';
import './button.css';

export const Button = ({ primary = false, backgroundColor = null, size = 'medium', label, ...props }) => {
  const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
  return (
    <button
      type="button"
      className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
      style={{ backgroundColor }}
      {...props}
    >
      {label}
    </button>
  );
};

Button.propTypes = {
  primary: PropTypes.bool,
  backgroundColor: PropTypes.string,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  label: PropTypes.string.isRequired,
  onClick: PropTypes.func,
};

Button.defaultProps = {
  primary: false,
  onClick: undefined,
};
```_

### Laufendes Storybook
```bash
# Start development server
npm run storybook

# Build static Storybook
npm run build-storybook

# Serve built Storybook
npx http-server storybook-static

# Start with specific port
npm run storybook -- --port 9001

# Start in quiet mode
npm run storybook -- --quiet
```_

## Geschichten schreiben

### Geschichte
```javascript
// Component.stories.js
import { Component } from './Component';

// Default export - story metadata
export default {
  title: 'Path/To/Component',
  component: Component,
  parameters: {
    // Story-level parameters
  },
  argTypes: {
    // Control definitions
  },
  args: {
    // Default args for all stories
  },
};

// Named exports - individual stories
export const Default = {};

export const WithProps = {
  args: {
    prop1: 'value1',
    prop2: 'value2',
  },
};

export const CustomStory = {
  render: (args) => <Component {...args} />,
  args: {
    // Story-specific args
  },
};
```_

### Geschichte der Geschichte
```javascript
// Organize stories with hierarchy
export default {
  title: 'Design System/Components/Button',
  // Creates: Design System > Components > Button
};

export default {
  title: 'Pages/Dashboard/UserProfile',
  // Creates: Pages > Dashboard > UserProfile
};

export default {
  title: 'Example/Button',
  // Creates: Example > Button
};
```_

### Mehrere Komponenten
```javascript
// stories/Forms.stories.js
import { Input } from '../components/Input';
import { Button } from '../components/Button';
import { Form } from '../components/Form';

export default {
  title: 'Forms/LoginForm',
};

export const LoginForm = () => (
  <Form>
    <Input type="email" placeholder="Email" />
    <Input type="password" placeholder="Password" />
    <Button primary>Login</Button>
  </Form>
);

export const SignupForm = () => (
  <Form>
    <Input placeholder="Full Name" />
    <Input type="email" placeholder="Email" />
    <Input type="password" placeholder="Password" />
    <Input type="password" placeholder="Confirm Password" />
    <Button primary>Sign Up</Button>
  </Form>
);
```_

### Story Parameter
```javascript
export default {
  title: 'Example/Button',
  component: Button,
  parameters: {
    // Layout
    layout: 'centered', // 'centered' | 'fullscreen' | 'padded'

    // Backgrounds
    backgrounds: {
      default: 'light',
      values: [
        { name: 'light', value: '#ffffff' },
        { name: 'dark', value: '#333333' },
      ],
    },

    // Viewport
    viewport: {
      defaultViewport: 'mobile1',
    },

    // Documentation
    docs: {
      description: {
        component: 'Button component for user interactions',
      },
    },
  },
};
```_

## Geschichte Formate

### CSF 3.0 (Current)
```javascript
// Modern format with object syntax
export default {
  title: 'Example/Button',
  component: Button,
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
};

export const Secondary = {
  args: {
    primary: false,
    label: 'Button',
  },
};
```_

### CSF 2.0 (Legacy)
```javascript
// Function-based format
export default {
  title: 'Example/Button',
  component: Button,
};

const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
};

export const Secondary = Template.bind({});
Secondary.args = {
  primary: false,
  label: 'Button',
};
```_

### Kundenspezifische Render Funktionen
```javascript
export const CustomRender = {
  render: (args) => {
    const [count, setCount] = React.useState(0);

    return (
      <div>
        <p>Count: {count}</p>
        <Button 
          {...args} 
          onClick={() => setCount(count + 1)}
        />
      </div>
    );
  },
  args: {
    label: 'Increment',
  },
};
```_

### Funktionen spielen
```javascript
import { userEvent, within } from '@storybook/testing-library';

export const InteractiveExample = {
  args: {
    label: 'Click me',
  },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const button = canvas.getByRole('button');

    // Simulate user interaction
    await userEvent.click(button);

    // Add assertions if needed
    // expect(button).toHaveClass('clicked');
  },
};
```_

## Kontrolle und Aktionen

### ArgTyps Konfiguration
```javascript
export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    // Text input
    label: {
      control: 'text',
      description: 'Button label text',
    },

    // Boolean
    primary: {
      control: 'boolean',
      description: 'Primary button style',
    },

    // Select dropdown
    size: {
      control: 'select',
      options: ['small', 'medium', 'large'],
      description: 'Button size',
    },

    // Radio buttons
    variant: {
      control: 'radio',
      options: ['primary', 'secondary', 'danger'],
    },

    // Color picker
    backgroundColor: {
      control: 'color',
    },

    // Number input
    borderRadius: {
      control: { type: 'number', min: 0, max: 50, step: 1 },
    },

    // Range slider
    opacity: {
      control: { type: 'range', min: 0, max: 1, step: 0.1 },
    },

    // Object editor
    style: {
      control: 'object',
    },

    // Array editor
    items: {
      control: 'object',
    },

    // Date picker
    createdAt: {
      control: 'date',
    },

    // Disable control
    onClick: {
      action: 'clicked',
      control: false,
    },
  },
};
```_

### Maßnahmen
```javascript
import { action } from '@storybook/addon-actions';

export default {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    onClick: { action: 'clicked' },
    onMouseEnter: { action: 'mouse-enter' },
    onMouseLeave: { action: 'mouse-leave' },
  },
};

// Or in individual stories
export const WithActions = {
  args: {
    label: 'Button',
    onClick: action('button-click'),
    onMouseEnter: action('mouse-enter'),
  },
};

// Multiple actions
export const MultipleActions = {
  args: {
    label: 'Multi Action Button',
    onClick: (...args) => {
      action('primary-click')(...args);
      action('analytics-track')('button-clicked');
    },
  },
};
```_

### Erweiterte Steuerungen
```javascript
export default {
  title: 'Example/Form',
  component: Form,
  argTypes: {
    // Conditional controls
    showAdvanced: {
      control: 'boolean',
    },
    advancedOptions: {
      control: 'object',
      if: { arg: 'showAdvanced', truthy: true },
    },

    // Custom control
    theme: {
      control: {
        type: 'select',
        labels: {
          light: 'Light Theme',
          dark: 'Dark Theme',
          auto: 'Auto (System)',
        },
      },
      options: ['light', 'dark', 'auto'],
    },

    // Multi-select
    features: {
      control: 'multi-select',
      options: ['feature1', 'feature2', 'feature3'],
    },
  },
};
```_

## Addons

### Grundlegende Addons
```javascript
// .storybook/main.js
module.exports = {
  addons: [
    '@storybook/addon-essentials', // Includes most common addons
    '@storybook/addon-interactions',
    '@storybook/addon-a11y',
    '@storybook/addon-design-tokens',
  ],
};

// Individual addons (if not using essentials)
module.exports = {
  addons: [
    '@storybook/addon-controls',
    '@storybook/addon-actions',
    '@storybook/addon-viewport',
    '@storybook/addon-backgrounds',
    '@storybook/addon-docs',
    '@storybook/addon-toolbars',
  ],
};
```_

### Erreichbarkeitszusatz
```javascript
// .storybook/preview.js
export const parameters = {
  a11y: {
    // Optional selector to inspect
    element: '#storybook-root',
    config: {
      rules: [
        {
          // Disable specific rules
          id: 'color-contrast',
          enabled: false,
        },
      ],
    },
    // Show violations in action panel
    manual: true,
  },
};

// In stories
export const AccessibleButton = {
  args: {
    label: 'Accessible Button',
  },
  parameters: {
    a11y: {
      // Story-specific a11y config
      config: {
        rules: [
          { id: 'button-name', enabled: true },
        ],
      },
    },
  },
};
```_

### Viewport Addon
```javascript
// .storybook/preview.js
export const parameters = {
  viewport: {
    viewports: {
      mobile: {
        name: 'Mobile',
        styles: {
          width: '375px',
          height: '667px',
        },
      },
      tablet: {
        name: 'Tablet',
        styles: {
          width: '768px',
          height: '1024px',
        },
      },
      desktop: {
        name: 'Desktop',
        styles: {
          width: '1024px',
          height: '768px',
        },
      },
    },
    defaultViewport: 'mobile',
  },
};
```_

### Design Tokens Addon
```javascript
// design-tokens.json
{
  "colors": {
    "primary": "#007bff",
    "secondary": "#6c757d",
    "success": "#28a745",
    "danger": "#dc3545"
  },
  "spacing": {
    "xs": "4px",
    "sm": "8px",
    "md": "16px",
    "lg": "24px",
    "xl": "32px"
  },
  "typography": {
    "fontFamily": {
      "primary": "Inter, sans-serif",
      "mono": "Monaco, monospace"
    },
    "fontSize": {
      "sm": "14px",
      "md": "16px",
      "lg": "18px",
      "xl": "24px"
    }
  }
}

// .storybook/main.js
module.exports = {
  addons: [
    {
      name: '@storybook/addon-design-tokens',
      options: {
        designTokenGlob: '**/design-tokens.json',
      },
    },
  ],
};
```_

### Kundenspezifische Addons
```javascript
// .storybook/addons/theme-switcher/register.js
import { addons, types } from '@storybook/addons';
import { ADDON_ID, TOOL_ID } from './constants';
import { Tool } from './Tool';

addons.register(ADDON_ID, () => {
  addons.add(TOOL_ID, {
    type: types.TOOL,
    title: 'Theme Switcher',
    render: Tool,
  });
});

// .storybook/addons/theme-switcher/Tool.js
import React from 'react';
import { useGlobals } from '@storybook/api';
import { IconButton } from '@storybook/components';

export const Tool = () => {
  const [globals, updateGlobals] = useGlobals();
  const theme = globals.theme || 'light';

  const toggleTheme = () => {
    updateGlobals({
      theme: theme === 'light' ? 'dark' : 'light',
    });
  };

  return (
    <IconButton
      key="theme-switcher"
      title="Toggle theme"
      onClick={toggleTheme}
    >
      {theme === 'light' ? '🌙' : '☀️'}
    </IconButton>
  );
};
```_

## Konfiguration

### Hauptkonfiguration
```javascript
// .storybook/main.js
module.exports = {
  // Stories location
  stories: [
    '../src/**/*.stories.@(js|jsx|ts|tsx|mdx)',
    '../stories/**/*.stories.@(js|jsx|ts|tsx|mdx)',
  ],

  // Addons
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    '@storybook/addon-a11y',
  ],

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

  // Features
  features: {
    buildStoriesJson: true,
    storyStoreV7: true,
  },

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

  // Webpack customization
  webpackFinal: async (config) => {
    // Add custom webpack config
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
    });

    return config;
  },

  // Vite customization
  viteFinal: async (config) => {
    // Customize Vite config
    config.define = {
      ...config.define,
      global: 'globalThis',
    };

    return config;
  },

  // Documentation
  docs: {
    autodocs: 'tag',
  },

  // Static directories
  staticDirs: ['../public'],
};
```_

### Vorschau Konfigurieren
```javascript
// .storybook/preview.js
import '../src/index.css'; // Global styles

export const parameters = {
  // Actions
  actions: { argTypesRegex: '^on[A-Z].*' },

  // Controls
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
    expanded: true,
    sort: 'requiredFirst',
  },

  // Layout
  layout: 'centered',

  // Backgrounds
  backgrounds: {
    default: 'light',
    values: [
      { name: 'light', value: '#ffffff' },
      { name: 'dark', value: '#333333' },
      { name: 'gray', value: '#f8f9fa' },
    ],
  },

  // Viewport
  viewport: {
    viewports: {
      mobile1: {
        name: 'Small mobile',
        styles: { width: '320px', height: '568px' },
      },
      mobile2: {
        name: 'Large mobile',
        styles: { width: '414px', height: '896px' },
      },
      tablet: {
        name: 'Tablet',
        styles: { width: '768px', height: '1024px' },
      },
    },
  },

  // Documentation
  docs: {
    theme: themes.light,
    source: {
      state: 'open',
    },
  },
};

// Global decorators
export const decorators = [
  (Story) => (
    <div style={{ margin: '3em', fontFamily: 'Inter, sans-serif' }}>
      <Story />
    </div>
  ),
];

// Global args
export const args = {
  // Default args for all stories
};

// Global arg types
export const argTypes = {
  // Global arg types
};
```_

### Umweltvariablen
```javascript
// .storybook/main.js
module.exports = {
  env: (config) => ({
    ...config,
    API_URL: 'https://api.example.com',
    FEATURE_FLAG: true,
  }),

  webpackFinal: async (config) => {
    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env.STORYBOOK': JSON.stringify(true),
      })
    );
    return config;
  },
};

// In components
const apiUrl = process.env.STORYBOOK 
  ? 'https://api-mock.example.com' 
  : process.env.API_URL;
```_

## Theming

### Zoll Thema
```javascript
// .storybook/theme.js
import { create } from '@storybook/theming';

export default create({
  base: 'light', // 'light' | 'dark'

  // Brand
  brandTitle: 'My Company Storybook',
  brandUrl: 'https://example.com',
  brandImage: 'https://example.com/logo.svg',
  brandTarget: '_self',

  // Colors
  colorPrimary: '#FF4785',
  colorSecondary: '#029CFD',

  // UI
  appBg: '#F6F9FC',
  appContentBg: '#FFFFFF',
  appBorderColor: '#E6ECF0',
  appBorderRadius: 4,

  // Typography
  fontBase: '"Inter", sans-serif',
  fontCode: 'Monaco, monospace',

  // Text colors
  textColor: '#2E3438',
  textInverseColor: '#FFFFFF',
  textMutedColor: '#798186',

  // Toolbar
  barTextColor: '#798186',
  barSelectedColor: '#029CFD',
  barBg: '#FFFFFF',

  // Form
  inputBg: '#FFFFFF',
  inputBorder: '#E6ECF0',
  inputTextColor: '#2E3438',
  inputBorderRadius: 4,
});

// .storybook/manager.js
import { addons } from '@storybook/addons';
import theme from './theme';

addons.setConfig({
  theme,
});
```_

### Dark Theme
```javascript
// .storybook/dark-theme.js
import { create } from '@storybook/theming';

export default create({
  base: 'dark',

  brandTitle: 'My Company Storybook',
  brandUrl: 'https://example.com',
  brandImage: 'https://example.com/logo-white.svg',

  colorPrimary: '#FF4785',
  colorSecondary: '#029CFD',

  appBg: '#1A1A1A',
  appContentBg: '#2D2D2D',
  appBorderColor: '#404040',

  textColor: '#FFFFFF',
  textInverseColor: '#1A1A1A',
  textMutedColor: '#CCCCCC',

  barTextColor: '#CCCCCC',
  barSelectedColor: '#029CFD',
  barBg: '#2D2D2D',

  inputBg: '#404040',
  inputBorder: '#666666',
  inputTextColor: '#FFFFFF',
});
```_

### Thema wechseln
```javascript
// .storybook/preview.js
import { themes } from '@storybook/theming';

export const parameters = {
  docs: {
    theme: themes.light,
  },
  darkMode: {
    // Override the default dark theme
    dark: { ...themes.dark, appBg: 'black' },
    // Override the default light theme
    light: { ...themes.normal, appBg: 'white' },
    // Set the initial theme
    current: 'light',
    // Disable the addon for specific stories
    stylePreview: true,
  },
};

// Global decorator for theme switching
export const decorators = [
  (Story, context) => {
    const theme = context.globals.theme || 'light';

    return (
      <div className={`theme-${theme}`}>
        <Story />
      </div>
    );
  },
];

// Global types for theme switcher
export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme for components',
    defaultValue: 'light',
    toolbar: {
      icon: 'circlehollow',
      items: [
        { value: 'light', icon: 'sun', title: 'Light' },
        { value: 'dark', icon: 'moon', title: 'Dark' },
      ],
      showName: true,
    },
  },
};
```_

## Prüfung

### Visuelle Prüfung
```javascript
// .storybook/test-runner.js
const { getStoryContext } = require('@storybook/test-runner');

module.exports = {
  async postRender(page, context) {
    const storyContext = await getStoryContext(page, context);

    // Skip visual tests for specific stories
    if (storyContext.parameters?.skipVisualTest) {
      return;
    }

    // Take screenshot
    const image = await page.screenshot();
    expect(image).toMatchImageSnapshot({
      customSnapshotIdentifier: context.id,
    });
  },
};

// In stories
export const VisualTest = {
  args: {
    label: 'Visual Test Button',
  },
  parameters: {
    // Skip this story in visual tests
    skipVisualTest: true,
  },
};
```_

### Interaction Testing
```javascript
// Button.stories.js
import { userEvent, within, expect } from '@storybook/test';

export const InteractionTest = {
  args: {
    label: 'Click me',
  },
  play: async ({ canvasElement, args }) => {
    const canvas = within(canvasElement);

    // Find elements
    const button = canvas.getByRole('button', { name: /click me/i });

    // Simulate interactions
    await userEvent.click(button);

    // Assertions
    await expect(args.onClick).toHaveBeenCalled();

    // Check DOM changes
    await expect(button).toHaveClass('clicked');

    // Wait for async operations
    await canvas.findByText('Success!');
  },
};

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

    // Fill form
    const emailInput = canvas.getByLabelText(/email/i);
    const passwordInput = canvas.getByLabelText(/password/i);
    const submitButton = canvas.getByRole('button', { name: /submit/i });

    await userEvent.type(emailInput, 'user@example.com');
    await userEvent.type(passwordInput, 'password123');
    await userEvent.click(submitButton);

    // Check results
    await expect(canvas.getByText(/success/i)).toBeInTheDocument();
  },
};
```_

### Einheitstest mit Geschichten
```javascript
// Button.test.js
import { render, screen } from '@testing-library/react';
import { composeStories } from '@storybook/testing-react';
import * as stories from './Button.stories';

const { Primary, Secondary, Large } = composeStories(stories);

describe('Button', () => {
  test('renders primary button', () => {
    render(<Primary />);
    expect(screen.getByRole('button')).toHaveClass('storybook-button--primary');
  });

  test('renders secondary button', () => {
    render(<Secondary />);
    expect(screen.getByRole('button')).not.toHaveClass('storybook-button--primary');
  });

  test('renders large button', () => {
    render(<Large />);
    expect(screen.getByRole('button')).toHaveClass('storybook-button--large');
  });
});
```_

### Zugänglichkeitsprüfung
```javascript
// a11y.test.js
import { axe, toHaveNoViolations } from 'jest-axe';
import { render } from '@testing-library/react';
import { composeStories } from '@storybook/testing-react';
import * as stories from './Button.stories';

expect.extend(toHaveNoViolations);

const { Primary, Secondary } = composeStories(stories);

describe('Button Accessibility', () => {
  test('Primary button should not have accessibility violations', async () => {
    const { container } = render(<Primary />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });

  test('Secondary button should not have accessibility violations', async () => {
    const { container } = render(<Secondary />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});
```_

## Dokumentation

### Autodokumentation
```javascript
// Component with JSDoc
/**
 * Primary UI component for user interaction
 */
export const Button = ({
  /**
   * Is this the principal call to action on the page?
   */
  primary = false,
  /**
   * What background color to use
   */
  backgroundColor,
  /**
   * How large should the button be?
   */
  size = 'medium',
  /**
   * Button contents
   */
  label,
  /**
   * Optional click handler
   */
  onClick,
  ...props
}) => {
  // Component implementation
};

// Stories with auto-generated docs
export default {
  title: 'Example/Button',
  component: Button,
  tags: ['autodocs'], // Enable auto-documentation
  parameters: {
    docs: {
      description: {
        component: 'Button component for user interactions. Supports multiple sizes and variants.',
      },
    },
  },
};
```_

### Kundenspezifische Dokumentation
```javascript
// Button.stories.js
export default {
  title: 'Example/Button',
  component: Button,
  parameters: {
    docs: {
      description: {
        component: `
# Button Component

The Button component is a fundamental UI element used throughout the application.

## Usage

\`\`\`jsx
import { Button } from './Button';

<Button primary onClick={handleClick}>
  Click me
</Button>
\`\`\`

## Design Guidelines

- Use primary buttons for main actions
- Use secondary buttons for supporting actions
- Ensure sufficient color contrast for accessibility
        `,
      },
    },
  },
};

export const Primary = {
  args: {
    primary: true,
    label: 'Button',
  },
  parameters: {
    docs: {
      description: {
        story: 'Primary buttons are used for the main call-to-action on a page.',
      },
    },
  },
};
```_

### MDX Dokumentation
__CODE_BLOCK_35_jsx
Import { Button } aus './Button';

Funktion MyComponent() {
zurück (
<= <===========================================================
<Button primär onClick={() => alert('Primary clicked!')}>
Primäraktion
</Button>
<Button onClick={() => alert('Secondary clicked!')}>
Sekundäraktion
</Button>
</div>
;
}
### Dokumentationsseiten
```javascript
// .storybook/main.js
module.exports = {
  stories: [
    '../src/**/*.stories.@(js|jsx|ts|tsx)',
    '../docs/**/*.stories.mdx', // Documentation stories
  ],
};

// docs/Introduction.stories.mdx
import { Meta } from '@storybook/addon-docs';

<Meta title="Introduction" />

# Design System

Welcome to our design system documentation.

## Getting Started

This Storybook contains all the components, patterns, and guidelines for our design system.

### Installation

```bash
npm install @company/design-system

Usage

Import { Button, Input, Card } von '@company/design-system';

Principles

  1. Consistency - Maintain visual and functional consistency
  2. Accessibility - Ensure all components are accessible
  3. Performance - Optimize for speed and efficiency
  4. Flexibility - Support customization and theming
    ## Bereitstellung
    
    ### Strategischer Aufbau
    ```bash
    # Build Storybook for deployment
    npm run build-storybook
    
    # Output directory
    ls storybook-static/
    
    # Serve locally
    npx http-server storybook-static
    ```_
    
    ### Netlify Deployment
    ```bash
    # netlify.toml
    [build]
      command = "npm run build-storybook"
      publish = "storybook-static"
    
    [build.environment]
      NODE_VERSION = "16"
    
    # Deploy
    npm install -g netlify-cli
    netlify deploy --prod --dir=storybook-static
    ```_
    
    ### Vercel Bereitstellung
    ```json
    // vercel.json
    {
      "buildCommand": "npm run build-storybook",
      "outputDirectory": "storybook-static",
      "framework": null
    }
    ```_
    
    ### GitHub Seiten
    ```yaml
    # .github/workflows/storybook.yml
    name: Build and Deploy Storybook
    
    on:
      push:
        branches: [ main ]
    
    jobs:
      build-and-deploy:
        runs-on: ubuntu-latest
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        - name: Setup Node
          uses: actions/setup-node@v3
          with:
            node-version: '16'
            cache: 'npm'
    
        - name: Install dependencies
          run: npm ci
    
        - name: Build Storybook
          run: npm run build-storybook
    
        - name: Deploy to GitHub Pages
          uses: peaceiris/actions-gh-pages@v3
          with:
            github_token: ${{ secrets.GITHUB_TOKEN }}
            publish_dir: ./storybook-static
    ```_
    
    ### Einsatz von Docker
    ```dockerfile
    # Dockerfile
    FROM node:16-alpine as builder
    
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci
    
    COPY . .
    RUN npm run build-storybook
    
    FROM nginx:alpine
    COPY --from=builder /app/storybook-static /usr/share/nginx/html
    COPY nginx.conf /etc/nginx/nginx.conf
    
    EXPOSE 80
    CMD ["nginx", "-g", "daemon off;"]
    ```_
    
    ### AWS S3 + CloudFront
    ```bash
    # Build and deploy to S3
    npm run build-storybook
    aws s3 sync storybook-static/ s3://my-storybook-bucket --delete
    aws cloudfront create-invalidation --distribution-id ABCD1234 --paths "/*"
    ```_
    
    ## Erweiterte Funktionen
    
    ### Benutzerdefinierte Webpack Konfiguration
    ```javascript
    // .storybook/main.js
    const path = require('path');
    
    module.exports = {
      webpackFinal: async (config) => {
        // Add alias
        config.resolve.alias = {
          ...config.resolve.alias,
          '@': path.resolve(__dirname, '../src'),
          '@components': path.resolve(__dirname, '../src/components'),
        };
    
        // Add custom loader
        config.module.rules.push({
          test: /\.scss$/,
          use: [
            'style-loader',
            'css-loader',
            {
              loader: 'sass-loader',
              options: {
                additionalData: `@import "@/styles/variables.scss";`,
              },
            },
          ],
        });
    
        // Add plugin
        config.plugins.push(
          new webpack.DefinePlugin({
            __VERSION__: JSON.stringify(process.env.npm_package_version),
          })
        );
    
        return config;
      },
    };
    ```_
    
    ### Benutzerdefinierte Babel Konfiguration
    ```javascript
    // .storybook/main.js
    module.exports = {
      babel: async (options) => ({
        ...options,
        plugins: [
          ...options.plugins,
          ['babel-plugin-styled-components', { displayName: true }],
        ],
      }),
    };
    ```_
    
    ### Umwelt-spezifische Konfiguration
    ```javascript
    // .storybook/main.js
    const isDevelopment = process.env.NODE_ENV === 'development';
    
    module.exports = {
      addons: [
        '@storybook/addon-essentials',
        ...(isDevelopment ? ['@storybook/addon-a11y'] : []),
      ],
    
      features: {
        storyStoreV7: !isDevelopment, // Disable in development for faster builds
      },
    
      webpackFinal: async (config) => {
        if (isDevelopment) {
          // Development-specific webpack config
          config.optimization.minimize = false;
        }
    
        return config;
      },
    };
    ```_
    
    ### Personal Manager UI
    ```javascript
    // .storybook/manager.js
    import { addons } from '@storybook/addons';
    
    addons.setConfig({
      // Show/hide panels
      showPanel: true,
      panelPosition: 'bottom', // 'bottom' | 'right'
    
      // Sidebar
      showNav: true,
      showToolbar: true,
    
      // Initial active panel
      selectedPanel: 'storybook/controls/panel',
    
      // Sidebar tree expansion
      initialActive: 'sidebar',
      sidebar: {
        showRoots: false,
        collapsedRoots: ['other'],
      },
    
      // Toolbar
      toolbar: {
        title: { hidden: false },
        zoom: { hidden: false },
        eject: { hidden: false },
        copy: { hidden: false },
        fullscreen: { hidden: false },
      },
    });
    ```_
    
    ## Leistung
    
    ### Lazy Loading
    ```javascript
    // .storybook/main.js
    module.exports = {
      features: {
        storyStoreV7: true, // Enable lazy loading
      },
    
      stories: [
        {
          directory: '../src/components',
          files: '**/*.stories.*',
          titlePrefix: 'Components',
        },
        {
          directory: '../src/pages',
          files: '**/*.stories.*',
          titlePrefix: 'Pages',
        },
      ],
    };
    ```_
    
    ### Bündeloptimierung
    ```javascript
    // .storybook/main.js
    module.exports = {
      webpackFinal: async (config) => {
        // Code splitting
        config.optimization.splitChunks = {
          chunks: 'all',
          cacheGroups: {
            vendor: {
              test: /[\\/]node_modules[\\/]/,
              name: 'vendors',
              chunks: 'all',
            },
          },
        };
    
        // Tree shaking
        config.optimization.usedExports = true;
        config.optimization.sideEffects = false;
    
        return config;
      },
    };
    ```_
    
    ### Speicheroptimierung
    ```javascript
    // .storybook/preview.js
    export const parameters = {
      // Reduce memory usage
      options: {
        storySort: {
          method: 'alphabetical',
          order: ['Introduction', 'Components', 'Pages'],
          locales: 'en-US',
        },
      },
    
      // Disable source code addon for better performance
      docs: {
        source: {
          state: 'closed',
        },
      },
    };
    
    // Cleanup decorators
    export const decorators = [
      (Story, context) => {
        // Cleanup on story change
        React.useEffect(() => {
          return () => {
            // Cleanup logic
          };
        }, [context.id]);
    
        return <Story />;
      },
    ];
    ```_
    
    ## Integration
    
    ### Integration von Werkzeugen
    ```javascript
    // Figma integration
    export default {
      title: 'Example/Button',
      component: Button,
      parameters: {
        design: {
          type: 'figma',
          url: 'https://www.figma.com/file/ABC123/Design-System?node-id=123%3A456',
        },
      },
    };
    
    // Sketch integration
    export const SketchExample = {
      parameters: {
        design: {
          type: 'sketch',
          url: 'https://sketch.cloud/s/abc123',
        },
      },
    };
    
    // Adobe XD integration
    export const XDExample = {
      parameters: {
        design: {
          type: 'adobe-xd',
          url: 'https://xd.adobe.com/view/abc123',
        },
      },
    };
    ```_
    
    ### Integration testen
    ```javascript
    // jest.config.js
    module.exports = {
      testEnvironment: 'jsdom',
      setupFilesAfterEnv: ['<rootDir>/src/setupTests.js'],
      testPathIgnorePatterns: ['/node_modules/', '/storybook-static/'],
    
      // Test stories
      testMatch: [
        '<rootDir>/src/**/__tests__/**/*.(js|jsx|ts|tsx)',
        '<rootDir>/src/**/?(*.)(spec|test).(js|jsx|ts|tsx)',
        '<rootDir>/src/**/*.stories.test.(js|jsx|ts|tsx)',
      ],
    };
    
    // Chromatic integration
    // .github/workflows/chromatic.yml
    name: 'Chromatic'
    on: push
    
    jobs:
      chromatic-deployment:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v1
          - run: yarn
          - uses: chromaui/action@v1
            with:
              token: ${{ secrets.GITHUB_TOKEN }}
              projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
    ```_
    
    ### CI/CD Integration
    ```yaml
    # .github/workflows/storybook-tests.yml
    name: Storybook Tests
    on: [push, pull_request]
    
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-node@v3
            with:
              node-version: '16'
              cache: 'npm'
    
          - run: npm ci
          - run: npm run build-storybook --quiet
          - run: npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
              "npx http-server storybook-static --port 6006 --silent" \
              "npx wait-on http://127.0.0.1:6006 && npm run test-storybook"
    ```_
    
    ## Fehlerbehebung
    
    ### Gemeinsame Themen
    ```bash
    # Port already in use
    npm run storybook -- --port 9001
    
    # Clear cache
    rm -rf node_modules/.cache/storybook
    
    # Webpack issues
    npm run storybook -- --no-manager-cache
    
    # TypeScript issues
    npm run storybook -- --no-dll
    
    # Memory issues
    NODE_OPTIONS="--max-old-space-size=4096" npm run storybook
    ```_
    
    ### Debug Mode
    ```bash
    # Enable debug logging
    DEBUG=storybook:* npm run storybook
    
    # Webpack debug
    npm run storybook -- --debug-webpack
    
    # Verbose output
    npm run storybook -- --verbose
    ```_
    
    ### Leistungsfragen
    ```javascript
    // .storybook/main.js
    module.exports = {
      // Disable source maps in development
      webpackFinal: async (config) => {
        if (process.env.NODE_ENV === 'development') {
          config.devtool = false;
        }
        return config;
      },
    
      // Reduce bundle size
      features: {
        storyStoreV7: true,
        buildStoriesJson: true,
      },
    };
    ```_
    
    ### Probleme erstellen
    ```bash
    # Clear all caches
    rm -rf node_modules/.cache
    rm -rf storybook-static
    npm run build-storybook
    
    # Check for conflicting dependencies
    npm ls
    
    # Update Storybook
    npx storybook@latest upgrade
    

Best Practices

Geschichte und Geschichte

  • **Hierarchische Struktur*: Verwenden Sie konsistente Namensmuster
  • Logical Grouping: Gruppenkomponenten zusammen
  • **Clear Naming*: Verwenden Sie beschreibende Geschichtennamen
  • ** Aussprache**: Umfassende Dokumentation

Komponentenentwicklung

  • Isolation: Komponenten isoliert entwickeln
  • Props Interface: Design klare, konsistente Prop-Schnittstellen
  • Standardwerte: Stellen Sie vernünftige Vorgaben vor
  • Error Handling: Handle Edge Cases anmutig

Teststrategie

  • **Visual Testing*: Verwenden Sie visuelle Regressionstests
  • ** Interaction Testing*: Testen Sie Benutzerinteraktionen
  • ** Eignungsprüfung*: Stellen Sie sicher, dass Komponenten zugänglich sind
  • **Unit Testing*: Testkomponentenlogik

Leistungsoptimierung

  • **Lazy Loading*: Verwenden Sie Story Store v7 für faules Laden
  • **Bundle Splitting*: Webpack-Konfiguration optimieren
  • Memory Management: Ressourcen richtig reinigen
  • **Build Optimization*: Bauzeiten minimieren

Team Collaboration

  • Design System: Erhalten Sie ein einheitliches Designsystem
  • ** Aussprache**: Dokumentation bis zum Datum halten
  • Code Bewertungen: Berichte und Komponenten
  • Automation: Automate-Test und Bereitstellung

--

Zusammenfassung

Storybook ist ein wesentliches Werkzeug für die moderne Frontend-Entwicklung, das ermöglicht:

  • Komponentenisolation: UI Komponenten unabhängig entwickeln und testen
  • **Visuelle Dokumentation*: Erstellen Sie lebendige Dokumentation für Designsysteme
  • Interaktive Entwicklung: Komponenten mit Echtzeit-Feedback erstellen
  • ** Testing Integration*: Visual, Interaktion und Zugänglichkeitstests
  • **Team Collaboration*: Komponenten in Teams und Stakeholdern teilen
  • Design Systemmanagement: Erhalten Sie konsistente UI-Muster

Zu den wichtigsten Vorteilen gehören schnellere Entwicklungszyklen, bessere Bauteilqualität, verbesserte Teamkollaboration und umfassende Dokumentation. Storybook unterstützt alle wichtigen Frontend-Frameworks und bietet umfangreiche Anpassungsmöglichkeiten durch Addons und Konfiguration.

<= <= <= <================================================================================= Funktion copyToClipboard() {\cHFFFF} const commands = document.querySelectorAll('code'); alle Befehle = ''; Befehle. Für jede(cmd) => alle Befehle += cmd.textContent + '\n'); navigator.clipboard.writeText (allCommands); Alarm ('Alle Befehle, die in die Zwischenablage kopiert werden!'); }

Funktion generierenPDF() { Fenster.print(); }