omgkit 2.2.0 → 2.3.0

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.
Files changed (55) hide show
  1. package/package.json +1 -1
  2. package/plugin/skills/databases/mongodb/SKILL.md +60 -776
  3. package/plugin/skills/databases/prisma/SKILL.md +53 -744
  4. package/plugin/skills/databases/redis/SKILL.md +53 -860
  5. package/plugin/skills/devops/aws/SKILL.md +68 -672
  6. package/plugin/skills/devops/github-actions/SKILL.md +54 -657
  7. package/plugin/skills/devops/kubernetes/SKILL.md +67 -602
  8. package/plugin/skills/devops/performance-profiling/SKILL.md +59 -863
  9. package/plugin/skills/frameworks/django/SKILL.md +87 -853
  10. package/plugin/skills/frameworks/express/SKILL.md +95 -1301
  11. package/plugin/skills/frameworks/fastapi/SKILL.md +90 -1198
  12. package/plugin/skills/frameworks/laravel/SKILL.md +87 -1187
  13. package/plugin/skills/frameworks/nestjs/SKILL.md +106 -973
  14. package/plugin/skills/frameworks/react/SKILL.md +94 -962
  15. package/plugin/skills/frameworks/vue/SKILL.md +95 -1242
  16. package/plugin/skills/frontend/accessibility/SKILL.md +91 -1056
  17. package/plugin/skills/frontend/frontend-design/SKILL.md +69 -1262
  18. package/plugin/skills/frontend/responsive/SKILL.md +76 -799
  19. package/plugin/skills/frontend/shadcn-ui/SKILL.md +73 -921
  20. package/plugin/skills/frontend/tailwindcss/SKILL.md +60 -788
  21. package/plugin/skills/frontend/threejs/SKILL.md +72 -1266
  22. package/plugin/skills/languages/javascript/SKILL.md +106 -849
  23. package/plugin/skills/methodology/brainstorming/SKILL.md +70 -576
  24. package/plugin/skills/methodology/defense-in-depth/SKILL.md +79 -831
  25. package/plugin/skills/methodology/dispatching-parallel-agents/SKILL.md +81 -654
  26. package/plugin/skills/methodology/executing-plans/SKILL.md +86 -529
  27. package/plugin/skills/methodology/finishing-development-branch/SKILL.md +95 -586
  28. package/plugin/skills/methodology/problem-solving/SKILL.md +67 -681
  29. package/plugin/skills/methodology/receiving-code-review/SKILL.md +70 -533
  30. package/plugin/skills/methodology/requesting-code-review/SKILL.md +70 -610
  31. package/plugin/skills/methodology/root-cause-tracing/SKILL.md +70 -646
  32. package/plugin/skills/methodology/sequential-thinking/SKILL.md +70 -478
  33. package/plugin/skills/methodology/systematic-debugging/SKILL.md +66 -559
  34. package/plugin/skills/methodology/test-driven-development/SKILL.md +91 -752
  35. package/plugin/skills/methodology/testing-anti-patterns/SKILL.md +78 -687
  36. package/plugin/skills/methodology/token-optimization/SKILL.md +72 -602
  37. package/plugin/skills/methodology/verification-before-completion/SKILL.md +108 -529
  38. package/plugin/skills/methodology/writing-plans/SKILL.md +79 -566
  39. package/plugin/skills/omega/omega-architecture/SKILL.md +91 -752
  40. package/plugin/skills/omega/omega-coding/SKILL.md +161 -552
  41. package/plugin/skills/omega/omega-sprint/SKILL.md +132 -777
  42. package/plugin/skills/omega/omega-testing/SKILL.md +157 -845
  43. package/plugin/skills/omega/omega-thinking/SKILL.md +165 -606
  44. package/plugin/skills/security/better-auth/SKILL.md +46 -1034
  45. package/plugin/skills/security/oauth/SKILL.md +80 -934
  46. package/plugin/skills/security/owasp/SKILL.md +78 -862
  47. package/plugin/skills/testing/playwright/SKILL.md +77 -700
  48. package/plugin/skills/testing/pytest/SKILL.md +73 -811
  49. package/plugin/skills/testing/vitest/SKILL.md +60 -920
  50. package/plugin/skills/tools/document-processing/SKILL.md +111 -838
  51. package/plugin/skills/tools/image-processing/SKILL.md +126 -659
  52. package/plugin/skills/tools/mcp-development/SKILL.md +85 -758
  53. package/plugin/skills/tools/media-processing/SKILL.md +118 -735
  54. package/plugin/stdrules/SKILL_STANDARDS.md +490 -0
  55. package/plugin/skills/SKILL_STANDARDS.md +0 -743
