shadcn-svelte은(는) 무엇을 하나요?
Svelte용 UI, 컴포넌트 및 디자인 시스템을 구축하기 위한 프레임워크입니다. 컴포넌트는 CLI를 통해 사용자 프로젝트에 소스로 추가됩니다.
중요: 모든 CLI 명령은 프로젝트의 패키지 러너를 사용하여 실행하세요:
npx shadcn-svelte@latest,pnpm dlx shadcn-svelte@latest, 또는bunx --bun shadcn-svelte@latest— 프로젝트의 패키지 매니저에 따라 적절한 러너를 사용합니다. 아래 예제는npx shadcn-svelte@latest를 사용하지만, 프로젝트에 맞는 올바른 러너로 대체하세요.
현재 프로젝트 컨텍스트
프로젝트 루트에서 components.json을 읽고, 실시간 파일 레이아웃이 필요할 때 aliases.ui 경로(CLI와 동일한 규칙으로 해석)에 있는 디렉토리를 나열하세요.
임포트 (Svelte)
각 컴포넌트는 자체 폴더에 index.ts 배럴 파일과 함께 있습니다. 설치 문서와 일치시킵니다:
- 멀티 파트 컴포넌트 (dialog, select, card, field, tabs, ...):
import * as Dialog from "$lib/components/ui/dialog"그런 다음Dialog.Content,Dialog.Title,Card.Root,Card.Header등 — 배럴이 내보내는 것(짧은 이름 및/또는Root as …별칭)을 사용합니다. - 단일 컴포넌트 배럴 (폴더에 의미 있는 컴포넌트가 하나만 있는 경우): 명명된 임포트 —
import { Button } from "$lib/components/ui/button"그리고<Button>,import * as Button+Button.Root가 아닙니다.{ Input },{ Badge },{ Spinner },{ Checkbox },{ Separator },{ Skeleton }등에도 동일한 패턴을 사용합니다.
import * as Dialog from "$lib/components/ui/dialog";
import { Button } from "$lib/components/ui/button";
import { Separator } from "$lib/components/ui/separator";
components.json의 실제 별칭(종종 $lib/components/ui/...)을 사용하고, 하드코딩된 경로는 사용하지 마세요.
원칙
- 기존 컴포넌트를 먼저 사용하세요. 인수 없이
npx shadcn-svelte@latest add를 실행하여 사용 가능한 컴포넌트를 탐색하거나, 사용자 정의 UI를 작성하기 전에 Components를 확인하세요. - 조합하고, 다시 발명하지 마세요. 설정 페이지 = Tabs + Card + form controls. 대시보드 = Sidebar + Card + Chart + Table.
- 사용자 정의 스타일보다 내장 변형을 먼저 사용하세요.
variant="outline",size="sm"등. - 의미론적 색상을 사용하세요.
bg-primary,text-muted-foreground— 절대bg-blue-500과 같은 원시 값을 사용하지 마세요.
중요 규칙
이 규칙은 항상 적용됩니다. 각 규칙은 올바르지 않은/올바른 코드 쌍이 있는 파일에 연결됩니다.
스타일링 및 Tailwind → styling.md
class는 레이아웃에 사용하고, 스타일링에는 사용하지 마세요. 컴포넌트 색상이나 타이포그래피를 절대 재정의하지 마세요.space-x-*또는space-y-*를 사용하지 마세요.flex와gap-*를 사용하세요. 수직 스택의 경우flex flex-col gap-*를 사용하세요.- 너비와 높이가 같을 때는
size-*를 사용하세요.w-10 h-10대신size-10. truncate단축어를 사용하세요.overflow-hidden text-ellipsis whitespace-nowrap를 사용하지 마세요.- 수동
dark:색상 재정의를 하지 마세요. 의미론적 토큰(bg-background,text-muted-foreground)을 사용하세요. - 조건부 클래스에는
cn()을 사용하세요. 수동 템플릿 리터럴 삼항 연산자를 작성하지 마세요. - 오버레이 컴포넌트에서 수동
z-index를 사용하지 마세요. Dialog, Sheet, Popover 등은 자체 스택을 처리합니다.
폼 및 입력 → forms.md
- 폼은
Field.FieldGroup+Field.Field를 사용합니다. 폼 레이아웃에 원시div와space-y-*또는grid gap-*를 절대 사용하지 마세요. InputGroup은InputGroup.Input/InputGroup.Textarea를 사용합니다.InputGroup.Root내부에서 원시Input/Textarea를 절대 사용하지 마세요.- 입력 내부의 버튼은
InputGroup.Root+InputGroup.Addon을 사용합니다. - 옵션 세트(2–7개 선택지)는
ToggleGroup을 사용합니다. 수동 활성 상태로Button을 반복하지 마세요. - 관련 체크박스/라디오 그룹화에는
Field.FieldSet+Field.FieldLegend를 사용합니다. 제목이 있는div를 사용하지 마세요. - 필드 유효성 검사는
data-invalid+aria-invalid를 사용합니다.Field에는data-invalid, 컨트롤에는aria-invalid를 사용합니다. 비활성화의 경우:Field에는data-disabled, 컨트롤에는disabled.
컴포넌트 구조 → composition.md
- 항목은 항상 해당 그룹 내에 있어야 합니다.
Select.Item→Select.Group.DropdownMenu.Item→DropdownMenu.Group.Command.Item→Command.Group. - 사용자 정의 트리거. 컨트롤을
Dialog.Trigger/AlertDialog.Trigger로 감싸거나, 루트에서bind:open으로 열림 상태를 제어합니다 — 컴포넌트 문서를 참조하세요. - Dialog, Sheet, Drawer는 항상 Title이 필요합니다. 접근성을 위해
Dialog.Title,Sheet.Title,Drawer.Title이 필요합니다. 시각적으로 숨길 경우class="sr-only"를 사용하세요. - 전체 Card 구성을 사용하세요.
Card.Header/Card.Title/Card.Description/Card.Content/Card.Footer. 모든 것을Card.Content에 넣지 마세요. - Button에는
isPending/isLoading이 없습니다.Button내부에Spinner+disabled로 구성하고,Spinner에data-icon="inline-start"/inline-end를 사용하여 올바른 간격을 만드세요 (import { Button },import { Spinner }). Tabs.Trigger는 반드시Tabs.List안에 있어야 합니다. 트리거를Tabs에 직접 렌더링하지 마세요.Avatar는 항상Avatar.Fallback이 필요합니다. 이미지 로드 실패 시를 대비합니다.
컴포넌트 사용, 사용자 정의 마크업 사용 금지 → composition.md
- 사용자 정의 마크업 전에 기존 컴포넌트를 먼저 사용하세요. 스타일이 지정된
div를 작성하기 전에 컴포넌트가 있는지 확인하세요. - 콜아웃은
Alert를 사용하세요. 사용자 정의 스타일 div를 만들지 마세요. - 빈 상태는
Empty를 사용하세요. 사용자 정의 빈 상태 마크업을 만들지 마세요. - 토스트는
svelte-sonner를 통해 사용하세요. UI 폴더의 Sonner 컴포넌트와 함께svelte-sonner의toast()를 사용하세요. <hr>또는 테두리 전용 클래스가 있는div대신Separator를 사용하세요.- 로딩 플레이스홀더에는
Skeleton을 사용하세요. 사용자 정의animate-pulsediv를 사용하지 마세요. - 사용자 정의 스타일 span 대신
Badge를 사용하세요.
아이콘 → icons.md
<Button>의 아이콘은data-icon을 사용합니다. 아이콘에data-icon="inline-start"또는data-icon="inline-end"를 사용하세요.- 컴포넌트 내부 아이콘에 크기 클래스를 사용하지 마세요. 컴포넌트는 CSS를 통해 아이콘 크기를 처리합니다.
size-4또는w-4 h-4를 사용하지 마세요. - 아이콘을 컴포넌트로 전달하세요. 문자열 키가 아닌 구성된
iconLibrary(예:@lucide/svelte)에서 가져오세요.
CLI
- 프리셋 — shadcn-svelte.com의 디자인 시스템 빌더에서 인코딩된 문자열을 복사하여
npx shadcn-svelte@latest init --preset <code>에 전달하세요.
주요 패턴
다음은 올바른 shadcn-svelte 코드를 구분하는 가장 일반적인 패턴입니다. 엣지 케이스는 위의 연결된 규칙 파일을 참조하세요.
<script lang="ts">
import * as Field from "$lib/components/ui/field";
import { Input } from "$lib/components/ui/input";
import { Button } from "$lib/components/ui/button";
import SearchIcon from "@lucide/svelte/icons/search";
import { Badge } from "$lib/components/ui/badge";
import * as Avatar from "$lib/components/ui/avatar";
</script>
<!-- 폼 레이아웃: Field.FieldGroup + Field.Field, div + Label이 아닙니다. -->
<Field.FieldGroup>
<Field.Field>
<Field.FieldLabel for="email">이메일</Field.FieldLabel>
<Input id="email" />
</Field.Field>
</Field.FieldGroup>
<!-- 유효성 검사: Field에는 data-invalid, 컨트롤에는 aria-invalid. -->
<Field.Field data-invalid>
<Field.FieldLabel for="email">이메일</Field.FieldLabel>
<Input id="email" aria-invalid />
<Field.FieldDescription>잘못된 이메일입니다.</Field.FieldDescription>
</Field.Field>
<!-- 버튼의 아이콘: data-icon, 크기 클래스 없음. -->
<Button>
<SearchIcon data-icon="inline-start" />
검색
</Button>
<!-- 간격: gap-*, space-y-*가 아닙니다. -->
<div class="flex flex-col gap-4"></div>
<!-- 동일한 치수: size-*, w-* h-*가 아닙니다. -->
<Avatar.Root class="size-10">
<Avatar.Image src="/u.png" alt="사용자" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar.Root>
<!-- 상태 색상: Badge 변형 또는 의미론적 토큰, 원시 색상이 아닙니다. -->
<Badge variant="secondary">+20.1%</Badge>
컴포넌트 선택
| 필요 사항 | 사용 |
|---|---|
| 버튼/액션 | 적절한 변형과 함께 Button (import { Button }) |
| 폼 입력 | Input, Select, Combobox, Switch, Checkbox, RadioGroup, Textarea, InputOTP, Slider |
| 2–5개 옵션 간 토글 | ToggleGroup.Root + ToggleGroup.Item |
| 데이터 표시 | Table, Card, Badge, Avatar |
| 내비게이션 | Sidebar, NavigationMenu, Breadcrumb, Tabs, Pagination |
| 오버레이 | Dialog (모달), Sheet (사이드 패널), Drawer (바텀 시트), AlertDialog (확인) |
| 피드백 | svelte-sonner (토스트), Alert, Progress, Skeleton, Spinner |
| 명령 팔레트 | Dialog 내부의 Command |
| 차트 | Chart (LayerChart) |
| 레이아웃 | Card, Separator, Resizable, ScrollArea, Accordion, Collapsible |
| 빈 상태 | Empty |
| 메뉴 | DropdownMenu, ContextMenu, Menubar |
| 툴팁/정보 | Tooltip, HoverCard, Popover |
주요 필드
별도의 info 명령이 아닌 components.json과 파일 시스템을 사용하세요:
aliases→ config의 실제 별칭 접두사(예:$lib/)를 사용하고, 관련 없는 프로젝트를 하드코딩하지 마세요.tailwind.css→ 테마 변수가 있는 전역 CSS 파일입니다. 테마 조정을 위해 이 파일을 편집하고, 사용자가 이미 사용하지 않는 한 두 번째 전역 파일을 추가하지 마세요.style→ 시각적 처리(예:nova,vega, …) 및 레지스트리 스타일 경로.iconLibrary→ 아이콘 패키지를 결정합니다(@lucide/svelte,@tabler/icons-svelte등).@lucide/svelte를 가정하지 마세요.registry→ CLI가 컴포넌트를 가져오는 위치; 기본 공식 레지스트리는shadcn-svelte.com입니다.resolvedPaths(개념적) → CLI가aliases를 절대 경로로 해석합니다. 디스크에서aliases.ui를 나열하여 설치된 컴포넌트를 확인하세요.
명령 및 플래그는 cli.md를 참조하세요.
컴포넌트 문서, 예제 및 사용법
문서와 예제를 보려면 https://shadcn-svelte.com/docs/components/<name>.md를 여세요. 컴포넌트를 생성, 수정, 디버깅 또는 사용할 때는 먼저 공식 페이지를 읽어 문서화된 API를 따르세요.
워크플로
- 프로젝트 컨텍스트 가져오기 —
components.json을 읽고 필요할 때 UI 컴포넌트 디렉토리를 나열하세요. - 먼저 설치된 컴포넌트 확인 —
add를 실행하기 전에 해결된ui경로 아래의 파일을 나열하세요. 추가되지 않은 컴포넌트는 임포트하지 말고, 이미 있는 컴포넌트는 업데이트하지 않는 한 다시 추가하지 마세요. - 컴포넌트 검색 — 인수 없이
npx shadcn-svelte@latest add(대화형 목록) 또는 문서 사이트를 사용하세요. - 설치 또는 업데이트 —
npx shadcn-svelte@latest add <name>또는 레지스트리 URL. 레지스트리에서 기존 파일을 새로 고치려면npx shadcn-svelte@latest update를 사용하세요 (cli.md 참조). - 서드파티 / URL로 추가된 항목의 임포트 수정 — 사용자 정의 레지스트리 URL에서 추가한 후, 프로젝트의
aliases와 일치하지 않는 하드코딩된 경로가 있는지 확인하세요. 프로젝트의ui/lib별칭을components.json에서 가져오도록 임포트를 다시 작성하세요. - 추가된 컴포넌트 검토 — 추가한 후, 추가된 파일을 읽고 구성(그룹, 제목, 유효성 검사 속성)을 확인하세요. 아이콘 임포트를
iconLibrary와 일치시키세요. - 원격 레지스트리 항목 — URL로 추가하는 것은 명시적입니다. 사용자가 알 수 없는 소스에서 컴포넌트를 원하는 경우,
add를 실행하기 전에 레지스트리 URL 또는 항목을 확인하세요.
DESIGN.md의 디자인 시스템
사용자가 프리셋 유무에 관계없이 DESIGN.md(또는 브랜드 사양)에서 디자인 시스템을 요청하는 경우, design-system.md를 처음부터 끝까지 따르세요:
- 새 앱의 경우,
npx sv create <app>로 SvelteKit을 스캐폴딩하고(또는 요청 시 Svelte + Vite),npx shadcn-svelte@latest init --preset <code>로 초기화합니다. 코드가 없으면 DESIGN.md에 맞는 스타일을 선택하고 이름을 전달합니다(예:init --preset luma). React 프리셋 코드와 스캐폴딩 플래그는 적용되지 않습니다. 기존 앱에서는 로컬 사용자 정의를 유지합니다. - 새 앱에서는
add --all --yes로 모든 컴포넌트를 설치하고, 기존 앱에서는 누락된 컴포넌트만 추가합니다. - 편집하기 전에 DESIGN.md의 프론트매터, Do's and Don'ts 및 Known Gaps를 읽으세요.
- 해당 토큰을
components.json의tailwind.css에 있는 변수에 매핑합니다. 반경 비율, 그림자, 글꼴 및type-*유틸리티를 고정합니다. - 설치된
tailwind-variants변형 및 관련 스타일 CSS를 다시 스타일링합니다. 컨트롤 높이를 함께 변경합니다. - design-system-page.md에 따라 페이지를 빌드합니다: 대비 확인된 색상 역할, 서체 견본, 고정된 상태 매트릭스, 엣지 케이스, do/don't 쌍, 레시피.
scripts/showcase-coverage.mjs로 임포트를 확인한 다음, 모든 컴포넌트가 렌더링되는지 확인합니다. - 브라우저에서 확인:
svelte-check, SSR을 포함한 프로덕션 빌드, 콘솔 오류 없음, 최상단 로드, 수평 오버플로우 없음, 다크 모드.
컴포넌트 업데이트
update 명령을 사용하여 프로젝트에 이미 있는 컴포넌트의 최신 레지스트리 버전을 가져옵니다. update 후 git diff로 변경 사항을 검토하세요.
- 로컬 작업을 커밋하거나 스태시합니다.
npx shadcn-svelte@latest update [component]또는--all을 실행합니다.- 파일을 사용자 정의한 경우 병합 충돌을 해결합니다.
- 의도적인 편집을 파괴할 경우 사용자의 명시적 승인 없이
add에--overwrite를 절대 사용하지 마세요.
빠른 참조
# 프로젝트에서 shadcn-svelte 초기화
…
[번역을 위해 잘림]