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