@@ -1,374 +1,48 @@
1
1
  ---
2
- name: tailwindcss
3
- description: Tailwind CSS utility-first styling with responsive design, dark mode, animations, and component patterns
4
- category: frontend
5
- triggers:
6
- - tailwind
7
- - tailwindcss
8
- - utility classes
9
- - css framework
10
- - styling
2
+ name: styling-with-tailwind
3
+ description: Claude styles UIs with Tailwind CSS utility classes, responsive design, and dark mode support. Use when creating component styles, theming systems, or responsive layouts.
11
4
  ---
12
5
 
13
- # Tailwind CSS
6
+ # Styling with Tailwind CSS
14
7
 
15
- Enterprise-grade **utility-first CSS framework** following industry best practices. This skill covers responsive design, dark mode, custom configurations, animations, component patterns, and optimization strategies used by top engineering teams.
16
-
17
- ## Purpose
18
-
19
- Build beautiful, responsive UIs efficiently:
20
-
21
- - Write utility-first CSS
22
- - Implement responsive designs
23
- - Configure dark mode theming
24
- - Create reusable component patterns
25
- - Customize design tokens
26
- - Optimize for production
27
- - Build accessible interfaces
28
-
29
- ## Features
30
-
31
- ### 1. Configuration Setup
32
-
33
- ```javascript
34
- // tailwind.config.js
35
- /** @type {import('tailwindcss').Config} */
36
- module.exports = {
37
- content: [
38
- "./src/**/*.{js,ts,jsx,tsx,mdx}",
39
- "./components/**/*.{js,ts,jsx,tsx}",
40
- "./app/**/*.{js,ts,jsx,tsx}",
41
- ],
42
- darkMode: "class", // or 'media'
43
- theme: {
44
- extend: {
45
- // Custom colors
46
- colors: {
47
- primary: {
48
- 50: "#eff6ff",
49
- 100: "#dbeafe",
50
- 200: "#bfdbfe",
51
- 300: "#93c5fd",
52
- 400: "#60a5fa",
53
- 500: "#3b82f6",
54
- 600: "#2563eb",
55
- 700: "#1d4ed8",
56
- 800: "#1e40af",
57
- 900: "#1e3a8a",
58
- 950: "#172554",
59
- },
60
- secondary: {
61
- 50: "#f8fafc",
62
- // ... other shades
63
- },
64
- },
65
- // Custom spacing
66
- spacing: {
67
- "18": "4.5rem",
68
- "88": "22rem",
69
- "128": "32rem",
70
- },
71
- // Custom fonts
72
- fontFamily: {
73
- sans: ["Inter", "system-ui", "sans-serif"],
74
- mono: ["JetBrains Mono", "monospace"],
75
- },
76
- // Custom font sizes
77
- fontSize: {
78
- "2xs": ["0.625rem", { lineHeight: "0.75rem" }],
79
- },
80
- // Custom border radius
81
- borderRadius: {
82
- "4xl": "2rem",
83
- },
84
- // Custom animations
85
- animation: {
86
- "fade-in": "fadeIn 0.3s ease-in-out",
87
- "slide-up": "slideUp 0.3s ease-out",
88
- "spin-slow": "spin 3s linear infinite",
89
- "pulse-slow": "pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite",
90
- },
91
- keyframes: {
92
- fadeIn: {
93
- "0%": { opacity: "0" },
94
- "100%": { opacity: "1" },
95
- },
96
- slideUp: {
97
- "0%": { transform: "translateY(10px)", opacity: "0" },
98
- "100%": { transform: "translateY(0)", opacity: "1" },
99
- },
100
- },
101
- // Custom box shadows
102
- boxShadow: {
103
- "soft": "0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)",
104
- "inner-soft": "inset 0 2px 4px 0 rgba(0, 0, 0, 0.05)",
105
- },
106
- // Custom breakpoints
107
- screens: {
108
- "xs": "475px",
109
- "3xl": "1920px",
110
- },
111
- },
112
- },
113
- plugins: [
114
- require("@tailwindcss/forms"),
115
- require("@tailwindcss/typography"),
116
- require("@tailwindcss/aspect-ratio"),
117
- require("@tailwindcss/container-queries"),
118
- ],
119
- };
120
- ```
121
-
122
- ```css
123
- /* globals.css */
124
- @tailwind base;
125
- @tailwind components;
126
- @tailwind utilities;
127
-
128
- @layer base {
129
- :root {
130
- --background: 0 0% 100%;
131
- --foreground: 222.2 84% 4.9%;
132
- --primary: 221.2 83.2% 53.3%;
133
- --primary-foreground: 210 40% 98%;
134
- --secondary: 210 40% 96.1%;
135
- --secondary-foreground: 222.2 47.4% 11.2%;
136
- --muted: 210 40% 96.1%;
137
- --muted-foreground: 215.4 16.3% 46.9%;
138
- --accent: 210 40% 96.1%;
139
- --accent-foreground: 222.2 47.4% 11.2%;
140
- --destructive: 0 84.2% 60.2%;
141
- --destructive-foreground: 210 40% 98%;
142
- --border: 214.3 31.8% 91.4%;
143
- --input: 214.3 31.8% 91.4%;
144
- --ring: 221.2 83.2% 53.3%;
145
- --radius: 0.5rem;
146
- }
147
-
148
- .dark {
149
- --background: 222.2 84% 4.9%;
150
- --foreground: 210 40% 98%;
151
- --primary: 217.2 91.2% 59.8%;
152
- --primary-foreground: 222.2 47.4% 11.2%;
153
- --secondary: 217.2 32.6% 17.5%;
154
- --secondary-foreground: 210 40% 98%;
155
- --muted: 217.2 32.6% 17.5%;
156
- --muted-foreground: 215 20.2% 65.1%;
157
- --accent: 217.2 32.6% 17.5%;
158
- --accent-foreground: 210 40% 98%;
159
- --destructive: 0 62.8% 30.6%;
160
- --destructive-foreground: 210 40% 98%;
161
- --border: 217.2 32.6% 17.5%;
162
- --input: 217.2 32.6% 17.5%;
163
- --ring: 224.3 76.3% 48%;
164
- }
165
- }
166
-
167
- @layer base {
168
- * {
169
- @apply border-border;
170
- }
171
- body {
172
- @apply bg-background text-foreground;
173
- }
174
- }
175
- ```
176
-
177
- ### 2. Component Patterns
8
+ ## Quick Start
178
9
 
