agentskills.codes
ST

storybook

>

Install

mkdir -p .claude/skills/storybook-ghali21 && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13670" && unzip -o skill.zip -d .claude/skills/storybook-ghali21 && rm skill.zip

Installs to .claude/skills/storybook-ghali21

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Storybook story generation standards for CleanMateX web-admin. Auto-invoked when generating or reviewing .stories.tsx files for Cmx Design System components (src/ui/) or feature components (src/features/). Covers story structure, RTL stories, a11y, mock patterns, and naming conventions. This file is the authoritative reference loaded by the storybook-generator agent before writing any story file.
399 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)

About this skill

Storybook Skill — CleanMateX

Scope

This skill ownsNot this skill
.stories.tsx file structure and contentComponent logic or props design → /frontend
RTL story variantsWhich RTL Tailwind classes to use → /frontend
Mock data and decorator patternsi18n translation keys → /i18n
Story naming and file placement conventionsJSDoc on the component itself → /code-documentation
Storybook commandsBuild/dev commands → /dev-commands

Mandatory Rules

  1. Every component in src/ui/ must have a .stories.tsx file — no exceptions.
  2. tags: ['autodocs'] on every meta — required for auto-generated docs page.
  3. Always include an RTL story for any component that has visible text or directional layout.
  4. parameters: { layout: 'centered' } for atomic components; 'fullscreen' for layout/page components.
  5. Never import from @/components/ui or @ui/compat — use @ui/primitives, @ui/feedback, etc.
  6. No real API calls, auth, or DB access in stories — use static mock data and decorators.
  7. Story file lives alongside the componentCmxButton.stories.tsx next to cmx-button.tsx.

Story File Structure

import type { Meta, StoryObj } from '@storybook/nextjs'
import { fn } from 'storybook/test'
// Import component using @ui/* path alias
import { CmxButton } from '@ui/primitives'

// ─── Meta ─────────────────────────────────────────────────────────────────────

const meta = {
  title: 'Primitives/CmxButton',   // Category/ComponentName — see Naming below
  component: CmxButton,
  parameters: {
    layout: 'centered',             // 'centered' | 'fullscreen' | 'padded'
  },
  tags: ['autodocs'],               // Required — generates API docs page
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'ghost', 'outline', 'destructive'],
      description: 'Visual style variant',
    },
    size: {
      control: 'select',
      options: ['xs', 'sm', 'md', 'lg'],
    },
    loading: { control: 'boolean' },
    disabled: { control: 'boolean' },
    onClick: { action: 'clicked' },  // or fn() for interaction tests
  },
  args: {
    // Default args shared by all stories — override per story
    children: 'Button',
    onClick: fn(),
  },
} satisfies Meta<typeof CmxButton>

export default meta
type Story = StoryObj<typeof meta>

// ─── Stories ──────────────────────────────────────────────────────────────────

export const Primary: Story = {
  args: { variant: 'primary', children: 'Save Order' },
}

export const Destructive: Story = {
  args: { variant: 'destructive', children: 'Delete' },
}

export const Loading: Story = {
  args: { loading: true, children: 'Saving…' },
}

export const Disabled: Story = {
  args: { disabled: true, children: 'Unavailable' },
}

// RTL story — required for any component with text or directional layout
export const RTL: Story = {
  args: { children: 'حفظ الطلب' },
  parameters: { direction: 'rtl' },   // activates dir="rtl" via preview.ts decorator
}

Naming Conventions

title field — Category/ComponentName

Source directoryCategory prefix
src/ui/primitives/Primitives/
src/ui/feedback/Feedback/
src/ui/forms/Forms/
src/ui/data-display/DataDisplay/
src/ui/navigation/Navigation/
src/ui/overlays/Overlays/
src/features/**/Features/FeatureName/

Export names (story variants)

Use PascalCase descriptive names — they appear as tabs in Storybook:

Default, Primary, Secondary, Ghost, Outline, Destructive
Loading, Disabled, WithIcon, WithError, WithHelpText
Small, Medium, Large
RTL                   ← always this exact name for Arabic layout stories
AllVariants           ← when showing a grid of all variants in one story
Playground            ← interactive story with all controls exposed

Per-Component Story Checklist

Primitives

CmxButton — stories: Primary, Secondary, Ghost, Outline, Destructive, Loading, Disabled, AllSizes, RTL

CmxInput — stories: Default, WithLabel, WithError, WithHelpText, WithLeftIcon, WithRightIcon, Disabled, RTL

CmxTextarea — stories: Default, WithLabel, WithError, Disabled, RTL

CmxSelect — stories: Default, WithLabel, WithError, Disabled, RTL

CmxCheckbox — stories: Default, Checked, Indeterminate, Disabled, WithLabel, RTL

CmxSwitch — stories: Default, Checked, Disabled, WithLabel, RTL

CmxSpinner — stories: Default, AllSizes

CmxCard — stories: Default, WithHeader, WithFooter, WithAll, RTL

Feedback

CmxStatusBadge — stories: AllVariants (grid), WithIcon, Pulse, AllSizes, RTL

CmxProgressBar — stories: Default, InProgress, Complete, RTL

