@kood/claude-code 0.1.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/dist/index.d.ts +2 -0
- package/dist/index.js +297 -0
- package/package.json +47 -0
- package/templates/hono/CLAUDE.md +376 -0
- package/templates/hono/docs/deployment/cloudflare.md +328 -0
- package/templates/hono/docs/deployment/index.md +291 -0
- package/templates/hono/docs/git/index.md +180 -0
- package/templates/hono/docs/library/hono/error-handling.md +400 -0
- package/templates/hono/docs/library/hono/index.md +241 -0
- package/templates/hono/docs/library/hono/middleware.md +334 -0
- package/templates/hono/docs/library/hono/rpc.md +454 -0
- package/templates/hono/docs/library/hono/validation.md +328 -0
- package/templates/hono/docs/library/prisma/index.md +427 -0
- package/templates/hono/docs/library/zod/index.md +413 -0
- package/templates/hono/docs/mcp/context7.md +106 -0
- package/templates/hono/docs/mcp/index.md +94 -0
- package/templates/hono/docs/mcp/sequential-thinking.md +101 -0
- package/templates/hono/docs/mcp/sgrep.md +105 -0
- package/templates/hono/docs/skills/gemini-review/SKILL.md +220 -0
- package/templates/hono/docs/skills/gemini-review/references/checklists.md +136 -0
- package/templates/hono/docs/skills/gemini-review/references/prompt-templates.md +303 -0
- package/templates/tanstack-start/CLAUDE.md +279 -0
- package/templates/tanstack-start/docs/architecture/architecture.md +547 -0
- package/templates/tanstack-start/docs/deployment/cloudflare.md +346 -0
- package/templates/tanstack-start/docs/deployment/index.md +102 -0
- package/templates/tanstack-start/docs/deployment/nitro.md +211 -0
- package/templates/tanstack-start/docs/deployment/railway.md +364 -0
- package/templates/tanstack-start/docs/deployment/vercel.md +287 -0
- package/templates/tanstack-start/docs/design/accessibility.md +433 -0
- package/templates/tanstack-start/docs/design/color.md +235 -0
- package/templates/tanstack-start/docs/design/components.md +409 -0
- package/templates/tanstack-start/docs/design/index.md +107 -0
- package/templates/tanstack-start/docs/design/safe-area.md +317 -0
- package/templates/tanstack-start/docs/design/spacing.md +341 -0
- package/templates/tanstack-start/docs/design/tailwind-setup.md +470 -0
- package/templates/tanstack-start/docs/design/typography.md +324 -0
- package/templates/tanstack-start/docs/git/index.md +203 -0
- package/templates/tanstack-start/docs/guides/best-practices.md +753 -0
- package/templates/tanstack-start/docs/guides/getting-started.md +304 -0
- package/templates/tanstack-start/docs/guides/husky-lint-staged.md +303 -0
- package/templates/tanstack-start/docs/guides/prettier.md +189 -0
- package/templates/tanstack-start/docs/guides/project-templates.md +710 -0
- package/templates/tanstack-start/docs/library/better-auth/2fa.md +136 -0
- package/templates/tanstack-start/docs/library/better-auth/advanced.md +138 -0
- package/templates/tanstack-start/docs/library/better-auth/index.md +83 -0
- package/templates/tanstack-start/docs/library/better-auth/plugins.md +111 -0
- package/templates/tanstack-start/docs/library/better-auth/session.md +127 -0
- package/templates/tanstack-start/docs/library/better-auth/setup.md +123 -0
- package/templates/tanstack-start/docs/library/prisma/crud.md +218 -0
- package/templates/tanstack-start/docs/library/prisma/index.md +165 -0
- package/templates/tanstack-start/docs/library/prisma/relations.md +191 -0
- package/templates/tanstack-start/docs/library/prisma/schema.md +177 -0
- package/templates/tanstack-start/docs/library/prisma/setup.md +156 -0
- package/templates/tanstack-start/docs/library/prisma/transactions.md +140 -0
- package/templates/tanstack-start/docs/library/tanstack-query/index.md +146 -0
- package/templates/tanstack-start/docs/library/tanstack-query/invalidation.md +146 -0
- package/templates/tanstack-start/docs/library/tanstack-query/optimistic-updates.md +196 -0
- package/templates/tanstack-start/docs/library/tanstack-query/setup.md +110 -0
- package/templates/tanstack-start/docs/library/tanstack-query/use-mutation.md +170 -0
- package/templates/tanstack-start/docs/library/tanstack-query/use-query.md +173 -0
- package/templates/tanstack-start/docs/library/tanstack-start/auth-patterns.md +171 -0
- package/templates/tanstack-start/docs/library/tanstack-start/index.md +114 -0
- package/templates/tanstack-start/docs/library/tanstack-start/middleware.md +142 -0
- package/templates/tanstack-start/docs/library/tanstack-start/routing.md +163 -0
- package/templates/tanstack-start/docs/library/tanstack-start/server-functions.md +128 -0
- package/templates/tanstack-start/docs/library/tanstack-start/setup.md +85 -0
- package/templates/tanstack-start/docs/library/zod/basic-types.md +186 -0
- package/templates/tanstack-start/docs/library/zod/complex-types.md +204 -0
- package/templates/tanstack-start/docs/library/zod/index.md +186 -0
- package/templates/tanstack-start/docs/library/zod/transforms.md +174 -0
- package/templates/tanstack-start/docs/library/zod/validation.md +208 -0
- package/templates/tanstack-start/docs/mcp/context7.md +204 -0
- package/templates/tanstack-start/docs/mcp/index.md +116 -0
- package/templates/tanstack-start/docs/mcp/sequential-thinking.md +180 -0
- package/templates/tanstack-start/docs/mcp/sgrep.md +174 -0
- package/templates/tanstack-start/docs/skills/gemini-review/SKILL.md +220 -0
- package/templates/tanstack-start/docs/skills/gemini-review/references/checklists.md +150 -0
- package/templates/tanstack-start/docs/skills/gemini-review/references/prompt-templates.md +293 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
# Tailwind CSS 설정
|
|
2
|
+
|
|
3
|
+
> **상위 문서**: [UI/UX 디자인 가이드](./index.md)
|
|
4
|
+
|
|
5
|
+
Tailwind CSS v4를 사용한 디자인 시스템 구현 가이드입니다.
|
|
6
|
+
|
|
7
|
+
## 기본 설정
|
|
8
|
+
|
|
9
|
+
### 설치
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
yarn add tailwindcss postcss autoprefixer
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### CSS 파일 설정
|
|
16
|
+
|
|
17
|
+
```css
|
|
18
|
+
/* src/styles/app.css */
|
|
19
|
+
@import "tailwindcss";
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### PostCSS 설정
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
// postcss.config.js
|
|
26
|
+
export default {
|
|
27
|
+
plugins: {
|
|
28
|
+
tailwindcss: {},
|
|
29
|
+
autoprefixer: {},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 디자인 토큰 정의
|
|
35
|
+
|
|
36
|
+
### @theme 디렉티브
|
|
37
|
+
|
|
38
|
+
Tailwind CSS v4에서는 `@theme` 디렉티브로 디자인 토큰을 정의합니다.
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
/* src/styles/app.css */
|
|
42
|
+
@import "tailwindcss";
|
|
43
|
+
|
|
44
|
+
@theme {
|
|
45
|
+
/* ========================================
|
|
46
|
+
* 색상 시스템
|
|
47
|
+
* ======================================== */
|
|
48
|
+
|
|
49
|
+
/* 브랜드 기본색 */
|
|
50
|
+
--color-primary-50: oklch(0.97 0.01 250);
|
|
51
|
+
--color-primary-100: oklch(0.93 0.03 250);
|
|
52
|
+
--color-primary-200: oklch(0.88 0.06 250);
|
|
53
|
+
--color-primary-300: oklch(0.78 0.1 250);
|
|
54
|
+
--color-primary-400: oklch(0.68 0.15 250);
|
|
55
|
+
--color-primary-500: oklch(0.55 0.2 250); /* 기본 */
|
|
56
|
+
--color-primary-600: oklch(0.48 0.22 250); /* hover */
|
|
57
|
+
--color-primary-700: oklch(0.42 0.2 250); /* active */
|
|
58
|
+
--color-primary-800: oklch(0.35 0.17 250);
|
|
59
|
+
--color-primary-900: oklch(0.28 0.12 250);
|
|
60
|
+
|
|
61
|
+
/* 의미론적 색상 */
|
|
62
|
+
--color-success: oklch(0.55 0.15 145);
|
|
63
|
+
--color-success-light: oklch(0.92 0.05 145);
|
|
64
|
+
--color-error: oklch(0.55 0.2 25);
|
|
65
|
+
--color-error-light: oklch(0.92 0.05 25);
|
|
66
|
+
--color-warning: oklch(0.75 0.15 85);
|
|
67
|
+
--color-warning-light: oklch(0.95 0.05 85);
|
|
68
|
+
--color-info: oklch(0.55 0.2 250);
|
|
69
|
+
--color-info-light: oklch(0.92 0.05 250);
|
|
70
|
+
|
|
71
|
+
/* ========================================
|
|
72
|
+
* 타이포그래피
|
|
73
|
+
* ======================================== */
|
|
74
|
+
|
|
75
|
+
/* 폰트 패밀리 */
|
|
76
|
+
--font-sans: "Pretendard", "Inter", system-ui, -apple-system, sans-serif;
|
|
77
|
+
--font-mono: "JetBrains Mono", "Fira Code", Consolas, monospace;
|
|
78
|
+
|
|
79
|
+
/* 폰트 크기 (선택적 커스텀) */
|
|
80
|
+
--font-size-hero: 3.5rem;
|
|
81
|
+
|
|
82
|
+
/* ========================================
|
|
83
|
+
* 간격 (선택적 커스텀)
|
|
84
|
+
* ======================================== */
|
|
85
|
+
|
|
86
|
+
--spacing-section: 4rem;
|
|
87
|
+
--spacing-page: 6rem;
|
|
88
|
+
|
|
89
|
+
/* ========================================
|
|
90
|
+
* 테두리 반경
|
|
91
|
+
* ======================================== */
|
|
92
|
+
|
|
93
|
+
--radius-button: 0.5rem;
|
|
94
|
+
--radius-card: 0.75rem;
|
|
95
|
+
--radius-modal: 1rem;
|
|
96
|
+
|
|
97
|
+
/* ========================================
|
|
98
|
+
* 그림자
|
|
99
|
+
* ======================================== */
|
|
100
|
+
|
|
101
|
+
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
102
|
+
--shadow-dropdown: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
|
103
|
+
--shadow-modal: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
|
104
|
+
|
|
105
|
+
/* ========================================
|
|
106
|
+
* 애니메이션
|
|
107
|
+
* ======================================== */
|
|
108
|
+
|
|
109
|
+
--transition-fast: 150ms ease;
|
|
110
|
+
--transition-normal: 200ms ease;
|
|
111
|
+
--transition-slow: 300ms ease;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 사용 예시
|
|
116
|
+
|
|
117
|
+
### 색상 토큰 사용
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
// 브랜드 색상
|
|
121
|
+
<button className="bg-primary-600 hover:bg-primary-700 text-white">
|
|
122
|
+
주요 버튼
|
|
123
|
+
</button>
|
|
124
|
+
|
|
125
|
+
// 의미론적 색상
|
|
126
|
+
<div className="bg-success-light border border-success text-success">
|
|
127
|
+
성공 메시지
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<div className="bg-error-light border border-error text-error">
|
|
131
|
+
오류 메시지
|
|
132
|
+
</div>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 폰트 토큰 사용
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
// 본문 (기본)
|
|
139
|
+
<p className="font-sans">Pretendard 폰트 적용</p>
|
|
140
|
+
|
|
141
|
+
// 코드
|
|
142
|
+
<code className="font-mono">JetBrains Mono 적용</code>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 커스텀 간격/반경 사용
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
// 섹션 간격
|
|
149
|
+
<section className="py-[--spacing-section]">
|
|
150
|
+
|
|
151
|
+
// 카드 반경
|
|
152
|
+
<div className="rounded-[--radius-card]">
|
|
153
|
+
|
|
154
|
+
// 모달 반경
|
|
155
|
+
<div className="rounded-[--radius-modal]">
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 다크 모드 설정
|
|
159
|
+
|
|
160
|
+
### 다크 모드 토큰
|
|
161
|
+
|
|
162
|
+
```css
|
|
163
|
+
@theme {
|
|
164
|
+
/* 라이트 모드 배경 */
|
|
165
|
+
--color-surface: white;
|
|
166
|
+
--color-surface-secondary: oklch(0.98 0 0);
|
|
167
|
+
|
|
168
|
+
/* 라이트 모드 텍스트 */
|
|
169
|
+
--color-text-primary: oklch(0.15 0 0);
|
|
170
|
+
--color-text-secondary: oklch(0.4 0 0);
|
|
171
|
+
--color-text-muted: oklch(0.6 0 0);
|
|
172
|
+
|
|
173
|
+
/* 라이트 모드 테두리 */
|
|
174
|
+
--color-border: oklch(0.9 0 0);
|
|
175
|
+
--color-border-strong: oklch(0.8 0 0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* 다크 모드 오버라이드 */
|
|
179
|
+
@media (prefers-color-scheme: dark) {
|
|
180
|
+
:root {
|
|
181
|
+
--color-surface: oklch(0.15 0 0);
|
|
182
|
+
--color-surface-secondary: oklch(0.2 0 0);
|
|
183
|
+
|
|
184
|
+
--color-text-primary: oklch(0.95 0 0);
|
|
185
|
+
--color-text-secondary: oklch(0.7 0 0);
|
|
186
|
+
--color-text-muted: oklch(0.5 0 0);
|
|
187
|
+
|
|
188
|
+
--color-border: oklch(0.3 0 0);
|
|
189
|
+
--color-border-strong: oklch(0.4 0 0);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 다크 모드 클래스 사용
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
// Tailwind의 dark: 접두사 사용
|
|
198
|
+
<div className="bg-white dark:bg-gray-900">
|
|
199
|
+
<h1 className="text-gray-900 dark:text-white">제목</h1>
|
|
200
|
+
<p className="text-gray-600 dark:text-gray-300">본문</p>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
// 또는 CSS 변수 사용
|
|
204
|
+
<div className="bg-[--color-surface] text-[--color-text-primary]">
|
|
205
|
+
자동으로 다크 모드 대응
|
|
206
|
+
</div>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 다크 모드 토글
|
|
210
|
+
|
|
211
|
+
```tsx
|
|
212
|
+
// src/components/theme-toggle.tsx
|
|
213
|
+
import { useEffect, useState } from 'react'
|
|
214
|
+
|
|
215
|
+
export const ThemeToggle = () => {
|
|
216
|
+
const [theme, setTheme] = useState<'light' | 'dark'>('light')
|
|
217
|
+
|
|
218
|
+
useEffect(() => {
|
|
219
|
+
// 시스템 설정 확인
|
|
220
|
+
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
221
|
+
setTheme('dark')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// localStorage 확인
|
|
225
|
+
const saved = localStorage.getItem('theme')
|
|
226
|
+
if (saved) setTheme(saved as 'light' | 'dark')
|
|
227
|
+
}, [])
|
|
228
|
+
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
document.documentElement.classList.toggle('dark', theme === 'dark')
|
|
231
|
+
localStorage.setItem('theme', theme)
|
|
232
|
+
}, [theme])
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
|
|
236
|
+
{theme === 'light' ? '🌙' : '☀️'}
|
|
237
|
+
</button>
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## 컴포넌트 스타일 패턴
|
|
243
|
+
|
|
244
|
+
### 버튼 컴포넌트
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
// src/components/ui/button.tsx
|
|
248
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
249
|
+
|
|
250
|
+
const buttonVariants = cva(
|
|
251
|
+
// 기본 스타일
|
|
252
|
+
'inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed',
|
|
253
|
+
{
|
|
254
|
+
variants: {
|
|
255
|
+
variant: {
|
|
256
|
+
primary: 'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500',
|
|
257
|
+
secondary: 'border border-gray-300 bg-white hover:bg-gray-50 focus:ring-gray-500',
|
|
258
|
+
ghost: 'hover:bg-gray-100 focus:ring-gray-500',
|
|
259
|
+
destructive: 'bg-red-600 text-white hover:bg-red-700 focus:ring-red-500',
|
|
260
|
+
},
|
|
261
|
+
size: {
|
|
262
|
+
sm: 'px-3 py-1.5 text-sm rounded-md',
|
|
263
|
+
md: 'px-4 py-2 text-base rounded-lg',
|
|
264
|
+
lg: 'px-6 py-3 text-lg rounded-lg',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
defaultVariants: {
|
|
268
|
+
variant: 'primary',
|
|
269
|
+
size: 'md',
|
|
270
|
+
},
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
interface ButtonProps
|
|
275
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
276
|
+
VariantProps<typeof buttonVariants> {}
|
|
277
|
+
|
|
278
|
+
export const Button = ({ variant, size, className, ...props }: ButtonProps) => {
|
|
279
|
+
return (
|
|
280
|
+
<button
|
|
281
|
+
className={buttonVariants({ variant, size, className })}
|
|
282
|
+
{...props}
|
|
283
|
+
/>
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### 입력 필드 컴포넌트
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
// src/components/ui/input.tsx
|
|
292
|
+
import { forwardRef } from 'react'
|
|
293
|
+
|
|
294
|
+
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
295
|
+
label?: string
|
|
296
|
+
error?: string
|
|
297
|
+
hint?: string
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
301
|
+
({ label, error, hint, className, id, ...props }, ref) => {
|
|
302
|
+
const inputId = id || label?.toLowerCase().replace(/\s/g, '-')
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div>
|
|
306
|
+
{label && (
|
|
307
|
+
<label
|
|
308
|
+
htmlFor={inputId}
|
|
309
|
+
className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"
|
|
310
|
+
>
|
|
311
|
+
{label}
|
|
312
|
+
</label>
|
|
313
|
+
)}
|
|
314
|
+
<input
|
|
315
|
+
ref={ref}
|
|
316
|
+
id={inputId}
|
|
317
|
+
className={`
|
|
318
|
+
w-full px-3 py-2 border rounded-lg transition-colors
|
|
319
|
+
placeholder:text-gray-400
|
|
320
|
+
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-primary-500
|
|
321
|
+
${error
|
|
322
|
+
? 'border-red-500 focus:ring-red-500 focus:border-red-500'
|
|
323
|
+
: 'border-gray-300 dark:border-gray-600'
|
|
324
|
+
}
|
|
325
|
+
${className}
|
|
326
|
+
`}
|
|
327
|
+
aria-invalid={!!error}
|
|
328
|
+
aria-describedby={error ? `${inputId}-error` : hint ? `${inputId}-hint` : undefined}
|
|
329
|
+
{...props}
|
|
330
|
+
/>
|
|
331
|
+
{error && (
|
|
332
|
+
<p id={`${inputId}-error`} className="mt-1 text-sm text-red-600" role="alert">
|
|
333
|
+
{error}
|
|
334
|
+
</p>
|
|
335
|
+
)}
|
|
336
|
+
{hint && !error && (
|
|
337
|
+
<p id={`${inputId}-hint`} className="mt-1 text-sm text-gray-500">
|
|
338
|
+
{hint}
|
|
339
|
+
</p>
|
|
340
|
+
)}
|
|
341
|
+
</div>
|
|
342
|
+
)
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
Input.displayName = 'Input'
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## 유용한 유틸리티
|
|
350
|
+
|
|
351
|
+
### cn() 함수 (클래스 병합)
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
yarn add clsx tailwind-merge
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
// src/lib/utils.ts
|
|
359
|
+
import { clsx, type ClassValue } from 'clsx'
|
|
360
|
+
import { twMerge } from 'tailwind-merge'
|
|
361
|
+
|
|
362
|
+
export const cn = (...inputs: ClassValue[]) => {
|
|
363
|
+
return twMerge(clsx(inputs))
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
```tsx
|
|
368
|
+
// 사용 예시
|
|
369
|
+
import { cn } from '@/lib/utils'
|
|
370
|
+
|
|
371
|
+
<button
|
|
372
|
+
className={cn(
|
|
373
|
+
'px-4 py-2 rounded-lg',
|
|
374
|
+
isActive && 'bg-blue-600 text-white',
|
|
375
|
+
isDisabled && 'opacity-50 cursor-not-allowed',
|
|
376
|
+
className
|
|
377
|
+
)}
|
|
378
|
+
>
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### class-variance-authority (CVA)
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
yarn add class-variance-authority
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
위의 버튼 컴포넌트 예시 참고.
|
|
388
|
+
|
|
389
|
+
## 반응형 디자인
|
|
390
|
+
|
|
391
|
+
### 브레이크포인트
|
|
392
|
+
|
|
393
|
+
```css
|
|
394
|
+
sm 640px 모바일 가로
|
|
395
|
+
md 768px 태블릿
|
|
396
|
+
lg 1024px 노트북
|
|
397
|
+
xl 1280px 데스크탑
|
|
398
|
+
2xl 1536px 대형 모니터
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### 모바일 퍼스트
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
// 모바일 → 태블릿 → 데스크탑 순서
|
|
405
|
+
<div className="
|
|
406
|
+
p-4 /* 기본: 모바일 */
|
|
407
|
+
md:p-6 /* 768px 이상 */
|
|
408
|
+
lg:p-8 /* 1024px 이상 */
|
|
409
|
+
">
|
|
410
|
+
|
|
411
|
+
// 그리드 반응형
|
|
412
|
+
<div className="
|
|
413
|
+
grid
|
|
414
|
+
grid-cols-1 /* 모바일: 1열 */
|
|
415
|
+
md:grid-cols-2 /* 태블릿: 2열 */
|
|
416
|
+
lg:grid-cols-3 /* 데스크탑: 3열 */
|
|
417
|
+
gap-4 md:gap-6
|
|
418
|
+
">
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## 플러그인 추가
|
|
422
|
+
|
|
423
|
+
### @tailwindcss/forms
|
|
424
|
+
|
|
425
|
+
폼 요소 기본 스타일링:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
yarn add @tailwindcss/forms
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
```css
|
|
432
|
+
@import "tailwindcss";
|
|
433
|
+
@plugin "@tailwindcss/forms";
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### @tailwindcss/typography
|
|
437
|
+
|
|
438
|
+
마크다운/리치 텍스트 스타일링:
|
|
439
|
+
|
|
440
|
+
```bash
|
|
441
|
+
yarn add @tailwindcss/typography
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
```css
|
|
445
|
+
@import "tailwindcss";
|
|
446
|
+
@plugin "@tailwindcss/typography";
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
```tsx
|
|
450
|
+
<article className="prose dark:prose-invert">
|
|
451
|
+
{/* 마크다운 렌더링 콘텐츠 */}
|
|
452
|
+
</article>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## 체크리스트
|
|
456
|
+
|
|
457
|
+
### 설정 시
|
|
458
|
+
|
|
459
|
+
- [ ] @theme으로 디자인 토큰 정의
|
|
460
|
+
- [ ] 브랜드 색상 설정
|
|
461
|
+
- [ ] 의미론적 색상 정의
|
|
462
|
+
- [ ] 폰트 패밀리 설정
|
|
463
|
+
- [ ] 다크 모드 대응
|
|
464
|
+
|
|
465
|
+
### 개발 시
|
|
466
|
+
|
|
467
|
+
- [ ] 일관된 토큰 사용
|
|
468
|
+
- [ ] 모바일 퍼스트 반응형
|
|
469
|
+
- [ ] cn() 함수로 클래스 병합
|
|
470
|
+
- [ ] 접근성 고려 (포커스, 대비)
|