179
10
  ```tsx
180
- // Button component with variants
181
- interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
182
- variant?: "primary" | "secondary" | "outline" | "ghost" | "destructive";
183
- size?: "sm" | "md" | "lg";
184
- loading?: boolean;
185
- }
186
-
187
- export function Button({
188
- variant = "primary",
189
- size = "md",
190
- loading,
191
- className,
192
- children,
193
- disabled,
194
- ...props
195
- }: ButtonProps) {
196
- const baseStyles = `
197
- inline-flex items-center justify-center
198
- font-medium rounded-lg
199
- transition-colors duration-200
200
- focus:outline-none focus:ring-2 focus:ring-offset-2
201
- disabled:opacity-50 disabled:cursor-not-allowed
202
- `;
203
-
11
+ // Button with variants using utility classes
12
+ export function Button({ variant = 'primary', size = 'md', children }: ButtonProps) {
13
+ const base = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50';
204
14
  const variants = {
205
- primary: `
206
- bg-primary-600 text-white
207
- hover:bg-primary-700
208
- focus:ring-primary-500
209
- `,
210
- secondary: `
211
- bg-secondary-100 text-secondary-900
212
- hover:bg-secondary-200
213
- focus:ring-secondary-500
214
- dark:bg-secondary-800 dark:text-secondary-100
215
- `,
216
- outline: `
217
- border-2 border-primary-600 text-primary-600
218
- hover:bg-primary-50
219
- focus:ring-primary-500
220
- dark:border-primary-400 dark:text-primary-400
221
- `,
222
- ghost: `
223
- text-gray-700 hover:bg-gray-100
224
- focus:ring-gray-500
225
- dark:text-gray-300 dark:hover:bg-gray-800
226
- `,
227
- destructive: `
228
- bg-red-600 text-white
229
- hover:bg-red-700
230
- focus:ring-red-500
231
- `,
232
- };
233
-
234
- const sizes = {
235
- sm: "px-3 py-1.5 text-sm gap-1.5",
236
- md: "px-4 py-2 text-base gap-2",
237
- lg: "px-6 py-3 text-lg gap-2.5",
15
+ primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500',
16
+ outline: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50 focus:ring-blue-500',
17
+ ghost: 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-800',
238
18
  };
19
+ const sizes = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2', lg: 'px-6 py-3 text-lg' };
239
20
 
240
21
  return (
241
- <button
242
- className={`${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`}
243
- disabled={disabled || loading}
244
- {...props}
245
- >
246
- {loading && (
247
- <svg
248
- className="animate-spin h-4 w-4"
249
- xmlns="http://www.w3.org/2000/svg"
250
- fill="none"
251
- viewBox="0 0 24 24"
252
- >
253
- <circle
254
- className="opacity-25"
255
- cx="12"
256
- cy="12"
257
- r="10"
258
- stroke="currentColor"
259
- strokeWidth="4"
260
- />
261
- <path
262
- className="opacity-75"
263
- fill="currentColor"
264
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
265
- />
266
- </svg>
267
- )}
22
+ <button className={`${base} ${variants[variant]} ${sizes[size]}`}>
268
23
  {children}
269
24
  </button>
270
25
  );
271
26
  }
27
+ ```
272
28
 
273
- // Card component
274
- interface CardProps {
275
- children: React.ReactNode;
276
- className?: string;
277
- hoverable?: boolean;
278
- }
279
-
280
- export function Card({ children, className, hoverable }: CardProps) {
281
- return (
282
- <div
283
- className={`
284
- bg-white dark:bg-gray-800
285
- rounded-xl shadow-soft
286
- border border-gray-200 dark:border-gray-700
287
- ${hoverable ? "hover:shadow-lg hover:-translate-y-1 transition-all duration-200" : ""}
288
- ${className}
289
- `}
290
- >
291
- {children}
292
- </div>
293
- );
294
- }
295
-
296
- export function CardHeader({ children, className }: { children: React.ReactNode; className?: string }) {
297
- return (
298
- <div className={`px-6 py-4 border-b border-gray-200 dark:border-gray-700 ${className}`}>
299
- {children}
300
- </div>
301
- );
302
- }
303
-
304
- export function CardContent({ children, className }: { children: React.ReactNode; className?: string }) {
305
- return <div className={`px-6 py-4 ${className}`}>{children}</div>;
306
- }
307
-
308
- export function CardFooter({ children, className }: { children: React.ReactNode; className?: string }) {
309
- return (
310
- <div className={`px-6 py-4 border-t border-gray-200 dark:border-gray-700 ${className}`}>
311
- {children}
312
- </div>
313
- );
314
- }
315
-
316
- // Input component
317
- interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
318
- label?: string;
319
- error?: string;
320
- hint?: string;
321
- }
29
+ ## Features
322
30
 
