管理 shadcn-svelte 组件和项目——添加、更新、修复、调试、样式化和组合 UI。提供项目上下文、组件文档和使用示例。适用于使用 shadcn-svelte、CLI、设计系统预设或任何包含 components.json 文件的项目。当触发“shadcn-svelte init”、“add component”或注册表 URL 时也会生效。
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 前查看组件。 - 组合,不要重新发明。 设置页面 = Tabs + Card + 表单控件。仪表盘 = 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-*。 使用size-10而非w-10 h-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。data-invalid放在Field上,aria-invalid放在控件上。对于禁用状态:data-disabled放在Field上,disabled放在控件上。
组件结构 → composition.md
- 项目始终位于其 Group 内部。
Select.Item→Select.Group。DropdownMenu.Item→DropdownMenu.Group。Command.Item→Command.Group。 - 自定义触发器。 将控件包裹在
Dialog.Trigger/AlertDialog.Trigger中,或使用bind:open控制根组件的打开状态——参见组件文档。 - Dialog、Sheet 和 Drawer 始终需要标题。
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。 不要构建自定义空状态标记。 - Toast 通过
svelte-sonner。 使用svelte-sonner的toast()函数,配合 UI 文件夹中的 Sonner 组件。 - 使用
Separator代替<hr>或仅带边框类的div。 - 使用
Skeleton作为加载占位符。不要使用自定义的animate-pulsediv。 - 使用
Badge代替自定义样式的 span。
图标 → 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">Email</Field.FieldLabel>
<Input id="email" />
</Field.Field>
</Field.FieldGroup>
<!-- 验证:data-invalid 在 Field 上,aria-invalid 在控件上。 -->
<Field.Field data-invalid>
<Field.FieldLabel for="email">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 配合适当的 variant(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(toast)、Alert、Progress、Skeleton、Spinner |
| 命令面板 | Command 放在 Dialog 内部 |
| 图表 | Chart(LayerChart) |
| 布局 | Card、Separator、Resizable、ScrollArea、Accordion、Collapsible |
| 空状态 | Empty |
| 菜单 | DropdownMenu、ContextMenu、Menubar |
| 工具提示/信息 | Tooltip、HoverCard、Popover |
关键字段
使用 components.json 和文件系统——而不是单独的 info 命令:
aliases→ 使用配置中的实际别名前缀(例如$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的硬编码路径。将导入重写为使用components.json中的项目ui/lib别名。 - 审查添加的组件——添加后,读取添加的文件并验证组合(组、标题、验证属性)。使图标导入与
iconLibrary对齐。 - 远程注册表项——通过 URL 添加是显式的;如果用户想要来自未知来源的组件,请在运行
add之前确认注册表 URL 或项。
更新组件
使用 update 命令从注册表拉取项目中已有组件的最新版本。在 update 之后使用 git diff 审查更改。
- 提交或暂存本地工作。
- 运行
npx shadcn-svelte@latest update [component]或--all。 - 如果自定义了文件,解决合并冲突。
- 在没有用户明确批准的情况下,绝不在
add上使用--overwrite,以免破坏有意的编辑。
快速参考
# 在项目中初始化 shadcn-svelte。
npx shadcn-svelte@latest init
# 使用文档站点构建器中的预设字符串初始化。
npx shadcn-svelte@latest init --preset <code>
# 添加组件(不带名称时交互式)。
npx shadcn-svelte@latest add
npx shadcn-svelte@latest add button card dialog
npx shadcn-svelte@latest add --all
# 更新已安装的组件。
npx shadcn-svelte@latest update button
npx shadcn-svelte@latest update --all --yes
# 构建自定义注册表(注册表作者)。
npx shadcn-svelte@latest registry build
注册表: 默认 https://shadcn-svelte.com/registry——如有需要可在 components.json 中覆盖。
文档: shadcn-svelte.com
详细参考
- rules/forms.md — Field.FieldGroup、Field.Field、InputGroup、ToggleGroup、Field.FieldSet、验证状态
- rules/composition.md — 组、覆盖层、Card、Tabs、Avatar、Alert、Empty、Toast、Separator、Skeleton、Badge、Button 加载状态
- rules/icons.md — data-icon、图标大小、传递图标组件
- rules/styling.md — 语义化颜色、变体、class、间距、尺寸、truncate、暗色模式、cn()、z-index
- cli.md — 命令、标志、注册表
- customization.md — 主题、CSS 变量、扩展组件






