$npx -y skills add vibeeval/vibecosystem --skill component-library-patternsDesign system token management, component API design, Storybook, and visual regression testing patterns
| 1 | # Component Library Patterns |
| 2 | |
| 3 | ## Design Tokens |
| 4 | |
| 5 | ```typescript |
| 6 | // tokens.ts - Single source of truth |
| 7 | export const tokens = { |
| 8 | color: { |
| 9 | primary: { 50: '#eff6ff', 500: '#3b82f6', 900: '#1e3a5f' }, |
| 10 | semantic: { success: '#22c55e', error: '#ef4444', warning: '#f59e0b' } |
| 11 | }, |
| 12 | spacing: { xs: '4px', sm: '8px', md: '16px', lg: '24px', xl: '32px' }, |
| 13 | font: { |
| 14 | size: { sm: '0.875rem', base: '1rem', lg: '1.125rem', xl: '1.25rem' }, |
| 15 | weight: { normal: 400, medium: 500, semibold: 600, bold: 700 } |
| 16 | }, |
| 17 | radius: { sm: '4px', md: '8px', lg: '12px', full: '9999px' }, |
| 18 | shadow: { |
| 19 | sm: '0 1px 2px rgba(0,0,0,0.05)', |
| 20 | md: '0 4px 6px rgba(0,0,0,0.1)' |
| 21 | } |
| 22 | } as const |
| 23 | ``` |
| 24 | |
| 25 | ## Component API Design |
| 26 | |
| 27 | ```typescript |
| 28 | // Composition pattern > prop explosion |
| 29 | // YANLIS: |
| 30 | <Button icon="check" iconPosition="left" loading loadingText="..." /> |
| 31 | |
| 32 | // DOGRU: |
| 33 | <Button> |
| 34 | <Button.Icon><CheckIcon /></Button.Icon> |
| 35 | <Button.Text>Save</Button.Text> |
| 36 | <Button.Spinner /> |
| 37 | </Button> |
| 38 | |
| 39 | // Polymorphic component |
| 40 | interface ButtonProps<T extends ElementType = 'button'> { |
| 41 | as?: T |
| 42 | variant: 'primary' | 'secondary' | 'ghost' |
| 43 | size: 'sm' | 'md' | 'lg' |
| 44 | } |
| 45 | ``` |
| 46 | |
| 47 | ## Storybook Patterns |
| 48 | |
| 49 | ```typescript |
| 50 | // Component.stories.tsx |
| 51 | const meta: Meta<typeof Button> = { |
| 52 | component: Button, |
| 53 | argTypes: { |
| 54 | variant: { control: 'select', options: ['primary', 'secondary'] }, |
| 55 | size: { control: 'radio', options: ['sm', 'md', 'lg'] } |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | export const Playground: Story = { args: { variant: 'primary', children: 'Click' } } |
| 60 | export const AllVariants: Story = { |
| 61 | render: () => ( |
| 62 | <div style={{ display: 'flex', gap: 8 }}> |
| 63 | {(['primary', 'secondary', 'ghost'] as const).map(v => ( |
| 64 | <Button key={v} variant={v}>{v}</Button> |
| 65 | ))} |
| 66 | </div> |
| 67 | ) |
| 68 | } |
| 69 | ``` |
| 70 | |
| 71 | ## Visual Regression Testing |
| 72 | |
| 73 | ```typescript |
| 74 | // Chromatic veya Percy ile |
| 75 | test('Button variants match snapshot', async ({ page }) => { |
| 76 | await page.goto('/iframe.html?id=button--all-variants') |
| 77 | await expect(page).toHaveScreenshot('button-variants.png', { |
| 78 | maxDiffPixelRatio: 0.01 |
| 79 | }) |
| 80 | }) |
| 81 | ``` |
| 82 | |
| 83 | ## Theming |
| 84 | |
| 85 | ```css |
| 86 | /* CSS Custom Properties */ |
| 87 | :root { |
| 88 | --color-primary: #3b82f6; |
| 89 | --color-bg: #ffffff; |
| 90 | --color-text: #1f2937; |
| 91 | } |
| 92 | |
| 93 | [data-theme="dark"] { |
| 94 | --color-primary: #60a5fa; |
| 95 | --color-bg: #111827; |
| 96 | --color-text: #f9fafb; |
| 97 | } |
| 98 | ``` |
| 99 | |
| 100 | ## Checklist |
| 101 | |
| 102 | - [ ] Design tokens single source of truth |
| 103 | - [ ] Component API composition-based (slot pattern) |
| 104 | - [ ] Her component'te Storybook story var |
| 105 | - [ ] Visual regression test aktif |
| 106 | - [ ] Accessibility: keyboard nav + ARIA + contrast |
| 107 | - [ ] Theming: CSS variables ile dark/light |
| 108 | - [ ] Semantic versioning + CHANGELOG |
| 109 | - [ ] Prop documentation (JSDoc veya MDX) |
| 110 | - [ ] Bundle size per-component tracked |
| 111 | |
| 112 | ## Anti-Patterns |
| 113 | |
| 114 | - Prop explosion (10+ prop → composition kullan) |
| 115 | - Token'sız hardcoded değerler |
| 116 | - Component'te global CSS |
| 117 | - Story'siz component |
| 118 | - Theme switch'te flash (FOUC) |
| 119 | - Circular dependency between components |