323
- export function Input({ label, error, hint, className, id, ...props }: InputProps) {
324
- const inputId = id || label?.toLowerCase().replace(/\s/g, "-");
31
+ | Feature | Description | Guide |
32
+ |---------|-------------|-------|
33
+ | Configuration | Extend colors, fonts, spacing, animations | `ref/config.md` |
34
+ | Responsive Design | Mobile-first breakpoints: sm, md, lg, xl, 2xl | `ref/responsive.md` |
35
+ | Dark Mode | Class-based dark mode with `dark:` prefix | `ref/dark-mode.md` |
36
+ | Custom Animations | Define keyframes and animation utilities | `ref/animations.md` |
37
+ | CSS Variables | Theme with CSS custom properties | `ref/theming.md` |
38
+ | Plugins | @tailwindcss/forms, typography, container-queries | `ref/plugins.md` |
325
39
 
326
- return (
327
- <div className="space-y-1">
328
- {label && (
329
- <label
330
- htmlFor={inputId}
331
- className="block text-sm font-medium text-gray-700 dark:text-gray-300"
332
- >
333
- {label}
334
- {props.required && <span className="text-red-500 ml-1">*</span>}
335
- </label>
336
- )}
337
- <input
338
- id={inputId}
339
- className={`
340
- w-full px-4 py-2
341
- border rounded-lg
342
- bg-white dark:bg-gray-800
343
- text-gray-900 dark:text-gray-100
344
- placeholder-gray-400 dark:placeholder-gray-500
345
- transition-colors duration-200
346
- focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent
347
- disabled:bg-gray-100 disabled:cursor-not-allowed
348
- ${error
349
- ? "border-red-500 focus:ring-red-500"
350
- : "border-gray-300 dark:border-gray-600"
351
- }
352
- ${className}
353
- `}
354
- {...props}
355
- />
356
- {hint && !error && (
357
- <p className="text-sm text-gray-500 dark:text-gray-400">{hint}</p>
358
- )}
359
- {error && (
360
- <p className="text-sm text-red-500 dark:text-red-400">{error}</p>
361
- )}
362
- </div>
363
- );
364
- }
365
- ```
40
+ ## Common Patterns
366
41
 
367
- ### 3. Responsive Design
42
+ ### Responsive Card Grid
368
43
 
369
44
  ```tsx
