Skip to content

Storybook to App Workflow

Overview

Storybook is for developing components in isolation. The actual components live in your codebase and are imported by both Storybook stories AND your app.

┌─────────────────────┐
│  Component File     │  ← The real component
│  Button.jsx         │
└─────────────────────┘
         ↓ imported by both
    ┌────┴────┐
    ↓         ↓
┌────────┐  ┌──────────┐
│ Story  │  │   App    │
│ .jsx   │  │  .jsx    │
└────────┘  └──────────┘

The Complete Workflow

1. Create a Component

File: src/components/Button.jsx

jsx
import React from 'react'

export default function Button({ 
  variant = 'primary', 
  children, 
  ...props 
}) {
  return (
    <button className={`btn btn-${variant}`} {...props}>
      {children}
    </button>
  )
}

2. Create a Storybook Story

File: src/components/Button.stories.jsx

jsx
import React from 'react'
import '../tailwind.css'
import '../styles.css'
import Button from './Button' // ← Import the real component

export default {
  title: 'Components/Button',
  component: Button,
  tags: ['autodocs'],
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'ghost']
    },
    children: {
      control: 'text'
    }
  }
}

export const Primary = {
  args: {
    variant: 'primary',
    children: 'Click me'
  }
}

Purpose: Develop, test, and document the component in isolation.

3. Use Component in Your App

File: src/App.jsx (or any other app file)

jsx
import React from 'react'
import Button from './components/Button' // ← Same import!

export default function App() {
  return (
    <div>
      <Button variant="primary" onClick={() => alert('Clicked!')}>
        My Button
      </Button>
    </div>
  )
}

Real Example from This Project

Icon Component

Component: src/components/Icon.jsx

jsx
export default function Icon({name, size = 16, ...props}) {
  // ... implementation
}

Story: src/components/Icon.stories.jsx

jsx
import Icon from './Icon'

export const Logo = {
  args: { name: 'logo', size: 28 }
}

Used in App: src/App.jsx

jsx
import Icon from './components/Icon'

// In render:
<Icon name="logo" size={36} />

Key Points

✅ DO:

  • Create component once in src/components/ComponentName.jsx
  • Import it in the story: import ComponentName from './ComponentName'
  • Import it in your app: import ComponentName from './components/ComponentName'
  • Develop and iterate in Storybook
  • Use the same component in your app

❌ DON'T:

  • Define components inline in story files (unless it's just for the story)
  • Copy/paste between Storybook and app
  • Maintain separate versions

Workflow Best Practices

Development Flow:

  1. Build in Storybook - Develop component with all variants

    bash
    npm run storybook
  2. Test interactively - Use Controls panel to test different props

  3. Import to app - Use the component where needed

    jsx
    import Button from './components/Button'
  4. Iterate - Make changes to the component file, see updates in both Storybook AND app

File Organization:

src/
├── components/
│   ├── Button.jsx          ← Real component
│   ├── Button.stories.jsx  ← Storybook story
│   ├── Button.test.jsx     ← Tests (optional)
│   ├── Icon.jsx
│   └── Icon.stories.jsx
├── App.jsx                 ← Uses Button and Icon
└── merchant/
    ├── Dashboard.jsx       ← Can also use Button/Icon
    └── OfferForm.jsx

Common Patterns

Pattern 1: Simple Import

jsx
// Component: src/components/Alert.jsx
export default function Alert({ type, message }) {
  return <div className={`alert-${type}`}>{message}</div>
}

// Story: src/components/Alert.stories.jsx
import Alert from './Alert'
export const Error = {
  args: { type: 'error', message: 'Something went wrong' }
}

// App: src/App.jsx
import Alert from './components/Alert'
<Alert type="error" message="Login failed" />

Pattern 2: With Multiple Exports

jsx
// Component: src/components/Card.jsx
export function Card({ children }) { /* ... */ }
export function CardHeader({ children }) { /* ... */ }
export function CardBody({ children }) { /* ... */ }

// Story: src/components/Card.stories.jsx
import { Card, CardHeader, CardBody } from './Card'

// App: src/App.jsx
import { Card, CardHeader, CardBody } from './components/Card'

Why This Workflow?

  1. Single Source of Truth - Component exists in one place
  2. Live Documentation - Storybook shows how to use each component
  3. Isolated Development - Build without worrying about app context
  4. Reusability - Same component works everywhere
  5. Team Collaboration - Designers/developers can review in Storybook

Next Steps

  • Check the updated App.jsx to see Button and Icon in action
  • Open Storybook at http://localhost:6007 to see the stories
  • Try changing Button.jsx - changes appear in both Storybook and the app!

See Also

Built with VitePress