# @cio/storybook
Storybook for ClassroomIO UI components.
## Development
To start the Storybook development server:
```bash
pnpm dev
```
## Build
To build the Storybook:
```bash
pnpm build
```
## Build Storybook
To build the Storybook (alternative command):
```bash
pnpm build-storybook
```
## Upload
To upload the built Storybook to Cloudflare R2:
```bash
pnpm upload:storybook
```
**Note:** This requires the build to be completed first. Make sure you have the following environment variables set:
- `CLOUDFLARE_ACCESS_KEY`
- `CLOUDFLARE_SECRET_ACCESS_KEY`
- `CLOUDFLARE_ACCOUNT_ID`
## Publish
To build and upload the Storybook in one command:
```bash
pnpm storybook:publish
```
This will build the Storybook and then upload it to R2.
## How to Create Storybook Stories
This guide documents the patterns and conventions for creating Storybook stories in the ClassroomIO UI component library.
### Table of Contents
- [File Structure](#file-structure)
- [Basic Story Structure](#basic-story-structure)
- [Import Patterns](#import-patterns)
- [Story Definition](#story-definition)
- [Template Snippets](#template-snippets)
- [Fields File](#fields-file)
- [Component Categorization](#component-categorization)
- [CSS Class Conventions](#css-class-conventions)
- [LMS Content Guidelines](#lms-content-guidelines)
- [Examples](#examples)
### File Structure
#### Directory Organization
Stories are organized into two main categories:
- **Atoms** (`src/atoms/`): Basic, indivisible UI components (Button, Input, Badge, etc.)
- **Molecules** (`src/molecules/`): Composite components made of multiple atoms (Card, Field, ButtonGroup, etc.)
#### File Naming
1. Create a directory matching the component name (kebab-case)
2. Create a story file: `{component-name}.stories.svelte`
3. Optionally create a fields file: `fields.ts` (for controls configuration)
**Example:**
```bash
src/molecules/hover-card/
├── hover-card.stories.svelte
└── fields.ts
```
### Basic Story Structure
Every story file follows this structure:
```svelte
{#snippet template()}
{/snippet}
```
### Import Patterns
#### Component Imports
- **Namespace imports** for multi-part components:
```svelte
import * as HoverCard from '@cio/ui/base/hover-card'; import * as Card from '@cio/ui/base/card'; import * as Field
from '@cio/ui/base/field';
```
- **Named imports** for single components:
```svelte
import {Button} from '@cio/ui/base/button'; import {Input} from '@cio/ui/base/input'; import {Avatar} from '@cio/ui/base/avatar';
```
#### Icon Imports
Use Lucide Svelte icons:
```svelte
import CalendarDaysIcon from '@lucide/svelte/icons/calendar-days'; import UsersIcon from '@lucide/svelte/icons/users';
import BookOpenIcon from '@lucide/svelte/icons/book-open';
```
### Story Definition
#### Title Format
- **Atoms**: `'Atom/ComponentName'` (e.g., `'Atom/Button'`)
- **Molecules**: `'Molecules/ComponentName'` (e.g., `'Molecules/HoverCard'`)
#### Component Reference
- For multi-part components, reference the `Root` component:
```svelte
component: HoverCard.Root component: Card.Root
```
- For single components, reference directly:
```svelte
component: Button component: Input
```
#### Parameters
Standard parameters configuration:
```svelte
parameters: {
layout: 'centered',
controls: {
include: FIELDS // Only if using fields.ts
}
}
```
#### Tags
Always include `tags: ['autodocs']` for automatic documentation generation.
### Template Snippets
#### Basic Template
```svelte
{#snippet template()}
{/snippet}
```
#### Template with Args (for controls)
For atoms that need to pass args to controls:
```svelte
{#snippet template(args)}
{/snippet}
```
#### Multiple Stories
Create multiple stories to showcase different use cases:
```svelte
{#snippet template()}
{/snippet}
{#snippet template()}
{/snippet}
{#snippet template()}
{/snippet}
```
### Fields File
Create a `fields.ts` file to control which props appear in Storybook controls:
```typescript
export const FIELDS = ['class'] as string[];
```
Common fields:
- `'class'` - CSS classes
- `'variant'` - Component variants
- `'size'` - Component sizes
- `'disabled'` - Disabled state
- Add more as needed based on component props
### Component Categorization
#### Atoms
Basic, indivisible components:
- Button, Input, Badge, Avatar, Label, Checkbox, Switch, etc.
- Single-purpose components
- Usually don't compose other components
#### Molecules
Composite components:
- Card, Field, ButtonGroup, HoverCard, Empty, etc.
- Made of multiple atoms or other components
- More complex functionality
**Guideline**: If a component uses multiple other components together, it's likely a molecule.
### CSS Class Conventions
#### UI Prefix
Use the `ui:` prefix for utility classes to scope them properly:
```svelte