370
- // Responsive layout patterns
371
- export function ResponsiveGrid({ children }: { children: React.ReactNode }) {
45
+ export function CardGrid({ children }: { children: React.ReactNode }) {
372
46
  return (
373
47
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6">
374
48
  {children}
@@ -376,473 +50,71 @@ export function ResponsiveGrid({ children }: { children: React.ReactNode }) {
376
50
  );
377
51
  }
378
52
 
379
- // Responsive navigation
380
- export function Navigation() {
381
- return (
382
- <nav className="bg-white dark:bg-gray-900 shadow-sm">
383
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
384
- <div className="flex justify-between h-16">
385
- {/* Logo */}
386
- <div className="flex-shrink-0 flex items-center">
387
- <Logo className="h-8 w-auto" />
388
- </div>
389
-
390
- {/* Desktop navigation */}
391
- <div className="hidden md:flex md:items-center md:space-x-8">
392
- <NavLink href="/">Home</NavLink>
393
- <NavLink href="/products">Products</NavLink>
394
- <NavLink href="/about">About</NavLink>
395
- <NavLink href="/contact">Contact</NavLink>
396
- </div>
397
-
398
- {/* Mobile menu button */}
399
- <div className="flex items-center md:hidden">
400
- <button
401
- className="
402
- inline-flex items-center justify-center
403
- p-2 rounded-md
404
- text-gray-400 hover:text-gray-500 hover:bg-gray-100
405
- focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary-500
406
- "
407
- >
408
- <span className="sr-only">Open main menu</span>
409
- <MenuIcon className="h-6 w-6" />
410
- </button>
411
- </div>
412
- </div>
413
- </div>
414
-
415
- {/* Mobile menu */}
416
- <div className="md:hidden">
417
- <div className="px-2 pt-2 pb-3 space-y-1">
418
- <MobileNavLink href="/">Home</MobileNavLink>
419
- <MobileNavLink href="/products">Products</MobileNavLink>
420
- <MobileNavLink href="/about">About</MobileNavLink>
421
- <MobileNavLink href="/contact">Contact</MobileNavLink>
422
- </div>
423
- </div>
424
- </nav>
425
- );
426
- }
427
-
428
- // Responsive hero section
429
- export function Hero() {
53
+ export function Card({ children, hoverable }: { children: React.ReactNode; hoverable?: boolean }) {
430
54
  return (
431
- <section className="relative bg-gray-900 overflow-hidden">
432
- {/* Background pattern */}
433
- <div className="absolute inset-0 bg-gradient-to-br from-primary-600 to-primary-900 opacity-90" />
434
-
435
- <div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24 sm:py-32 lg:py-40">
436
- <div className="text-center lg:text-left lg:max-w-2xl">
437
- {/* Responsive typography */}
438
- <h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold text-white tracking-tight">
439
- Build amazing products
440
- <span className="block text-primary-300 mt-2">with confidence</span>
441
- </h1>
442
-
443
- <p className="mt-6 text-lg sm:text-xl text-gray-300 max-w-xl mx-auto lg:mx-0">
444
- Start building your next project with our comprehensive component
445
- library and design system.
446
- </p>
447
-
448
- {/* Responsive button layout */}
449
- <div className="mt-10 flex flex-col sm:flex-row gap-4 justify-center lg:justify-start">
450
- <Button size="lg" className="w-full sm:w-auto">
451
- Get Started
452
- </Button>
453
- <Button variant="outline" size="lg" className="w-full sm:w-auto">
454
- Learn More
455
- </Button>
456
- </div>
457
- </div>
458
- </div>
459
- </section>
55
+ <div className={cn(
56
+ 'bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6',
57
+ hoverable && 'hover:shadow-lg hover:-translate-y-1 transition-all duration-200'
58
+ )}>
59
+ {children}
60
+ </div>
460
61
  );
461
62
  }
462
63
  ```
463
64
 
464
- ### 4. Dark Mode
65
+ ### Dark Mode Toggle
465
66
 
466
67
  ```tsx
467
- // Dark mode toggle
468
- import { useEffect, useState } from "react";
469
-
470
68
  export function DarkModeToggle() {
471
69
  const [isDark, setIsDark] = useState(false);
472
70
 
473
71
  useEffect(() => {
474
- // Check initial preference
475
- const isDarkMode =
476
- localStorage.getItem("theme") === "dark" ||
477
- (!localStorage.getItem("theme") &&
478
- window.matchMedia("(prefers-color-scheme: dark)").matches);
479
- setIsDark(isDarkMode);
480
- document.documentElement.classList.toggle("dark", isDarkMode);
72
+ const dark = localStorage.theme === 'dark' ||
73
+ (!localStorage.theme && window.matchMedia('(prefers-color-scheme: dark)').matches);
74
+ setIsDark(dark);
75
+ document.documentElement.classList.toggle('dark', dark);
481
76
  }, []);
482
77
 
483
- const toggleDarkMode = () => {
484
- const newIsDark = !isDark;
485
- setIsDark(newIsDark);
486
- document.documentElement.classList.toggle("dark", newIsDark);
487
- localStorage.setItem("theme", newIsDark ? "dark" : "light");
78
+ const toggle = () => {
79
+ setIsDark(!isDark);
80
+ document.documentElement.classList.toggle('dark', !isDark);
81
+ localStorage.theme = !isDark ? 'dark' : 'light';
488
82
  };
489
83
 
490
84
  return (
491
- <button
492
- onClick={toggleDarkMode}
493
- className="
494
- p-2 rounded-lg
495
- text-gray-500 hover:text-gray-700
496
- dark:text-gray-400 dark:hover:text-gray-200
497
- hover:bg-gray-100 dark:hover:bg-gray-800
498
- transition-colors duration-200
499
- "
500
- aria-label={isDark ? "Switch to light mode" : "Switch to dark mode"}
501
- >
502
- {isDark ? (
503
- <SunIcon className="h-5 w-5" />
504
- ) : (
505
- <MoonIcon className="h-5 w-5" />
506
- )}
85
+ <button onClick={toggle} className="p-2 rounded-lg text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800">
86
+ {isDark ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
507
87
  </button>
508
88
  );
509
89
  }
510
-
511
- // Dark mode aware components
512
- export function DarkModeCard({ title, description }: { title: string; description: string }) {
513
- return (
514
- <div
515
- className="
516
- p-6 rounded-xl
517
- bg-white dark:bg-gray-800
518
- border border-gray-200 dark:border-gray-700
519
- shadow-sm hover:shadow-md
520
- transition-shadow duration-200
521
- "
522
- >
523
- <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
524
- {title}
525
- </h3>
526
- <p className="mt-2 text-gray-600 dark:text-gray-300">
527
- {description}
528
- </p>
529
- </div>
530
- );
531
- }
532
90
  ```
533
91
 
534
- ### 5. Animation Patterns
92
+ ### Conditional Classes with cn()
535
93
 
536
94
  ```tsx
537
- // Animated components
538
- export function AnimatedCard({ children, delay = 0 }: { children: React.ReactNode; delay?: number }) {
539
- return (
540
- <div
541
- className="animate-slide-up opacity-0"
542
- style={{
543
- animationDelay: `${delay}ms`,
544
- animationFillMode: "forwards",
545
- }}
546
- >
547
- {children}
548
- </div>
549
- );
550
- }
551
-
552
- // Hover animations
553
- export function HoverCard({ children }: { children: React.ReactNode }) {
554
- return (
555
- <div
556
- className="
557
- group
558
- relative
559
- bg-white dark:bg-gray-800
560
- rounded-xl shadow-sm
561
- transition-all duration-300
562
- hover:shadow-xl hover:-translate-y-2
563
- cursor-pointer
564
- "
565
- >
566
- {/* Gradient overlay on hover */}
567
- <div
568
- className="
569
- absolute inset-0 rounded-xl
570
- bg-gradient-to-br from-primary-500/0 to-primary-500/0
571
- group-hover:from-primary-500/5 group-hover:to-primary-500/10
572
- transition-all duration-300
573
- "
574
- />
575
- <div className="relative z-10">{children}</div>
576
- </div>
577
- );
578
- }
579
-
580
- // Loading skeleton
581
- export function Skeleton({ className }: { className?: string }) {
582
- return (
583
- <div
584
- className={`
585
- animate-pulse
586
- bg-gray-200 dark:bg-gray-700
587
- rounded
588
- ${className}
589
- `}
590
- />
591
- );
592
- }
593
-
594
- export function CardSkeleton() {
595
- return (
596
- <div className="p-6 bg-white dark:bg-gray-800 rounded-xl">
597
- <Skeleton className="h-6 w-3/4 mb-4" />
598
- <Skeleton className="h-4 w-full mb-2" />
599
- <Skeleton className="h-4 w-5/6 mb-2" />
600
- <Skeleton className="h-4 w-4/6" />
601
- <div className="mt-6 flex gap-2">
602
- <Skeleton className="h-10 w-24" />
603
- <Skeleton className="h-10 w-24" />
604
- </div>
605
- </div>
606
- );
607
- }
608
-
609
- // Transition group
610
- export function FadeTransition({ show, children }: { show: boolean; children: React.ReactNode }) {
611
- return (
612
- <div
613
- className={`
614
- transition-all duration-300 ease-in-out
615
- ${show ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-4 pointer-events-none"}
616
- `}
617
- >
618
- {children}
619
- </div>
620
- );
621
- }
622
- ```
623
-
624
- ### 6. Utility Class Patterns
625
-
626
- ```tsx
627
- // Using clsx/cn for conditional classes
628
- import { clsx, type ClassValue } from "clsx";
629
- import { twMerge } from "tailwind-merge";
95
+ import { clsx, type ClassValue } from 'clsx';
96
+ import { twMerge } from 'tailwind-merge';
630
97
 
631
98
  export function cn(...inputs: ClassValue[]) {
632
99
  return twMerge(clsx(inputs));
633
100
  }
634
101
 
635
102
  // Usage
636
- interface BadgeProps {
637
- variant?: "default" | "success" | "warning" | "error";
638
- children: React.ReactNode;
639
- className?: string;
640
- }
641
-
642
- export function Badge({ variant = "default", children, className }: BadgeProps) {
643
- return (
644
- <span
645
- className={cn(
646
- "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
647
- {
648
- "bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200":
649
- variant === "default",
650
- "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200":
651
- variant === "success",
652
- "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200":
653
- variant === "warning",
654
- "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200":
655
- variant === "error",
656
- },
657
- className
658
- )}
659
- >
660
- {children}
661
- </span>
662
- );
663
- }
664
-
665
- // Responsive spacing utility
666
- export function Stack({
667
- children,
668
- spacing = "md",
669
- direction = "vertical",
670
- }: {
671
- children: React.ReactNode;
672
- spacing?: "sm" | "md" | "lg";
673
- direction?: "vertical" | "horizontal";
674
- }) {
675
- const spacingClasses = {
676
- sm: direction === "vertical" ? "space-y-2" : "space-x-2",
677
- md: direction === "vertical" ? "space-y-4" : "space-x-4",
678
- lg: direction === "vertical" ? "space-y-6" : "space-x-6",
679
- };
680
-
681
- return (
682
- <div
683
- className={cn(
684
- direction === "horizontal" && "flex items-center",
685
- spacingClasses[spacing]
686
- )}
687
- >
688
- {children}
689
- </div>
690
- );
691
- }
692
- ```
693
-
694
- ### 7. Form Patterns
695
-
696
- ```tsx
697
- // Complete form example
698
- export function ContactForm() {
699
- return (
700
- <form className="space-y-6">
701
- <div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
702
- <Input
703
- label="First Name"
704
- name="firstName"
705
- placeholder="John"
706
- required
707
- />
708
- <Input
709
- label="Last Name"
710
- name="lastName"
711
- placeholder="Doe"
712
- required
713
- />
714
- </div>
715
-
716
- <Input
717
- label="Email"
718
- name="email"
719
- type="email"
720
- placeholder="john@example.com"
721
- required
722
- />
723
-
724
- <div className="space-y-1">
725
- <label
726
- htmlFor="message"
727
- className="block text-sm font-medium text-gray-700 dark:text-gray-300"
728
- >
729
- Message
730
- </label>
731
- <textarea
732
- id="message"
733
- name="message"
734
- rows={4}
735
- className="
736
- w-full px-4 py-2
737
- border border-gray-300 dark:border-gray-600
738
- rounded-lg
739
- bg-white dark:bg-gray-800
740
- text-gray-900 dark:text-gray-100
741
- placeholder-gray-400 dark:placeholder-gray-500
742
- focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent
743
- resize-none
744
- "
745
- placeholder="Your message..."
746
- />
747
- </div>
748
-
749
- <div className="flex items-center">
750
- <input
751
- id="terms"
752
- name="terms"
753
- type="checkbox"
754
- className="
755
- h-4 w-4
756
- rounded
757
- border-gray-300
758
- text-primary-600
759
- focus:ring-primary-500
760
- "
761
- />
762
- <label
763
- htmlFor="terms"
764
- className="ml-2 text-sm text-gray-600 dark:text-gray-400"
765
- >
766
- I agree to the{" "}
767
- <a href="/terms" className="text-primary-600 hover:underline">
768
- terms and conditions
769
- </a>
770
- </label>
771
- </div>
772
-
773
- <Button type="submit" className="w-full sm:w-auto">
774
- Send Message
775
- </Button>
776
- </form>
777
- );
778
- }
779
- ```
780
-
781
- ## Use Cases
782
-
783
- ### Responsive Dashboard Layout
784
-
785
- ```tsx
786
- export function DashboardLayout({ children }: { children: React.ReactNode }) {
787
- return (
788
- <div className="min-h-screen bg-gray-50 dark:bg-gray-900">
789
- {/* Sidebar */}
790
- <aside
791
- className="
792
- fixed inset-y-0 left-0
793
- z-50 w-64
794
- bg-white dark:bg-gray-800
795
- border-r border-gray-200 dark:border-gray-700
796
- transform -translate-x-full lg:translate-x-0
797
- transition-transform duration-300
798
- "
799
- >
800
- {/* Sidebar content */}
801
- </aside>
802
-
803
- {/* Main content */}
804
- <main className="lg:pl-64">
805
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
806
- {children}
807
- </div>
808
- </main>
809
- </div>
810
- );
811
- }
103
+ <div className={cn(
104
+ 'px-4 py-2 rounded-lg',
105
+ isActive && 'bg-blue-500 text-white',
106
+ isDisabled && 'opacity-50 cursor-not-allowed',
107
+ className
108
+ )} />
812
109
  ```
813
110
 
814
111
  ## Best Practices
815
112
 
816
- ### Do's
817
-
818
- - Use mobile-first responsive design
819
- - Leverage utility composition
820
- - Create reusable component patterns
821
- - Use CSS variables for theming
822
- - Implement dark mode properly
823
- - Use the cn() utility for conditional classes
824
- - Configure purge/content correctly
825
- - Use semantic class grouping
826
- - Optimize for production build
827
- - Follow consistent spacing scales
828
-
829
- ### Don'ts
830
-
831
- - Don't overuse @apply
832
- - Don't create overly specific utilities
833
- - Don't ignore accessibility
834
- - Don't repeat complex class combinations
835
- - Don't hardcode colors outside theme
836
- - Don't skip responsive testing
837
- - Don't forget dark mode variants
838
- - Don't use arbitrary values excessively
839
- - Don't ignore the configuration file
840
- - Don't mix styling paradigms
841
-
842
- ## References
843
-
844
- - [Tailwind CSS Documentation](https://tailwindcss.com/docs)
845
- - [Tailwind UI](https://tailwindui.com/)
846
- - [Headless UI](https://headlessui.com/)
847
- - [Tailwind CSS Best Practices](https://tailwindcss.com/docs/reusing-styles)
848
- - [Tailwind CSS Plugins](https://tailwindcss.com/docs/plugins)
113
+ | Do | Avoid |
114
+ |----|-------|
115
+ | Use mobile-first responsive design | Overusing @apply (prefer utilities) |
116
+ | Leverage `cn()` for conditional classes | Hardcoding colors outside theme |
117
+ | Configure content paths for purging | Using arbitrary values excessively |
118
+ | Use CSS variables for theming | Mixing styling paradigms |
119
+ | Group related utilities semantically | Skipping dark mode variants |
120
+ | Use consistent spacing scales | Ignoring responsive testing |