@choblue/claude-code-toolkit 1.2.3 → 1.2.4
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
27c83ec4fadcaf1ee2f771651fa76d31262a831a
|
|
@@ -313,7 +313,82 @@ function UserPage({ userId }: UserPageProps) {
|
|
|
313
313
|
|
|
314
314
|
---
|
|
315
315
|
|
|
316
|
-
## 9.
|
|
316
|
+
## 9. 접근성 (a11y)
|
|
317
|
+
|
|
318
|
+
### 시맨틱 HTML 사용
|
|
319
|
+
- 클릭 가능한 요소는 반드시 `<button>` 또는 `<a>`를 사용한다
|
|
320
|
+
- `<div onClick>`, `<span onClick>`을 금지한다
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// Bad
|
|
324
|
+
<div onClick={handleDelete} className="cursor-pointer">삭제</div>
|
|
325
|
+
|
|
326
|
+
// Good
|
|
327
|
+
<button type="button" onClick={handleDelete}>삭제</button>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 아이콘 버튼에 aria-label 필수
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
// Bad - 스크린 리더가 내용을 알 수 없음
|
|
334
|
+
<button onClick={onClose}><XIcon /></button>
|
|
335
|
+
|
|
336
|
+
// Good
|
|
337
|
+
<button onClick={onClose} aria-label="닫기"><XIcon /></button>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### 이미지에 alt, width, height 필수
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
// Bad
|
|
344
|
+
<img src={user.avatar} />
|
|
345
|
+
|
|
346
|
+
// Good
|
|
347
|
+
<img src={user.avatar} alt={`${user.name} 프로필`} width={40} height={40} />
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### focus-visible 보장
|
|
351
|
+
- `outline: none`을 사용할 때 반드시 `focus-visible` 대체 스타일을 제공한다
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
// Bad - 포커스 표시 완전 제거
|
|
355
|
+
<button className="outline-none">
|
|
356
|
+
|
|
357
|
+
// Good - 키보드 포커스 시 표시
|
|
358
|
+
<button className="outline-none focus-visible:ring-2 focus-visible:ring-blue-500">
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### 폼 접근성
|
|
362
|
+
- 모든 입력 필드에 `<label>` 또는 `aria-label`을 연결한다
|
|
363
|
+
- 적절한 `type`, `inputMode`, `autoComplete` 속성을 사용한다
|
|
364
|
+
- 붙여넣기(`onPaste`)를 차단하지 않는다
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 10. UX 패턴
|
|
369
|
+
|
|
370
|
+
### 파괴적 액션에 확인 단계
|
|
371
|
+
- 삭제, 초기화 등 되돌릴 수 없는 동작에는 확인 UI를 추가한다
|
|
372
|
+
|
|
373
|
+
### URL 파라미터와 UI 상태 동기화
|
|
374
|
+
- 탭, 필터, 페이지 등 공유 가능한 UI 상태는 URL 파라미터에 반영한다
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
// Bad - 새로고침하면 상태 소실
|
|
378
|
+
const [tab, setTab] = useState('overview');
|
|
379
|
+
|
|
380
|
+
// Good - URL에 상태 반영 (deep-link 가능)
|
|
381
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
382
|
+
const tab = searchParams.get('tab') ?? 'overview';
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### 대규모 리스트 가상화
|
|
386
|
+
- 50개 이상의 항목을 렌더링할 때는 가상화 라이브러리를 사용한다
|
|
387
|
+
- `@tanstack/react-virtual`, `react-window` 등을 활용한다
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## 11. 금지 사항
|
|
317
392
|
|
|
318
393
|
- `any` 타입 사용 금지
|
|
319
394
|
- 인라인 스타일(`style={{}}`) 사용 금지 - 프로젝트 스타일링 방식을 따른다
|
|
@@ -325,4 +400,8 @@ function UserPage({ userId }: UserPageProps) {
|
|
|
325
400
|
- `useEffect` 내에서 상태 동기화 로직 작성 금지 (파생값으로 처리)
|
|
326
401
|
- Props drilling이 3단계 이상일 때 Context 또는 상태 관리 라이브러리 미사용 금지
|
|
327
402
|
- 서버 상태(API 데이터)를 `useState` + `useEffect`로 관리 금지 (서버 상태 라이브러리 사용)
|
|
328
|
-
- 각 함수/컴포넌트마다 try-catch 남발 금지 (에러 경계에서 일괄 처리)
|
|
403
|
+
- 각 함수/컴포넌트마다 try-catch 남발 금지 (에러 경계에서 일괄 처리)
|
|
404
|
+
- `<div onClick>`, `<span onClick>` 금지 (`<button>` 또는 `<a>` 사용)
|
|
405
|
+
- 아이콘 버튼에 `aria-label` 누락 금지
|
|
406
|
+
- `outline: none` 단독 사용 금지 (`focus-visible` 대체 필수)
|
|
407
|
+
- 입력 필드에 `onPaste` 차단 금지
|
|
@@ -361,7 +361,43 @@ export function Button({ variant, size, className, ...props }: ButtonProps) {
|
|
|
361
361
|
|
|
362
362
|
---
|
|
363
363
|
|
|
364
|
-
## 8.
|
|
364
|
+
## 8. 트랜지션 & 모션
|
|
365
|
+
|
|
366
|
+
### transition 속성 명시
|
|
367
|
+
- `transition-all` 사용을 금지한다 - 변경되는 속성만 명시한다
|
|
368
|
+
- 불필요한 속성까지 트랜지션되면 성능이 저하된다
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
// Bad - 모든 속성에 트랜지션
|
|
372
|
+
<button className="transition-all">
|
|
373
|
+
|
|
374
|
+
// Good - 필요한 속성만
|
|
375
|
+
<button className="transition-colors">
|
|
376
|
+
<div className="transition-[transform,opacity]">
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### prefers-reduced-motion 존중
|
|
380
|
+
- 애니메이션/트랜지션이 있는 요소에는 `motion-reduce:` 변형을 고려한다
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
// 모션 감소 선호 시 애니메이션 비활성화
|
|
384
|
+
<div className="animate-bounce motion-reduce:animate-none">
|
|
385
|
+
<div className="transition-transform motion-reduce:transition-none">
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### 다크 모드 color-scheme
|
|
389
|
+
- 다크 모드 지원 시 `color-scheme: dark`를 설정하여 네이티브 UI(스크롤바, 입력 필드 등)도 다크 테마에 맞춘다
|
|
390
|
+
|
|
391
|
+
```css
|
|
392
|
+
/* app.css */
|
|
393
|
+
.dark {
|
|
394
|
+
color-scheme: dark;
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## 9. 금지 사항
|
|
365
401
|
|
|
366
402
|
- 인라인 `style={{}}` 사용 금지 - Tailwind 유틸리티 클래스를 사용한다
|
|
367
403
|
- 임의값(arbitrary values) 남용 금지 - `w-[137px]` 같은 임의값은 최소화한다
|
|
@@ -373,6 +409,7 @@ export function Button({ variant, size, className, ...props }: ButtonProps) {
|
|
|
373
409
|
- Tailwind 기본 테마 토큰 삭제 금지 - `@theme`에서 필요한 토큰만 추가한다
|
|
374
410
|
- 사용하지 않는 커스텀 색상/간격 정의 금지 - 실제 사용하는 값만 정의한다
|
|
375
411
|
- `tailwind.config.ts` 사용 금지 - v4에서는 CSS `@theme`으로 설정한다
|
|
412
|
+
- `transition-all` 사용 금지 - 변경되는 속성만 명시한다 (`transition-colors`, `transition-opacity` 등)
|
|
376
413
|
- 클래스 문자열 동적 생성 금지 - Tailwind의 JIT가 감지하지 못한다
|
|
377
414
|
|
|
378
415
|
```typescript
|