shadcn-svelte

shadcn-svelte

热门

管理 shadcn-svelte 组件和项目——添加、更新、修复、调试、样式化和组合 UI。提供项目上下文、组件文档和使用示例。适用于使用 shadcn-svelte、CLI、设计系统预设或任何包含 components.json 文件的项目。当触发“shadcn-svelte init”、“add component”或注册表 URL 时也会生效。

8994Star
559Fork
更新于 2026/7/28
SKILL.md
readonly只读
name
shadcn-svelte
description

管理 shadcn-svelte 组件和项目——添加、更新、修复、调试、样式化和组合 UI。提供项目上下文、组件文档和使用示例。适用于使用 shadcn-svelte、CLI、设计系统预设或任何包含 components.json 文件的项目。当触发“shadcn-svelte init”、“add component”或注册表 URL 时也会生效。

shadcn-svelte

一个用于构建 Svelte UI、组件和设计系统的框架。组件通过 CLI 以源代码形式添加到用户项目中。

重要: 所有 CLI 命令都使用项目的包管理器运行:npx shadcn-svelte@latestpnpm dlx shadcn-svelte@latestbunx --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.ContentDialog.TitleCard.RootCard.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/...),而不是硬编码路径。

原则

  1. 优先使用现有组件。 运行 npx shadcn-svelte@latest add(不带参数)浏览可用组件,或在编写自定义 UI 前查看组件
  2. 组合,不要重新发明。 设置页面 = Tabs + Card + 表单控件。仪表盘 = Sidebar + Card + Chart + Table。
  3. 优先使用内置变体,而非自定义样式。variant="outline"size="sm" 等。
  4. 使用语义化颜色。bg-primarytext-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-backgroundtext-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.ItemSelect.GroupDropdownMenu.ItemDropdownMenu.GroupCommand.ItemCommand.Group
  • 自定义触发器。 将控件包裹在 Dialog.Trigger / AlertDialog.Trigger 中,或使用 bind:open 控制根组件的打开状态——参见组件文档。
  • Dialog、Sheet 和 Drawer 始终需要标题。 Dialog.TitleSheet.TitleDrawer.Title 是无障碍必需的。如果视觉上隐藏,使用 class="sr-only"
  • 使用完整的 Card 组合。 Card.Header/Card.Title/Card.Description/Card.Content/Card.Footer。不要将所有内容都放在 Card.Content 中。
  • Button 没有 isPending/isLoadingButton 内部组合 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-sonnertoast() 函数,配合 UI 文件夹中的 Sonner 组件。
  • 使用 Separator 代替 <hr> 或仅带边框类的 div
  • 使用 Skeleton 作为加载占位符。不要使用自定义的 animate-pulse div。
  • 使用 Badge 代替自定义样式的 span。

图标 → icons.md

  • <Button> 中的图标使用 data-icon 在图标上使用 data-icon="inline-start"data-icon="inline-end"
  • 组件内部的图标不加尺寸类。 组件通过 CSS 处理图标大小。不使用 size-4w-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 }
表单输入 InputSelectComboboxSwitchCheckboxRadioGroupTextareaInputOTPSlider
在 2-5 个选项间切换 ToggleGroup.Root + ToggleGroup.Item
数据展示 TableCardBadgeAvatar
导航 SidebarNavigationMenuBreadcrumbTabsPagination
覆盖层 Dialog(模态框)、Sheet(侧面板)、Drawer(底部抽屉)、AlertDialog(确认对话框)
反馈 svelte-sonner(toast)、AlertProgressSkeletonSpinner
命令面板 Command 放在 Dialog 内部
图表 Chart(LayerChart)
布局 CardSeparatorResizableScrollAreaAccordionCollapsible
空状态 Empty
菜单 DropdownMenuContextMenuMenubar
工具提示/信息 TooltipHoverCardPopover

关键字段

使用 components.json 和文件系统——而不是单独的 info 命令:

  • aliases → 使用配置中的实际别名前缀(例如 $lib/),绝不硬编码不相关的项目。
  • tailwind.css → 存放主题变量的全局 CSS 文件。编辑此文件进行主题调整;除非用户已经使用另一个全局文件,否则不要添加第二个全局文件。
  • style → 视觉处理(例如 novavega 等)和注册表样式路径。
  • 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。

工作流程

  1. 获取项目上下文——读取 components.json,并在需要时列出 UI 组件目录。
  2. 首先检查已安装的组件——在运行 add 之前,列出已解析的 ui 路径下的文件。不要导入尚未添加的组件,也不要重新添加已存在的组件(除非更新)。
  3. 发现组件——npx shadcn-svelte@latest add(不带参数,交互式列表)或文档站点。
  4. 安装或更新——npx shadcn-svelte@latest add <name> 或注册表 URL。要从注册表刷新现有文件,使用 npx shadcn-svelte@latest update(参见 cli.md)。
  5. 修复第三方/URL 添加项的导入——从自定义注册表 URL 添加后,检查是否有不匹配项目 aliases 的硬编码路径。将导入重写为使用 components.json 中的项目 ui / lib 别名。
  6. 审查添加的组件——添加后,读取添加的文件并验证组合(组、标题、验证属性)。使图标导入与 iconLibrary 对齐。
  7. 远程注册表项——通过 URL 添加是显式的;如果用户想要来自未知来源的组件,请在运行 add 之前确认注册表 URL 或项。

更新组件

使用 update 命令从注册表拉取项目中已有组件的最新版本。在 update 之后使用 git diff 审查更改。

  1. 提交或暂存本地工作。
  2. 运行 npx shadcn-svelte@latest update [component]--all
  3. 如果自定义了文件,解决合并冲突。
  4. 在没有用户明确批准的情况下,绝不在 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 变量、扩展组件