CmxProgressIndicator — stories: Default, WithSteps, RTL

CmxSummaryMessage — stories: Success, Error, Warning, Info, RTL

CmxConfirmDialog — stories: Default, Open (use decorator to control open state), RTL

Forms

CmxForm — stories: Default (with CmxFormField children), WithValidation, RTL

CmxFormField — stories: Default, WithError, Required, RTL

CmxSelectDropdown — stories: Default, WithOptions, Disabled, RTL

CmxCheckboxGroup — stories: Default, WithPreselected, RTL

Data Display

CmxDataTable — stories: Default (with sample columns+data), Loading, Empty, WithPagination, RTL

CmxKpiStatCard — stories: Default, WithTrend, AllVariants, RTL

CmxEmptyState — stories: Default, WithAction, RTL

CmxProcessingStepTimeline — stories: Default, InProgress, Completed, RTL

Navigation

CmxTabsPanel — stories: Default, WithBadge, RTL

CmxProgressSteps — stories: Default, Step2Active, Completed, RTL

CmxLanguageSwitcher — stories: Default (no auth needed — static toggle)

Overlays

CmxDialog — stories: Default (closed), Open (use useState decorator), WithForm, RTL


RTL Stories — Pattern

The Storybook toolbar already has a Direction toggle (configured in .storybook/preview.ts). The RTL story sets it to 'rtl' by default so reviewers see Arabic layout immediately:

export const RTL: Story = {
  name: 'RTL (Arabic)',
  args: {
    // Use real Arabic text — not Lorem Ipsum
    label: 'رقم الطلب',
    placeholder: 'أدخل رقم الطلب',
  },
  parameters: {
    direction: 'rtl',   // passed to preview.ts decorator → sets document.documentElement.dir
  },
}

Real Arabic text to use in stories:

ContextArabic
Button saveحفظ
Button cancelإلغاء
Button deleteحذف
Button submitإرسال
Input labelرقم الطلب
Input placeholderأدخل القيمة
Search placeholderبحث...
Status: activeنشط
Status: processingقيد المعالجة
Status: completedمكتمل
Status: cancelledملغى
Table headerالاسم
Empty state titleلا توجد نتائج
Dialog titleتأكيد الحذف

Mock Data Patterns

Static table data

// Mock data for CmxDataTable stories — no API call
const mockOrders = [
  { id: '1001', customer: 'Ahmed Al-Rashid', status: 'NEW', total: 45.00 },
  { id: '1002', customer: 'Sarah Johnson', status: 'IN_PROGRESS', total: 128.50 },
  { id: '1003', customer: 'Mohammed Ali', status: 'COMPLETED', total: 67.25 },
]

const mockColumns: ColumnDef<typeof mockOrders[0]>[] = [
  { accessorKey: 'id', header: 'Order #' },
  { accessorKey: 'customer', header: 'Customer' },
  { accessorKey: 'status', header: 'Status' },
  { accessorKey: 'total', header: 'Total' },
]

Controlled open state (Dialog, Confirm)

// Decorator to control open/close state for overlay components
export const Open: Story = {
  decorators: [
    (StoryComponent) => {
      const [open, setOpen] = React.useState(true)
      return <StoryComponent args={{ open, onOpenChange: setOpen }} />
    },
  ],
}

Icon usage

import { CheckCircle, AlertTriangle, Info } from 'lucide-react'
// Pass Lucide icon components directly — they match LucideIcon type
args: { icon: CheckCircle, showIcon: true }

a11y Requirements

Every story must pass Storybook's @storybook/addon-a11y panel (no red violations). Common rules:

  • Interactive elements must have accessible labels (aria-label or visible text)
  • Form inputs must be linked to labels (CmxInput handles this automatically via id)
  • Color is not the only indicator of state (status badges use both color + text)
  • Focus ring must be visible in keyboard nav (handled by Cmx theme tokens)

Stories that intentionally test accessibility edge cases:

export const A11yMinimal: Story = {
  name: 'A11y: icon-only button',
  args: { children: <SearchIcon />, 'aria-label': 'Search orders' },
}

Story Generation Workflow (for the agent)

When generating stories for a component, follow this sequence:

  1. Read the component file — extract props interface, variant values, default props
  2. Identify story set — use the per-component checklist above; add extras if component has unique behavior
  3. Write the meta block — correct title category, full argTypes, shared args
  4. Write each story — one export per variant, use real-world content (not "foo", "test")
  5. Add RTL story — always, for any component with visible text
  6. Verify imports — use @ui/* paths, never @/components/ui or @ui/compat
  7. Check play functions — add for interactive stories (form submit, dialog open/close, etc.)

Commands

cd web-admin

npm run storybook          # Dev server → localhost:6006 (hot reload)
npm run docs:storybook     # Static build → docs/storybook/
npm run docs:generate      # TypeDoc + Storybook static build together

File Placement

src/ui/primitives/
  cmx-button.tsx
  CmxButton.stories.tsx    ← story lives next to component

src/ui/feedback/
  cmx-status-badge.tsx
  CmxStatusBadge.stories.tsx

src/features/orders/
  OrderCard.tsx
  Order

---

*Content truncated.*

Search skills

Search the agent skills registry