@equal-experts/kuat-react 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,523 @@
1
+ # Kuat Design System Color Guide
2
+
3
+ A guide to using colors in the Kuat Design System. This document helps ensure consistent, accessible, and brand-compliant color usage across all digital products built with shadcn/ui and shadcn-vue.
4
+
5
+ ---
6
+
7
+ ## Brand Colors
8
+
9
+ The Kuat Design System is built around four core brand color palettes, each with a specific purpose and meaning. Understanding when and how to use these colors is essential for maintaining brand consistency.
10
+
11
+ ### Primary Brand Color: EE Blue
12
+
13
+ **EE Blue** (`--brand-ee-blue`) is the primary brand color, representing trust, professionalism, and technology. It's used for:
14
+
15
+ - **Primary actions:** Main buttons, links, and call-to-action elements
16
+ - **Brand identity:** Logos, headers, and key brand elements
17
+ - **Navigation:** Active states, selected items, and primary navigation
18
+ - **Focus states:** Focus rings and active indicators
19
+
20
+ **Color Value:** `oklch(0.645 0.163 237.5)` - A vibrant, professional blue
21
+
22
+ **Usage Guidelines:**
23
+ - Use as the `primary` semantic token for main actions
24
+ - Always pair with `primary-foreground` (white) for text on EE Blue backgrounds
25
+ - Use lighter shades (50-200) for subtle backgrounds and accents
26
+ - Use darker shades (700-950) for depth and contrast in dark mode
27
+
28
+ ### Secondary Brand Color: Transform Teal
29
+
30
+ **Transform Teal** (`--brand-transform-teal`) represents transformation, growth, and innovation. It's used for:
31
+
32
+ - **Secondary actions:** Alternative buttons and secondary call-to-actions
33
+ - **Accent elements:** Highlights, badges, and secondary information
34
+ - **Progressive states:** Success indicators, positive feedback, and growth metrics
35
+
36
+ **Color Value:** `oklch(0.645 0.120 185.0)` - A fresh, modern teal
37
+
38
+ **Usage Guidelines:**
39
+ - Use as the `secondary` semantic token for secondary actions
40
+ - Always pair with `secondary-foreground` (white) for text on Transform Teal backgrounds
41
+ - Works well for data visualization and chart elements
42
+ - Use sparingly to maintain visual hierarchy
43
+
44
+ ### Supporting Brand Color: Tech Blue
45
+
46
+ **Tech Blue** (`--brand-tech-blue`) is a deeper, more technical blue used for:
47
+
48
+ - **Sidebar navigation:** Primary sidebar backgrounds and navigation elements
49
+ - **Technical interfaces:** Developer tools, technical documentation, and code-related UI
50
+ - **Depth and structure:** Cards and containers in dark mode
51
+
52
+ **Color Value:** `oklch(0.435 0.090 240.0)` - A sophisticated, technical blue
53
+
54
+ **Usage Guidelines:**
55
+ - Primarily used for sidebar components (`--sidebar`)
56
+ - Works well in dark mode for card backgrounds (`--card` in dark mode)
57
+ - Use darker shades (700-950) for depth and contrast
58
+ - Maintains technical, professional aesthetic
59
+
60
+ ### Accent Brand Color: Equal Ember
61
+
62
+ **Equal Ember** (`--brand-equal-ember`) is a warm, energetic orange used for:
63
+
64
+ - **Special highlights:** Important notices, warnings, and attention-grabbing elements
65
+ - **Energy and warmth:** Adding personality and warmth to the interface
66
+ - **Status indicators:** Warning states and special notifications
67
+
68
+ **Color Value:** `oklch(0.625 0.200 65.0)` - A vibrant, energetic orange
69
+
70
+ **Usage Guidelines:**
71
+ - Use sparingly for maximum impact
72
+ - Best for warning states and special highlights
73
+ - Not used in default semantic tokens, but available for custom use cases
74
+ - Maintains brand warmth and energy
75
+
76
+ ### Brand Color Palette Structure
77
+
78
+ Each brand color palette includes a full scale from 50 (lightest) to 950 (darkest), providing flexibility for various use cases:
79
+
80
+ - **50-200:** Light backgrounds, subtle accents, and hover states
81
+ - **300-500:** Primary brand colors and main actions
82
+ - **600-800:** Darker variants for depth and contrast
83
+ - **900-950:** Maximum depth for dark mode and high contrast
84
+
85
+ All brand colors are available as CSS variables: `--ee-blue-*`, `--tech-blue-*`, `--transform-teal-*`, `--equal-ember-*`
86
+
87
+ ---
88
+
89
+ ## Color Specification
90
+
91
+ ### Semantic Color Tokens
92
+
93
+ The design system uses **semantic color tokens** that map brand colors to UI purposes. This abstraction allows for consistent theming while maintaining brand identity.
94
+
95
+ | Token | CSS Variable | Brand Color Source | Tailwind Class | Usage |
96
+ |-------|-------------|-------------------|----------------|-------|
97
+ | Background | `--background` | White (light) / Slate-900 (dark) | `bg-background` | Page and component backgrounds |
98
+ | Foreground | `--foreground` | Slate-950 (light) / White (dark) | `text-foreground` | Primary text color |
99
+ | Primary | `--primary` | EE Blue 500 | `bg-primary`, `text-primary` | Primary brand color, main actions |
100
+ | Primary Foreground | `--primary-foreground` | White | `text-primary-foreground` | Text on primary backgrounds |
101
+ | Secondary | `--secondary` | Transform Teal 500 | `bg-secondary`, `text-secondary` | Secondary brand color |
102
+ | Secondary Foreground | `--secondary-foreground` | White | `text-secondary-foreground` | Text on secondary backgrounds |
103
+ | Muted | `--muted` | Slate-100 | `bg-muted` | Subtle backgrounds, disabled states |
104
+ | Muted Foreground | `--muted-foreground` | Slate-500 (light) / Slate-300 (dark) | `text-muted-foreground` | Secondary text, hints, metadata |
105
+ | Accent | `--accent` | EE Blue 50 (light) / EE Blue 800 (dark) | `bg-accent`, `text-accent` | Accent color for highlights |
106
+ | Accent Foreground | `--accent-foreground` | Slate-950 | `text-accent-foreground` | Text on accent backgrounds |
107
+ | Destructive | `--destructive` | Red-600 | `bg-destructive`, `text-destructive` | Error states, destructive actions |
108
+ | Destructive Foreground | `--destructive-foreground` | White | `text-destructive-foreground` | Text on destructive backgrounds |
109
+ | Border | `--border` | Slate-200 (light) / Slate-700 (dark) | `border-border` | Borders, dividers, outlines |
110
+ | Input | `--input` | White (light) / Slate-600 (dark) | `border-input` | Input field borders |
111
+ | Ring | `--ring` | Slate-300 | `ring-ring` | Focus rings, active states |
112
+
113
+ ### Component-Specific Colors
114
+
115
+ #### Card Colors
116
+ - **Card:** `--card` - White (light) / Tech Blue 800 (dark)
117
+ - **Card Foreground:** `--card-foreground` - Slate-950
118
+
119
+ #### Popover Colors
120
+ - **Popover:** `--popover` - Black
121
+ - **Popover Foreground:** `--popover-foreground` - White
122
+
123
+ #### Sidebar Colors
124
+ - **Sidebar:** `--sidebar` - Tech Blue 500 (light) / Tech Blue 700 (dark)
125
+ - **Sidebar Foreground:** `--sidebar-foreground` - White
126
+ - **Sidebar Primary:** `--sidebar-primary` - EE Blue 500
127
+ - **Sidebar Primary Foreground:** `--sidebar-primary-foreground` - EE Blue 50
128
+ - **Sidebar Accent:** `--sidebar-accent` - Slate-200 (light) / EE Blue 700 (dark)
129
+ - **Sidebar Accent Foreground:** `--sidebar-accent-foreground` - Tech Blue 500
130
+ - **Sidebar Border:** `--sidebar-border` - Slate-200
131
+ - **Sidebar Ring:** `--sidebar-ring` - Slate-100
132
+
133
+ #### Chart Colors
134
+ - **Chart 1:** `--chart-1` - Blue (`#1f77b4`)
135
+ - **Chart 2:** `--chart-2` - Orange (`#ff7f0e`)
136
+ - **Chart 3:** `--chart-3` - Green (`#2ca02c`)
137
+ - **Chart 4:** `--chart-4` - Red (`#d62728`)
138
+ - **Chart 5:** `--chart-5` - Purple (`#9467bd`)
139
+
140
+ ### Color Format
141
+
142
+ All colors in the design system use the **oklch** color space for better color manipulation and consistency. OKLCH provides:
143
+
144
+ - **Perceptual uniformity:** Equal changes in values correspond to equal changes in perception
145
+ - **Better color manipulation:** Easier to create consistent color scales
146
+ - **Future-proof:** Modern CSS color format with excellent browser support
147
+
148
+ **Example:**
149
+ ```css
150
+ --primary: oklch(0.645 0.163 237.5);
151
+ /* Lightness: 0.645, Chroma: 0.163, Hue: 237.5° */
152
+ ```
153
+
154
+ ### Light and Dark Mode
155
+
156
+ All semantic tokens automatically adapt to light and dark modes. The system uses:
157
+
158
+ - **Light Mode:** Defined in `:root` selector
159
+ - **Dark Mode:** Defined in `.dark` selector
160
+
161
+ Color values switch automatically when the `.dark` class is applied to the root element.
162
+
163
+ ---
164
+
165
+ ## Usage Guidelines
166
+
167
+ ### Using Colors in Components
168
+
169
+ #### React Components
170
+
171
+ ```tsx
172
+ // Using Tailwind classes (recommended)
173
+ <div className="bg-background text-foreground border-border">
174
+ <button className="bg-primary text-primary-foreground hover:bg-primary/90">
175
+ Primary Action
176
+ </button>
177
+ <button className="bg-secondary text-secondary-foreground">
178
+ Secondary Action
179
+ </button>
180
+ <p className="text-muted-foreground">Secondary text</p>
181
+ <div className="border-destructive text-destructive">Error message</div>
182
+ </div>
183
+ ```
184
+
185
+ #### Vue Components
186
+
187
+ ```vue
188
+ <template>
189
+ <div class="bg-background text-foreground border-border">
190
+ <button class="bg-primary text-primary-foreground hover:bg-primary/90">
191
+ Primary Action
192
+ </button>
193
+ <button class="bg-secondary text-secondary-foreground">
194
+ Secondary Action
195
+ </button>
196
+ <p class="text-muted-foreground">Secondary text</p>
197
+ <div class="border-destructive text-destructive">Error message</div>
198
+ </div>
199
+ </template>
200
+ ```
201
+
202
+ #### Using CSS Variables Directly
203
+
204
+ ```css
205
+ .custom-element {
206
+ background-color: var(--background);
207
+ color: var(--foreground);
208
+ border-color: var(--border);
209
+ }
210
+ ```
211
+
212
+ **Note:** Colors are defined in oklch format, so they work directly with CSS variables. No conversion needed.
213
+
214
+ ### Component-Specific Color Usage
215
+
216
+ #### Buttons
217
+
218
+ **Primary Button:**
219
+ - Background: `bg-primary` (EE Blue)
220
+ - Text: `text-primary-foreground` (White)
221
+ - Hover: `hover:bg-primary/90` (90% opacity)
222
+ - Active: `active:bg-primary/80` (80% opacity)
223
+ - Disabled: `disabled:opacity-50`
224
+
225
+ ```tsx
226
+ <button className="bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50">
227
+ Primary Button
228
+ </button>
229
+ ```
230
+
231
+ **Secondary Button:**
232
+ - Background: `bg-secondary` (Transform Teal)
233
+ - Text: `text-secondary-foreground` (White)
234
+ - Hover: `hover:bg-secondary/90`
235
+
236
+ ```tsx
237
+ <button className="bg-secondary text-secondary-foreground hover:bg-secondary/90">
238
+ Secondary Button
239
+ </button>
240
+ ```
241
+
242
+ **Destructive Button:**
243
+ - Background: `bg-destructive` (Red-600)
244
+ - Text: `text-destructive-foreground` (White)
245
+ - Hover: `hover:bg-destructive/90`
246
+
247
+ ```tsx
248
+ <button className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
249
+ Delete
250
+ </button>
251
+ ```
252
+
253
+ #### Links
254
+
255
+ **Default Link:**
256
+ - Color: `text-primary` (EE Blue)
257
+ - Hover: `hover:underline` or `hover:text-primary/80`
258
+
259
+ ```tsx
260
+ <a href="#" className="text-primary hover:underline">
261
+ Link text
262
+ </a>
263
+ ```
264
+
265
+ #### Form Inputs
266
+
267
+ **Input Field:**
268
+ - Background: `bg-background`
269
+ - Border: `border-input`
270
+ - Focus Ring: `ring-ring`
271
+ - Text: `text-foreground`
272
+
273
+ ```tsx
274
+ <input className="bg-background border-input text-foreground focus:ring-ring" />
275
+ ```
276
+
277
+ #### Cards
278
+
279
+ **Card Component:**
280
+ - Background: `bg-card`
281
+ - Text: `text-card-foreground`
282
+ - Border: `border-border`
283
+
284
+ ```tsx
285
+ <div className="bg-card text-card-foreground border-border rounded-lg p-4">
286
+ Card content
287
+ </div>
288
+ ```
289
+
290
+ #### Status Indicators
291
+
292
+ **Error:**
293
+ - Color: `text-destructive`
294
+ - Background: `bg-destructive/10` (10% opacity)
295
+
296
+ ```tsx
297
+ <div className="bg-destructive/10 text-destructive border-destructive">
298
+ Error message
299
+ </div>
300
+ ```
301
+
302
+ **Info:**
303
+ - Color: `text-primary`
304
+ - Background: `bg-primary/10`
305
+
306
+ ```tsx
307
+ <div className="bg-primary/10 text-primary border-primary">
308
+ Information
309
+ </div>
310
+ ```
311
+
312
+ ### Dark Mode
313
+
314
+ All colors automatically adapt to dark mode when the `.dark` class is applied to the root element.
315
+
316
+ **Enabling Dark Mode:**
317
+
318
+ ```tsx
319
+ // Add dark class to root element
320
+ <html className="dark">
321
+ {/* content */}
322
+ </html>
323
+ ```
324
+
325
+ **Dark Mode Behavior:**
326
+ - Background switches from white to slate-900
327
+ - Foreground switches from slate-950 to white
328
+ - Brand colors (primary, secondary) remain consistent
329
+ - Supporting colors (muted, border) adapt for better contrast
330
+ - All semantic tokens automatically switch
331
+
332
+ ### Accessibility
333
+
334
+ The design system adheres to **WCAG AA accessibility standards** for color contrast:
335
+
336
+ - **Normal text (14px and below):** Minimum contrast ratio of **4.5:1**
337
+ - **Large text (18px+ or 14px+ bold):** Minimum contrast ratio of **3:1**
338
+
339
+ **Approved Color Combinations:**
340
+
341
+ ✅ **Text on Backgrounds:**
342
+ - `text-foreground` on `bg-background` - Meets WCAG AA
343
+ - `text-primary-foreground` on `bg-primary` - Meets WCAG AA
344
+ - `text-secondary-foreground` on `bg-secondary` - Meets WCAG AA
345
+ - `text-muted-foreground` on `bg-muted` - Meets WCAG AA
346
+ - `text-destructive-foreground` on `bg-destructive` - Meets WCAG AA
347
+
348
+ ✅ **Borders:**
349
+ - `border-border` provides sufficient contrast on `bg-background`
350
+ - `border-input` provides sufficient contrast for form fields
351
+
352
+ **Testing Contrast:**
353
+
354
+ Always test color combinations to ensure they meet accessibility standards. Use tools like:
355
+ - [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
356
+ - Browser DevTools accessibility features
357
+ - Automated accessibility testing tools
358
+
359
+ ### Best Practices
360
+
361
+ #### ✅ Do's
362
+
363
+ 1. **Use semantic color tokens**
364
+ - ✅ Always use CSS variables or Tailwind classes (`bg-primary`, `text-foreground`)
365
+ - ✅ Use `-foreground` variants for text on colored backgrounds
366
+ - ✅ Leverage automatic dark mode support
367
+
368
+ 2. **Maintain brand consistency**
369
+ - ✅ Use `primary` (EE Blue) for main brand actions
370
+ - ✅ Use `secondary` (Transform Teal) for secondary actions
371
+ - ✅ Use brand colors consistently across the application
372
+ - ✅ Respect the brand color hierarchy
373
+
374
+ 3. **Ensure accessibility**
375
+ - ✅ Always use foreground variants on colored backgrounds
376
+ - ✅ Test contrast ratios meet WCAG AA standards
377
+ - ✅ Don't rely solely on color to convey information
378
+
379
+ 4. **Use opacity modifiers**
380
+ - ✅ Use Tailwind opacity utilities (`/90`, `/50`, `/10`) for hover states
381
+ - ✅ Example: `hover:bg-primary/90` for 90% opacity
382
+
383
+ 5. **Follow component patterns**
384
+ - ✅ Use shadcn/ui component color patterns
385
+ - ✅ Maintain consistent color relationships across states
386
+
387
+ #### ❌ Don'ts
388
+
389
+ 1. **Don't hardcode colors**
390
+ - ❌ Don't use hex values directly (`#1795d4`)
391
+ - ❌ Don't use RGB values directly
392
+ - ❌ Don't create custom color values outside the token system
393
+
394
+ 2. **Don't ignore semantic tokens**
395
+ - ❌ Don't use `text-foreground` on `bg-primary` (use `text-primary-foreground`)
396
+ - ❌ Don't mix color systems (don't combine tokens with hardcoded colors)
397
+
398
+ 3. **Don't break accessibility**
399
+ - ❌ Don't use low-contrast combinations
400
+ - ❌ Don't rely solely on color to convey information
401
+ - ❌ Don't ignore dark mode considerations
402
+
403
+ 4. **Don't misuse brand colors**
404
+ - ❌ Don't use brand colors in ways that conflict with their meaning
405
+ - ❌ Don't create custom variations of brand colors
406
+ - ❌ Don't use brand colors for non-brand purposes
407
+
408
+ 5. **Don't create custom color variations**
409
+ - ❌ Don't modify color tokens without updating `@equal-experts/kuat-core`
410
+ - ❌ Don't create new color tokens outside the system
411
+
412
+ ### Examples
413
+
414
+ #### ✅ Good: Using Semantic Tokens
415
+
416
+ ```tsx
417
+ // React
418
+ <div className="bg-background text-foreground">
419
+ <h1 className="text-primary">Heading</h1>
420
+ <p className="text-muted-foreground">Secondary text</p>
421
+ <button className="bg-primary text-primary-foreground hover:bg-primary/90">
422
+ Action
423
+ </button>
424
+ </div>
425
+ ```
426
+
427
+ ```vue
428
+ <!-- Vue -->
429
+ <template>
430
+ <div class="bg-background text-foreground">
431
+ <h1 class="text-primary">Heading</h1>
432
+ <p class="text-muted-foreground">Secondary text</p>
433
+ <button class="bg-primary text-primary-foreground hover:bg-primary/90">
434
+ Action
435
+ </button>
436
+ </div>
437
+ </template>
438
+ ```
439
+
440
+ #### ❌ Bad: Hardcoded Colors
441
+
442
+ ```tsx
443
+ // Don't do this
444
+ <div style={{ backgroundColor: '#ffffff', color: '#020617' }}>
445
+ <button style={{ backgroundColor: '#1795d4', color: '#ffffff' }}>
446
+ Action
447
+ </button>
448
+ </div>
449
+ ```
450
+
451
+ #### ✅ Good: Accessible Color Combinations
452
+
453
+ ```tsx
454
+ // Proper foreground/background pairing
455
+ <button className="bg-primary text-primary-foreground">
456
+ Primary Action
457
+ </button>
458
+
459
+ <div className="bg-destructive text-destructive-foreground">
460
+ Error Message
461
+ </div>
462
+ ```
463
+
464
+ #### ❌ Bad: Inaccessible Combinations
465
+
466
+ ```tsx
467
+ // Wrong - using foreground on primary background
468
+ <button className="bg-primary text-foreground">
469
+ Action
470
+ </button>
471
+
472
+ // Should be:
473
+ <button className="bg-primary text-primary-foreground">
474
+ Action
475
+ </button>
476
+ ```
477
+
478
+ ---
479
+
480
+ ## Modifying Colors
481
+
482
+ To modify colors in the design system:
483
+
484
+ 1. **Edit `@equal-experts/kuat-core/src/variables.css`**
485
+ - Update the oklch values in `:root` (light mode)
486
+ - Update the oklch values in `.dark` (dark mode)
487
+ - Maintain brand color relationships
488
+
489
+ 2. **Rebuild packages**
490
+ ```bash
491
+ pnpm build
492
+ ```
493
+
494
+ 3. **Test accessibility**
495
+ - Verify contrast ratios meet WCAG AA standards
496
+ - Test in both light and dark modes
497
+ - Ensure brand consistency is maintained
498
+
499
+ 4. **Update documentation**
500
+ - Update this file if color meanings change
501
+ - Update component examples if needed
502
+
503
+ ---
504
+
505
+ ## Additional Resources
506
+
507
+ - **Design System Overview:** See [design-system.md](./design-system.md) for complete design system documentation
508
+ - **Typography Guide:** See [typography.md](./typography.md) for text color usage
509
+ - **Component Guidelines:** See [../technical/component-guidelines.md](../technical/component-guidelines.md) for component color patterns
510
+ - **shadcn/ui Colors:** [shadcn/ui Theming Documentation](https://ui.shadcn.com/docs/theming)
511
+ - **Tailwind Colors:** [Tailwind CSS Color Documentation](https://tailwindcss.com/docs/customizing-colors)
512
+
513
+ ---
514
+
515
+ ## Notes
516
+
517
+ - **Color Format:** Colors use oklch format for better color manipulation and consistency
518
+ - **CSS Variables:** All colors are available as CSS variables in `@equal-experts/kuat-core/src/variables.css`
519
+ - **Tailwind Integration:** Colors are exposed via Tailwind utility classes
520
+ - **Dark Mode:** All colors automatically adapt when `.dark` class is applied
521
+ - **Accessibility:** All color combinations are designed to meet WCAG AA standards
522
+ - **Semantic Tokens:** Always use semantic color names rather than specific color values
523
+ - **Brand First:** Brand colors guide the system; semantic tokens provide the implementation layer
@@ -0,0 +1,148 @@
1
+ # Kuat Design System - Agent Documentation
2
+
3
+ ## Overview
4
+
5
+ The Kuat Design System is a monorepo containing component libraries for both React and Vue, sharing a common design token system through `@equal-experts/kuat-core`.
6
+
7
+ ## Design Tokens
8
+
9
+ All design tokens are centralized in `@equal-experts/kuat-core/src/variables.css`:
10
+
11
+ ### Color System
12
+ - Uses HSL color format for better manipulation
13
+ - Supports light and dark modes via CSS variables
14
+ - Semantic color names: `background`, `foreground`, `primary`, `secondary`, `muted`, `accent`, `destructive`
15
+ - Chart colors: `chart-1` through `chart-5`
16
+
17
+ ### Spacing & Layout
18
+ - Border radius: `--radius` (default: 0.5rem)
19
+ - Responsive breakpoints follow Tailwind defaults
20
+
21
+ ### Usage in Components
22
+
23
+ ```tsx
24
+ // React example
25
+ <div className="bg-background text-foreground border-border">
26
+ <button className="bg-primary text-primary-foreground">
27
+ Click me
28
+ </button>
29
+ </div>
30
+ ```
31
+
32
+ ```vue
33
+ <!-- Vue example -->
34
+ <template>
35
+ <div class="bg-background text-foreground border-border">
36
+ <button class="bg-primary text-primary-foreground">
37
+ Click me
38
+ </button>
39
+ </div>
40
+ </template>
41
+ ```
42
+
43
+ ## Component Patterns
44
+
45
+ ### React Components (shadcn/ui)
46
+
47
+ Components follow shadcn/ui patterns:
48
+ - Built on Radix UI primitives
49
+ - Styled with Tailwind CSS
50
+ - Use `cn()` utility for className merging
51
+ - Support variants via `class-variance-authority`
52
+
53
+ Example structure:
54
+ ```tsx
55
+ import { cn } from "@/lib/utils"
56
+ import { cva, type VariantProps } from "class-variance-authority"
57
+
58
+ const buttonVariants = cva(
59
+ "inline-flex items-center justify-center rounded-md",
60
+ {
61
+ variants: {
62
+ variant: {
63
+ default: "bg-primary text-primary-foreground",
64
+ // ...
65
+ }
66
+ }
67
+ }
68
+ )
69
+ ```
70
+
71
+ ### Vue Components (shadcn-vue)
72
+
73
+ Components follow shadcn-vue patterns:
74
+ - Built on Radix Vue primitives
75
+ - Styled with Tailwind CSS
76
+ - Use `cn()` utility for className merging
77
+ - Support variants via `class-variance-authority`
78
+
79
+ Example structure:
80
+ ```vue
81
+ <script setup lang="ts">
82
+ import { cn } from "@/lib/utils"
83
+ import { cva, type VariantProps } from "class-variance-authority"
84
+
85
+ const buttonVariants = cva(/* ... */)
86
+ </script>
87
+
88
+ <template>
89
+ <button :class="cn(buttonVariants({ variant }), $attrs.class)">
90
+ <slot />
91
+ </button>
92
+ </template>
93
+ ```
94
+
95
+ ## Theming
96
+
97
+ The design system supports light and dark modes through CSS variables:
98
+
99
+ ```css
100
+ :root {
101
+ /* Light mode variables */
102
+ }
103
+
104
+ .dark {
105
+ /* Dark mode variables */
106
+ }
107
+ ```
108
+
109
+ To enable dark mode, add the `dark` class to the root element.
110
+
111
+ ## Accessibility
112
+
113
+ All components should:
114
+ - Use semantic HTML elements
115
+ - Support keyboard navigation
116
+ - Include proper ARIA attributes
117
+ - Follow WCAG 2.1 AA standards
118
+ - Work with screen readers
119
+
120
+ Radix UI/Vue primitives provide accessibility features out of the box.
121
+
122
+ ## Best Practices
123
+
124
+ 1. **Always use design tokens** - Don't hardcode colors or spacing
125
+ 2. **Use the `cn()` utility** - For conditional and merged classNames
126
+ 3. **Follow component patterns** - Maintain consistency with existing components
127
+ 4. **Export from index.ts** - Make components available via package exports
128
+ 5. **Type everything** - Use TypeScript for all components
129
+ 6. **Document props** - Use JSDoc comments for component APIs
130
+
131
+ ## Common Utilities
132
+
133
+ ### `cn()` Function
134
+ Located in `src/lib/utils.ts` in each package:
135
+ ```ts
136
+ import { clsx } from "clsx"
137
+ import { twMerge } from "tailwind-merge"
138
+
139
+ export function cn(...inputs: ClassValue[]) {
140
+ return twMerge(clsx(inputs))
141
+ }
142
+ ```
143
+
144
+ This utility:
145
+ - Merges classNames conditionally
146
+ - Resolves Tailwind class conflicts (last one wins)
147
+ - Handles undefined/null values gracefully
148
+