@0xsown/vibe-code-fe 1.0.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.
- package/bin/index.js +181 -0
- package/package.json +32 -0
- package/skills/claude-md-improver/SKILL.md +179 -0
- package/skills/claude-md-improver/references/quality-criteria.md +109 -0
- package/skills/claude-md-improver/references/templates.md +253 -0
- package/skills/claude-md-improver/references/update-guidelines.md +150 -0
- package/skills/find-skills/SKILL.md +133 -0
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/next-best-practices/SKILL.md +153 -0
- package/skills/next-best-practices/async-patterns.md +87 -0
- package/skills/next-best-practices/bundling.md +180 -0
- package/skills/next-best-practices/data-patterns.md +297 -0
- package/skills/next-best-practices/debug-tricks.md +105 -0
- package/skills/next-best-practices/directives.md +73 -0
- package/skills/next-best-practices/error-handling.md +227 -0
- package/skills/next-best-practices/file-conventions.md +140 -0
- package/skills/next-best-practices/font.md +245 -0
- package/skills/next-best-practices/functions.md +108 -0
- package/skills/next-best-practices/hydration-error.md +91 -0
- package/skills/next-best-practices/image.md +173 -0
- package/skills/next-best-practices/metadata.md +301 -0
- package/skills/next-best-practices/parallel-routes.md +287 -0
- package/skills/next-best-practices/route-handlers.md +146 -0
- package/skills/next-best-practices/rsc-boundaries.md +159 -0
- package/skills/next-best-practices/runtime-selection.md +39 -0
- package/skills/next-best-practices/scripts.md +141 -0
- package/skills/next-best-practices/self-hosting.md +371 -0
- package/skills/next-best-practices/suspense-boundaries.md +67 -0
- package/skills/next-cache-components/SKILL.md +411 -0
- package/skills/shadcn-ui/README.md +248 -0
- package/skills/shadcn-ui/SKILL.md +326 -0
- package/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
- package/skills/shadcn-ui/examples/data-table.tsx +313 -0
- package/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
- package/skills/shadcn-ui/resources/component-catalog.md +481 -0
- package/skills/shadcn-ui/resources/customization-guide.md +516 -0
- package/skills/shadcn-ui/resources/migration-guide.md +463 -0
- package/skills/shadcn-ui/resources/setup-guide.md +412 -0
- package/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
- package/skills/supabase-postgres-best-practices/AGENTS.md +68 -0
- package/skills/supabase-postgres-best-practices/CLAUDE.md +68 -0
- package/skills/supabase-postgres-best-practices/README.md +116 -0
- package/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/skills/supabase-postgres-best-practices/references/security-rls-performance.md +57 -0
- package/skills/tailwind-design-system/SKILL.md +874 -0
- package/skills/vercel-composition-patterns/AGENTS.md +946 -0
- package/skills/vercel-composition-patterns/README.md +60 -0
- package/skills/vercel-composition-patterns/SKILL.md +89 -0
- package/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/vercel-composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/vercel-composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/vercel-composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/vercel-react-best-practices/AGENTS.md +2934 -0
- package/skills/vercel-react-best-practices/README.md +123 -0
- package/skills/vercel-react-best-practices/SKILL.md +136 -0
- package/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/skills/vercel-react-native-skills/AGENTS.md +2897 -0
- package/skills/vercel-react-native-skills/README.md +165 -0
- package/skills/vercel-react-native-skills/SKILL.md +121 -0
- package/skills/vercel-react-native-skills/rules/animation-derived-value.md +53 -0
- package/skills/vercel-react-native-skills/rules/animation-gesture-detector-press.md +95 -0
- package/skills/vercel-react-native-skills/rules/animation-gpu-properties.md +65 -0
- package/skills/vercel-react-native-skills/rules/design-system-compound-components.md +66 -0
- package/skills/vercel-react-native-skills/rules/fonts-config-plugin.md +71 -0
- package/skills/vercel-react-native-skills/rules/imports-design-system-folder.md +68 -0
- package/skills/vercel-react-native-skills/rules/js-hoist-intl.md +61 -0
- package/skills/vercel-react-native-skills/rules/list-performance-callbacks.md +44 -0
- package/skills/vercel-react-native-skills/rules/list-performance-function-references.md +132 -0
- package/skills/vercel-react-native-skills/rules/list-performance-images.md +53 -0
- package/skills/vercel-react-native-skills/rules/list-performance-inline-objects.md +97 -0
- package/skills/vercel-react-native-skills/rules/list-performance-item-expensive.md +94 -0
- package/skills/vercel-react-native-skills/rules/list-performance-item-memo.md +82 -0
- package/skills/vercel-react-native-skills/rules/list-performance-item-types.md +104 -0
- package/skills/vercel-react-native-skills/rules/list-performance-virtualize.md +67 -0
- package/skills/vercel-react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
- package/skills/vercel-react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
- package/skills/vercel-react-native-skills/rules/navigation-native-navigators.md +188 -0
- package/skills/vercel-react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
- package/skills/vercel-react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
- package/skills/vercel-react-native-skills/rules/react-state-dispatcher.md +91 -0
- package/skills/vercel-react-native-skills/rules/react-state-fallback.md +56 -0
- package/skills/vercel-react-native-skills/rules/react-state-minimize.md +65 -0
- package/skills/vercel-react-native-skills/rules/rendering-no-falsy-and.md +74 -0
- package/skills/vercel-react-native-skills/rules/rendering-text-in-text-component.md +36 -0
- package/skills/vercel-react-native-skills/rules/scroll-position-no-state.md +82 -0
- package/skills/vercel-react-native-skills/rules/state-ground-truth.md +80 -0
- package/skills/vercel-react-native-skills/rules/ui-expo-image.md +66 -0
- package/skills/vercel-react-native-skills/rules/ui-image-gallery.md +104 -0
- package/skills/vercel-react-native-skills/rules/ui-measure-views.md +78 -0
- package/skills/vercel-react-native-skills/rules/ui-menus.md +174 -0
- package/skills/vercel-react-native-skills/rules/ui-native-modals.md +77 -0
- package/skills/vercel-react-native-skills/rules/ui-pressable.md +61 -0
- package/skills/vercel-react-native-skills/rules/ui-safe-area-scroll.md +65 -0
- package/skills/vercel-react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
- package/skills/vercel-react-native-skills/rules/ui-styling.md +87 -0
- package/skills/web-design-guidelines/SKILL.md +39 -0
- package/templates/AGENTS.md +31 -0
- package/templates/CLAUDE.md +31 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
# shadcn/ui Customization Guide
|
|
2
|
+
|
|
3
|
+
Learn how to customize shadcn/ui components to match your brand and design requirements.
|
|
4
|
+
|
|
5
|
+
## Theming Approach
|
|
6
|
+
|
|
7
|
+
shadcn/ui uses a CSS variable-based theming system, making it easy to customize colors, spacing, and other design tokens globally.
|
|
8
|
+
|
|
9
|
+
## Color Customization
|
|
10
|
+
|
|
11
|
+
### Understanding the Color System
|
|
12
|
+
|
|
13
|
+
shadcn/ui uses HSL color values stored as CSS variables. Each color has a base value and a foreground variant for text/content that appears on top of it.
|
|
14
|
+
|
|
15
|
+
**Base Color Variables** (in `globals.css`):
|
|
16
|
+
```css
|
|
17
|
+
:root {
|
|
18
|
+
--background: 0 0% 100%; /* Page background */
|
|
19
|
+
--foreground: 222.2 84% 4.9%; /* Primary text color */
|
|
20
|
+
--primary: 221.2 83.2% 53.3%; /* Primary brand color */
|
|
21
|
+
--primary-foreground: 210 40% 98%; /* Text on primary */
|
|
22
|
+
--secondary: 210 40% 96.1%; /* Secondary actions */
|
|
23
|
+
--accent: 210 40% 96.1%; /* Accent highlights */
|
|
24
|
+
--muted: 210 40% 96.1%; /* Muted backgrounds */
|
|
25
|
+
--destructive: 0 84.2% 60.2%; /* Error/danger */
|
|
26
|
+
--border: 214.3 31.8% 91.4%; /* Border colors */
|
|
27
|
+
--input: 214.3 31.8% 91.4%; /* Input borders */
|
|
28
|
+
--ring: 221.2 83.2% 53.3%; /* Focus rings */
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Changing Brand Colors
|
|
33
|
+
|
|
34
|
+
To match your brand, update the primary color:
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
:root {
|
|
38
|
+
/* Original blue */
|
|
39
|
+
--primary: 221.2 83.2% 53.3%;
|
|
40
|
+
|
|
41
|
+
/* Change to brand purple */
|
|
42
|
+
--primary: 270 91% 65%;
|
|
43
|
+
|
|
44
|
+
/* Adjust foreground for contrast */
|
|
45
|
+
--primary-foreground: 0 0% 100%;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**HSL Format**: `hue saturation lightness`
|
|
50
|
+
- Hue: 0-360 (color wheel position)
|
|
51
|
+
- Saturation: 0-100% (color intensity)
|
|
52
|
+
- Lightness: 0-100% (brightness)
|
|
53
|
+
|
|
54
|
+
### Tools for Color Selection
|
|
55
|
+
|
|
56
|
+
1. **HSL Color Picker**: https://hslpicker.com/
|
|
57
|
+
2. **Shadcn Theme Generator**: https://ui.shadcn.com/themes
|
|
58
|
+
3. **Coolors**: https://coolors.co/ (generates palettes)
|
|
59
|
+
|
|
60
|
+
### Creating a Color Scheme
|
|
61
|
+
|
|
62
|
+
Start with your primary brand color, then derive other colors:
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
:root {
|
|
66
|
+
/* 1. Primary brand color */
|
|
67
|
+
--primary: 230 90% 60%;
|
|
68
|
+
--primary-foreground: 0 0% 100%;
|
|
69
|
+
|
|
70
|
+
/* 2. Lighter variant for secondary */
|
|
71
|
+
--secondary: 230 30% 95%;
|
|
72
|
+
--secondary-foreground: 230 90% 30%;
|
|
73
|
+
|
|
74
|
+
/* 3. Subtle accent (shift hue slightly) */
|
|
75
|
+
--accent: 200 90% 60%;
|
|
76
|
+
--accent-foreground: 0 0% 100%;
|
|
77
|
+
|
|
78
|
+
/* 4. Muted backgrounds (low saturation) */
|
|
79
|
+
--muted: 230 20% 96%;
|
|
80
|
+
--muted-foreground: 230 20% 40%;
|
|
81
|
+
|
|
82
|
+
/* 5. Keep destructive red-based */
|
|
83
|
+
--destructive: 0 84% 60%;
|
|
84
|
+
--destructive-foreground: 0 0% 100%;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Dark Mode
|
|
89
|
+
|
|
90
|
+
### Setting Up Dark Mode
|
|
91
|
+
|
|
92
|
+
shadcn/ui includes dark mode support out of the box. Add dark mode colors:
|
|
93
|
+
|
|
94
|
+
```css
|
|
95
|
+
.dark {
|
|
96
|
+
--background: 222.2 84% 4.9%;
|
|
97
|
+
--foreground: 210 40% 98%;
|
|
98
|
+
--primary: 221.2 83.2% 53.3%;
|
|
99
|
+
--primary-foreground: 210 40% 98%;
|
|
100
|
+
/* ... all color variables */
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Toggle Dark Mode
|
|
105
|
+
|
|
106
|
+
**Next.js with next-themes**:
|
|
107
|
+
```bash
|
|
108
|
+
npm install next-themes
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
// app/providers.tsx
|
|
113
|
+
"use client"
|
|
114
|
+
|
|
115
|
+
import { ThemeProvider } from "next-themes"
|
|
116
|
+
|
|
117
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
118
|
+
return (
|
|
119
|
+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
|
120
|
+
{children}
|
|
121
|
+
</ThemeProvider>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// app/layout.tsx
|
|
126
|
+
import { Providers } from "./providers"
|
|
127
|
+
|
|
128
|
+
export default function RootLayout({ children }) {
|
|
129
|
+
return (
|
|
130
|
+
<html suppressHydrationWarning>
|
|
131
|
+
<body>
|
|
132
|
+
<Providers>{children}</Providers>
|
|
133
|
+
</body>
|
|
134
|
+
</html>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// components/theme-toggle.tsx
|
|
139
|
+
"use client"
|
|
140
|
+
|
|
141
|
+
import { Moon, Sun } from "lucide-react"
|
|
142
|
+
import { useTheme } from "next-themes"
|
|
143
|
+
import { Button } from "@/components/ui/button"
|
|
144
|
+
|
|
145
|
+
export function ThemeToggle() {
|
|
146
|
+
const { setTheme, theme } = useTheme()
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<Button
|
|
150
|
+
variant="ghost"
|
|
151
|
+
size="icon"
|
|
152
|
+
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
|
|
153
|
+
>
|
|
154
|
+
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
|
155
|
+
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
|
156
|
+
<span className="sr-only">Toggle theme</span>
|
|
157
|
+
</Button>
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Component Customization
|
|
163
|
+
|
|
164
|
+
### Using Variants
|
|
165
|
+
|
|
166
|
+
shadcn/ui components use `class-variance-authority` (cva) for variants. Example from Button:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
// components/ui/button.tsx
|
|
170
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
171
|
+
|
|
172
|
+
const buttonVariants = cva(
|
|
173
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium",
|
|
174
|
+
{
|
|
175
|
+
variants: {
|
|
176
|
+
variant: {
|
|
177
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
178
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
179
|
+
outline: "border border-input bg-background hover:bg-accent",
|
|
180
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
181
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
182
|
+
},
|
|
183
|
+
size: {
|
|
184
|
+
default: "h-10 px-4 py-2",
|
|
185
|
+
sm: "h-9 rounded-md px-3",
|
|
186
|
+
lg: "h-11 rounded-md px-8",
|
|
187
|
+
icon: "h-10 w-10",
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
defaultVariants: {
|
|
191
|
+
variant: "default",
|
|
192
|
+
size: "default",
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Adding Custom Variants
|
|
199
|
+
|
|
200
|
+
To add a new variant, edit the component file in `components/ui/`:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Add new "success" variant to button
|
|
204
|
+
const buttonVariants = cva(
|
|
205
|
+
"...",
|
|
206
|
+
{
|
|
207
|
+
variants: {
|
|
208
|
+
variant: {
|
|
209
|
+
default: "...",
|
|
210
|
+
destructive: "...",
|
|
211
|
+
// Add new variant
|
|
212
|
+
success: "bg-green-600 text-white hover:bg-green-700",
|
|
213
|
+
},
|
|
214
|
+
// Add new size
|
|
215
|
+
size: {
|
|
216
|
+
default: "...",
|
|
217
|
+
xl: "h-12 rounded-md px-10 text-base",
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
// Update TypeScript interface
|
|
224
|
+
export interface ButtonProps
|
|
225
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
226
|
+
VariantProps<typeof buttonVariants> {
|
|
227
|
+
asChild?: boolean
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Usage:
|
|
232
|
+
```tsx
|
|
233
|
+
<Button variant="success" size="xl">Save Changes</Button>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Creating Composite Components
|
|
237
|
+
|
|
238
|
+
Don't modify `components/ui/` directly. Instead, create wrapper components:
|
|
239
|
+
|
|
240
|
+
```tsx
|
|
241
|
+
// components/loading-button.tsx
|
|
242
|
+
import { Button, ButtonProps } from "@/components/ui/button"
|
|
243
|
+
import { Loader2 } from "lucide-react"
|
|
244
|
+
|
|
245
|
+
interface LoadingButtonProps extends ButtonProps {
|
|
246
|
+
loading?: boolean
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function LoadingButton({
|
|
250
|
+
loading,
|
|
251
|
+
children,
|
|
252
|
+
disabled,
|
|
253
|
+
...props
|
|
254
|
+
}: LoadingButtonProps) {
|
|
255
|
+
return (
|
|
256
|
+
<Button disabled={loading || disabled} {...props}>
|
|
257
|
+
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
258
|
+
{children}
|
|
259
|
+
</Button>
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Typography Customization
|
|
265
|
+
|
|
266
|
+
### Font Family
|
|
267
|
+
|
|
268
|
+
Update `tailwind.config.js`:
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
module.exports = {
|
|
272
|
+
theme: {
|
|
273
|
+
extend: {
|
|
274
|
+
fontFamily: {
|
|
275
|
+
sans: ['Inter', 'system-ui', 'sans-serif'],
|
|
276
|
+
heading: ['Poppins', 'system-ui', 'sans-serif'],
|
|
277
|
+
mono: ['Fira Code', 'monospace'],
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Import fonts in your layout:
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
// app/layout.tsx
|
|
288
|
+
import { Inter, Poppins } from 'next/font/google'
|
|
289
|
+
|
|
290
|
+
const inter = Inter({ subsets: ['latin'], variable: '--font-sans' })
|
|
291
|
+
const poppins = Poppins({
|
|
292
|
+
weight: ['600', '700'],
|
|
293
|
+
subsets: ['latin'],
|
|
294
|
+
variable: '--font-heading',
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
export default function RootLayout({ children }) {
|
|
298
|
+
return (
|
|
299
|
+
<html className={`${inter.variable} ${poppins.variable}`}>
|
|
300
|
+
<body className="font-sans">{children}</body>
|
|
301
|
+
</html>
|
|
302
|
+
)
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Use in components:
|
|
307
|
+
```tsx
|
|
308
|
+
<h1 className="font-heading text-3xl">Heading</h1>
|
|
309
|
+
<p className="font-sans">Body text</p>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Font Sizes
|
|
313
|
+
|
|
314
|
+
Extend Tailwind's font scale:
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
// tailwind.config.js
|
|
318
|
+
module.exports = {
|
|
319
|
+
theme: {
|
|
320
|
+
extend: {
|
|
321
|
+
fontSize: {
|
|
322
|
+
'xs': '0.75rem', // 12px
|
|
323
|
+
'sm': '0.875rem', // 14px
|
|
324
|
+
'base': '1rem', // 16px
|
|
325
|
+
'lg': '1.125rem', // 18px
|
|
326
|
+
'xl': '1.25rem', // 20px
|
|
327
|
+
'2xl': '1.5rem', // 24px
|
|
328
|
+
'3xl': '1.875rem', // 30px
|
|
329
|
+
'4xl': '2.25rem', // 36px
|
|
330
|
+
'5xl': '3rem', // 48px
|
|
331
|
+
'6xl': '3.75rem', // 60px
|
|
332
|
+
'7xl': '4.5rem', // 72px
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Spacing & Layout
|
|
340
|
+
|
|
341
|
+
### Border Radius
|
|
342
|
+
|
|
343
|
+
Customize roundedness globally:
|
|
344
|
+
|
|
345
|
+
```css
|
|
346
|
+
/* globals.css */
|
|
347
|
+
:root {
|
|
348
|
+
--radius: 0.5rem; /* Default (8px) */
|
|
349
|
+
|
|
350
|
+
/* More rounded */
|
|
351
|
+
--radius: 1rem; /* 16px */
|
|
352
|
+
|
|
353
|
+
/* Sharp edges */
|
|
354
|
+
--radius: 0; /* No rounding */
|
|
355
|
+
|
|
356
|
+
/* Very rounded */
|
|
357
|
+
--radius: 1.5rem; /* 24px */
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
This affects all components using `rounded-lg`, `rounded-md`, `rounded-sm`.
|
|
362
|
+
|
|
363
|
+
### Custom Spacing
|
|
364
|
+
|
|
365
|
+
Extend Tailwind's spacing scale:
|
|
366
|
+
|
|
367
|
+
```javascript
|
|
368
|
+
// tailwind.config.js
|
|
369
|
+
module.exports = {
|
|
370
|
+
theme: {
|
|
371
|
+
extend: {
|
|
372
|
+
spacing: {
|
|
373
|
+
'72': '18rem',
|
|
374
|
+
'84': '21rem',
|
|
375
|
+
'96': '24rem',
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Animation Customization
|
|
383
|
+
|
|
384
|
+
### Adjusting Existing Animations
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
// tailwind.config.js
|
|
388
|
+
module.exports = {
|
|
389
|
+
theme: {
|
|
390
|
+
extend: {
|
|
391
|
+
keyframes: {
|
|
392
|
+
// Make accordion faster
|
|
393
|
+
"accordion-down": {
|
|
394
|
+
from: { height: 0 },
|
|
395
|
+
to: { height: "var(--radix-accordion-content-height)" },
|
|
396
|
+
},
|
|
397
|
+
"accordion-up": {
|
|
398
|
+
from: { height: "var(--radix-accordion-content-height)" },
|
|
399
|
+
to: { height: 0 },
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
animation: {
|
|
403
|
+
"accordion-down": "accordion-down 0.15s ease-out", // Faster
|
|
404
|
+
"accordion-up": "accordion-up 0.15s ease-out",
|
|
405
|
+
},
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Adding New Animations
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
// tailwind.config.js
|
|
415
|
+
module.exports = {
|
|
416
|
+
theme: {
|
|
417
|
+
extend: {
|
|
418
|
+
keyframes: {
|
|
419
|
+
"fade-in": {
|
|
420
|
+
"0%": { opacity: 0 },
|
|
421
|
+
"100%": { opacity: 1 },
|
|
422
|
+
},
|
|
423
|
+
"slide-in-bottom": {
|
|
424
|
+
"0%": { transform: "translateY(100%)" },
|
|
425
|
+
"100%": { transform: "translateY(0)" },
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
animation: {
|
|
429
|
+
"fade-in": "fade-in 0.3s ease-out",
|
|
430
|
+
"slide-in-bottom": "slide-in-bottom 0.3s ease-out",
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Use in components:
|
|
438
|
+
```tsx
|
|
439
|
+
<div className="animate-fade-in">Content</div>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Advanced Customization
|
|
443
|
+
|
|
444
|
+
### Creating a Design System
|
|
445
|
+
|
|
446
|
+
Structure your customizations:
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
src/
|
|
450
|
+
├── styles/
|
|
451
|
+
│ ├── globals.css # CSS variables & base styles
|
|
452
|
+
│ ├── themes/
|
|
453
|
+
│ │ ├── default.css # Default theme
|
|
454
|
+
│ │ └── brand.css # Brand-specific overrides
|
|
455
|
+
│ └── components/
|
|
456
|
+
│ └── custom.css # Component-specific styles
|
|
457
|
+
├── lib/
|
|
458
|
+
│ └── design-tokens.ts # Shared constants
|
|
459
|
+
└── components/
|
|
460
|
+
├── ui/ # shadcn components (don't modify)
|
|
461
|
+
└── custom/ # Your wrapper components
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Design Tokens File
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
// lib/design-tokens.ts
|
|
468
|
+
export const designTokens = {
|
|
469
|
+
colors: {
|
|
470
|
+
brand: {
|
|
471
|
+
primary: 'hsl(230, 90%, 60%)',
|
|
472
|
+
secondary: 'hsl(230, 30%, 95%)',
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
spacing: {
|
|
476
|
+
section: '5rem',
|
|
477
|
+
card: '1.5rem',
|
|
478
|
+
},
|
|
479
|
+
radius: {
|
|
480
|
+
card: '1rem',
|
|
481
|
+
button: '0.5rem',
|
|
482
|
+
},
|
|
483
|
+
typography: {
|
|
484
|
+
h1: 'text-5xl font-heading font-bold',
|
|
485
|
+
h2: 'text-4xl font-heading font-semibold',
|
|
486
|
+
h3: 'text-3xl font-heading font-semibold',
|
|
487
|
+
body: 'text-base font-sans',
|
|
488
|
+
small: 'text-sm text-muted-foreground',
|
|
489
|
+
},
|
|
490
|
+
} as const
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
Use in components:
|
|
494
|
+
```tsx
|
|
495
|
+
import { designTokens } from "@/lib/design-tokens"
|
|
496
|
+
|
|
497
|
+
<h1 className={designTokens.typography.h1}>Title</h1>
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
## Best Practices
|
|
501
|
+
|
|
502
|
+
1. **Don't modify `components/ui/` files directly**: Create wrapper components instead
|
|
503
|
+
2. **Use CSS variables for theming**: Easier to maintain and switch themes
|
|
504
|
+
3. **Leverage Tailwind's `extend`**: Don't replace defaults, extend them
|
|
505
|
+
4. **Keep variants in component files**: Co-locate variant logic with components
|
|
506
|
+
5. **Test dark mode**: Ensure all customizations work in both themes
|
|
507
|
+
6. **Document custom variants**: Add comments for custom additions
|
|
508
|
+
7. **Use consistent spacing**: Stick to Tailwind's spacing scale
|
|
509
|
+
8. **Maintain accessibility**: Don't sacrifice contrast for aesthetics
|
|
510
|
+
|
|
511
|
+
## Resources
|
|
512
|
+
|
|
513
|
+
- [Tailwind CSS Customization](https://tailwindcss.com/docs/theme)
|
|
514
|
+
- [CVA Documentation](https://cva.style/docs)
|
|
515
|
+
- [Radix UI Theming](https://www.radix-ui.com/themes/docs/theme/overview)
|
|
516
|
+
- [HSL Color Theory](https://www.w3.org/TR/css-color-3/#hsl-color)
|