Token导航 LogoToken导航TokenDH.com
前端设计需要联网github未标认证来源可访问clear审计通过

shadcn-svelte-skillshadcn/ui Svelte 技能

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

210

周安装

9

GitHub Stars

4

下载量

73
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:shadcn-svelte-skill(shadcn/ui Svelte 技能)
来源仓库:https://github.com/linehaul-ai/linehaulai-claude-marketplace
仓库路径:skills/shadcn-svelte-skill
安装命令:
npx skills add https://github.com/linehaul-ai/linehaulai-claude-marketplace --skill shadcn-svelte-skill
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/linehaul-ai/linehaulai-claude-marketplace --skill shadcn-svelte-skill

简介

shadcn-svelte-skill 提供生产级 UI 组件,支持 Svelte 框架开发。

  • 适合在 Codex、Claude、Cursor 等宿主中构建可访问的应用界面。
  • 通过 npx skills add 命令从指定仓库安装并使用。
  • 使用时需结合项目现有设计系统,避免引入依赖锁定风险。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

shadcn-svelte with Tailwind v4.1 + Vite

A comprehensive guide for working with shadcn-svelte, the Svelte port of shadcn/ui. This skill covers component installation, customization, and integration patterns for Svelte and SvelteKit projects using Tailwind CSS v4.1 with the @tailwindcss/vite plugin.

When to Use

Use shadcn-svelte when:

  • Building component-based Svelte/SvelteKit applications
  • You need accessible, styled UI elements (buttons, forms, modals, dialogs, etc.)
  • You want customizable components that don't lock you into a UI library
  • You're using Tailwind CSS v4.1 with Vite for zero-runtime CSS
  • You need complex components like data tables, drawers, or navigation menus
  • You want TypeScript support with full type safety

Do NOT use for lightweight static sites or when you prefer minimal dependencies.

Svelte Component Library Ecosystem

While this skill focuses on shadcn-svelte, here's the broader Svelte UI landscape to help you choose:

Library Comparison

LibraryTypeBest ForLearning Curve
shadcn-svelteCopy-paste componentsFull customization, TypeScript-firstMedium
Skeleton UIInstallable packageRapid development, themesLow
Melt UIHeadless primitivesMaximum accessibility controlHigh
CustomBuilt from scratchUnique requirementsVaries

Skeleton UI

Full-featured component library with built-in theming:

npm install @skeletonlabs/skeleton @skeletonlabs/tw-plugin
<script>
  import { AppBar, AppShell } from '@skeletonlabs/skeleton';
</script>

<AppShell>
  <svelte:fragment slot="header">
    <AppBar>My App</AppBar>
  </svelte:fragment>
  <slot />
</AppShell>

Use when: You want rapid development with pre-built themes and don't need deep customization.

Melt UI

Headless, accessible primitives—you bring the styling:

npm install @melt-ui/svelte
<script>
  import { createDialog, melt } from '@melt-ui/svelte';

  const { trigger, overlay, content, title, close } = createDialog();
</script>

<button use:melt={$trigger}>Open</button>

{#if $open}
  <div use:melt={$overlay} class="fixed inset-0 bg-black/50" />
  <div use:melt={$content} class="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white p-6 rounded-lg">
    <h2 use:melt={$title}>Dialog Title</h2>
    <button use:melt={$close}>Close</button>
  </div>
{/if}

Use when: You need complete styling control with guaranteed accessibility.

Quick Add Workflow

For simple component additions across libraries:

# shadcn-svelte (recommended for this skill)
npx shadcn-svelte@latest add button card dialog

# Skeleton UI
npm install @skeletonlabs/skeleton

# Melt UI
npm install @melt-ui/svelte

For complex multi-component features, see the workflows.md reference document.

Core Concepts

shadcn-svelte is copy-paste component infrastructure, not a traditional npm package. You own the code—components live in your $lib/components/ui/ directory. This means:

  • Full customization without forking
  • No version lock-in (upgrade on your schedule)
  • TypeScript-first with Svelte 5 reactive variables
  • Tailwind v4.1 with @tailwindcss/vite for zero-runtime styling
  • Built on Bits UI primitives for accessibility
  • CSS variables for dynamic theming

Setup: SvelteKit with Tailwind v4.1

1. Create SvelteKit Project

pnpm dlx sv create my-app
cd my-app

2. Install Tailwind v4.1 + @tailwindcss/vite

pnpm i -D tailwindcss @tailwindcss/vite
pnpm dlx shadcn-svelte@latest init

3. Configure Vite with Tailwind Plugin

Edit vite.config.ts:

import { defineConfig } from 'vite'
import { sveltekit } from '@sveltejs/kit/vite'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [tailwindcss(), sveltekit()],
})

4. Update CSS Entry Point

Edit src/app.css (remove old @tailwind directives):

@import "tailwindcss";

/* Your custom CSS here */
@layer utilities {
  .btn-custom {
    @apply px-4 py-2 rounded-lg font-semibold transition-colors;
  }
}

No separate tailwind.config.js needed—Tailwind v4.1 scans content automatically. If you need custom configuration:

// tailwind.config.js (optional)
export default {
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#f9fafb',
          // ...
        },
      },
    },
  },
  plugins: [],
}

5. Ensure CSS is Imported in Layout

Edit src/routes/+layout.svelte:

<script>
  import '../app.css'
</script>

<slot />

The init command:

  • Sets up @tailwindcss/vite plugin in vite.config.ts
  • Creates src/app.css with @import "tailwindcss"
  • Creates the cn() utility function for class merging
  • Configures path aliases

Add Components

# Add individual components
pnpm dlx shadcn-svelte@latest add button

# Add multiple at once
pnpm dlx shadcn-svelte@latest add card alert dialog

# Add all components
pnpm dlx shadcn-svelte@latest add --all

# View all available components
pnpm dlx shadcn-svelte@latest list

Components install to: src/lib/components/ui/[component-name]/

Common Workflows

Basic Component Usage

<script lang="ts">
  import { Button } from "$lib/components/ui/button";
</script>

<Button variant="default">Click me</Button>
<Button variant="outline">Outlined</Button>
<Button variant="destructive">Delete</Button>
<Button disabled>Disabled</Button>

Form with Validation

pnpm dlx shadcn-svelte@latest add form input label
<script lang="ts">
  import { superForm } from "sveltekit-superforms";
  import { zodClient } from "sveltekit-superforms/adapters";
  import { z } from "zod";
  import * as Form from "$lib/components/ui/form";
  import { Input } from "$lib/components/ui/input";
  import { Button } from "$lib/components/ui/button";

  const schema = z.object({
    email: z.string().email(),
    name: z.string().min(2),
  });

  const form = superForm(data.form, {
    validators: zodClient(schema),
  });

  const { form: formData, enhance } = form;
</script>

<form method="POST" use:enhance>
  <Form.Field {form} name="email">
    <Form.Control let:attrs>
      <Form.Label>Email</Form.Label>
      <Input {...attrs} type="email" bind:value={$formData.email} />
    </Form.Control>
    <Form.FieldErrors />
  </Form.Field>

  <Button type="submit">Submit</Button>
</form>

Data Table with TanStack Table v8

For production data tables, use TanStack Table v8 (not svelte-headless-table) for advanced features like sorting, filtering, pagination, and row selection.

Installation

# Add table components and helpers
pnpm dlx shadcn-svelte@latest add table data-table button dropdown-menu checkbox input

# Install TanStack Table core
pnpm add @tanstack/table-core

Project Structure for Data Tables

routes/your-route/
  columns.ts                          # Column definitions
  data-table.svelte                   # Main table component
  data-table-actions.svelte           # Row action menus
  data-table-checkbox.svelte          # Selection checkboxes
  data-table-[field]-button.svelte    # Sortable headers
  +page.svelte                        # Page using the table

Basic Data Table Setup

Step 1: Define Columns (columns.ts)

import type { ColumnDef } from "@tanstack/table-core";
import { renderComponent, renderSnippet } from "$lib/components/ui/data-table/index.js";
import { createRawSnippet } from "svelte";

export type Payment = {
  id: string;
  amount: number;
  status: "pending" | "processing" | "success" | "failed";
  email: string;
};

export const columns: ColumnDef<Payment>[] = [
  // Simple text column
  {
    accessorKey: "status",
    header: "Status",
  },

  // Formatted cell with snippet
  {
    accessorKey: "amount",
    header: () => {
      const snippet = createRawSnippet(() => ({
        render: () => `<div class="text-end">Amount</div>`,
      }));
      return renderSnippet(snippet);
    },
    cell: ({ row }) => {
      const snippet = createRawSnippet<[{ value: number }]>((getValue) => {
        const { value } = getValue();
        const formatted = new Intl.NumberFormat("en-US", {
          style: "currency",
          currency: "USD",
        }).format(value);
        return {
          render: () => `<div class="text-end font-medium">${formatted}</div>`,
        };
      });
      return renderSnippet(snippet, { value: row.original.amount });
    },
  },

  // Component-based cell (for complex UI like action menus)
  {
    id: "actions",
    cell: ({ row }) => renderComponent(DataTableActions, { payment: row.original }),
  },
];

Step 2: Create Table Component (data-table.svelte)

<script lang="ts" generics="TData, TValue">
  import {
    type ColumnDef,
    type PaginationState,
    type SortingState,
    getCoreRowModel,
    getPaginationRowModel,
    getSortedRowModel,
  } from "@tanstack/table-core";
  import { createSvelteTable, FlexRender } from "$lib/components/ui/data-table/index.js";
  import * as Table from "$lib/components/ui/table/index.js";
  import { Button } from "$lib/components/ui/button/index.js";

  type DataTableProps<TData, TValue> = {
    data: TData[];
    columns: ColumnDef<TData, TValue>[];
  };

  let { data, columns }: DataTableProps<TData, TValue> = $props();

  // State management with Svelte 5 runes
  let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: 10 });
  let sorting = $state<SortingState>([]);

  const table = createSvelteTable({
    get data() { return data; },
    columns,
    state: {
      get pagination() { return pagination; },
      get sorting() { return sorting; },
    },
    onPaginationChange: (updater) => {
      pagination = typeof updater === "function" ? updater(pagination) : updater;
    },
    onSortingChange: (updater) => {
      sorting = typeof updater === "function" ? updater(sorting) : updater;
    },
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
  });
</script>

<div class="w-full">
  <div class="rounded-md border">
    <Table.Root>
      <Table.Header>
        {#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
          <Table.Row>
            {#each headerGroup.headers as header (header.id)}
              <Table.Head>
                {#if !header.isPlaceholder}
                  <FlexRender
                    content={header.column.columnDef.header}
                    context={header.getContext()}
                  />
                {/if}
              </Table.Head>
            {/each}
          </Table.Row>
        {/each}
      </Table.Header>
      <Table.Body>
        {#each table.getRowModel().rows as row (row.id)}
          <Table.Row>
            {#each row.getVisibleCells() as cell (cell.id)}
              <Table.Cell>
                <FlexRender
                  content={cell.column.columnDef.cell}
                  context={cell.getContext()}
                />
              </Table.Cell>
            {/each}
          </Table.Row>
        {:else}
          <Table.Row>
            <Table.Cell colspan={columns.length} class="h-24 text-center">
              No results.
            </Table.Cell>
          </Table.Row>
        {/each}
      </Table.Body>
    </Table.Root>
  </div>

  <!-- Pagination controls -->
  <div class="flex items-center justify-end space-x-2 pt-4">
    <Button
      variant="outline"
      size="sm"
      onclick={() => table.previousPage()}
      disabled={!table.getCanPreviousPage()}
    >
      Previous
    </Button>
    <Button
      variant="outline"
      size="sm"
      onclick={() => table.nextPage()}
      disabled={!table.getCanNextPage()}
    >
      Next
    </Button>
  </div>
</div>

Step 3: Use in Page (+page.svelte)

<script lang="ts">
  import DataTable from "./data-table.svelte";
  import { columns } from "./columns.js";

  let { data } = $props();
</script>

<DataTable data={data.payments} {columns} />

Adding Sorting to Columns

Create sortable header button component (data-table-email-button.svelte):

<script lang="ts">
  import type { ComponentProps } from "svelte";
  import ArrowUpDownIcon from "@lucide/svelte/icons/arrow-up-down";
  import { Button } from "$lib/components/ui/button/index.js";

  let { variant = "ghost", ...restProps }: ComponentProps<typeof Button> = $props();
</script>

<Button {variant} {...restProps}>
  Email
  <ArrowUpDownIcon class="ms-2" />
</Button>

Update column definition:

{
  accessorKey: "email",
  header: ({ column }) => renderComponent(DataTableEmailButton, {
    onclick: column.getToggleSortingHandler(),
  }),
}

Adding Filtering

Add to data-table.svelte:

<script lang="ts" generics="TData, TValue">
  import {
    type ColumnFiltersState,
    getFilteredRowModel,
  } from "@tanstack/table-core";
  import { Input } from "$lib/components/ui/input/index.js";

  let columnFilters = $state<ColumnFiltersState>([]);

  const table = createSvelteTable({
    // ... existing config
    state: {
      get columnFilters() { return columnFilters; },
    },
    onColumnFiltersChange: (updater) => {
      columnFilters = typeof updater === "function" ? updater(columnFilters) : updater;
    },
    getFilteredRowModel: getFilteredRowModel(),
  });
</script>

<!-- Add above table -->
<div class="flex items-center py-4">
  <Input
    placeholder="Filter emails..."
    value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
    oninput={(e) => table.getColumn("email")?.setFilterValue(e.currentTarget.value)}
    onchange={(e) => table.getColumn("email")?.setFilterValue(e.currentTarget.value)}
    class="max-w-sm"
  />
</div>

Adding Row Selection

Create checkbox component (data-table-checkbox.svelte):

<script lang="ts">
  import type { ComponentProps } from "svelte";
  import { Checkbox } from "$lib/components/ui/checkbox/index.js";

  let {
    checked = false,
    onCheckedChange = (v) => (checked = v),
    ...restProps
  }: ComponentProps<typeof Checkbox> = $props();
</script>

<Checkbox bind:checked={() => checked, onCheckedChange} {...restProps} />

Add select column to columns.ts:

{
  id: "select",
  header: ({ table }) => renderComponent(DataTableCheckbox, {
    checked: table.getIsAllPageRowsSelected(),
    indeterminate: table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected(),
    onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
    "aria-label": "Select all",
  }),
  cell: ({ row }) => renderComponent(DataTableCheckbox, {
    checked: row.getIsSelected(),
    onCheckedChange: (value) => row.toggleSelected(!!value),
    "aria-label": "Select row",
  }),
  enableSorting: false,
  enableHiding: false,
}

Add to data-table.svelte:

<script lang="ts" generics="TData, TValue">
  import { type RowSelectionState } from "@tanstack/table-core";

  let rowSelection = $state<RowSelectionState>({});

  const table = createSvelteTable({
    // ... existing config
    state: {
      get rowSelection() { return rowSelection; },
    },
    onRowSelectionChange: (updater) => {
      rowSelection = typeof updater === "function" ? updater(rowSelection) : updater;
    },
  });
</script>

<!-- Show selection count -->
<div class="text-muted-foreground flex-1 text-sm">
  {table.getFilteredSelectedRowModel().rows.length} of{" "}
  {table.getFilteredRowModel().rows.length} row(s) selected.
</div>

Row Actions Pattern

Create actions component (data-table-actions.svelte):

<script lang="ts">
  import EllipsisIcon from "@lucide/svelte/icons/ellipsis";
  import { Button } from "$lib/components/ui/button/index.js";
  import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js";

  let { id }: { id: string } = $props();
</script>

<DropdownMenu.Root>
  <DropdownMenu.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="ghost" size="icon" class="relative size-8 p-0">
        <span class="sr-only">Open menu</span>
        <EllipsisIcon />
      </Button>
    {/snippet}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Label>Actions</DropdownMenu.Label>
    <DropdownMenu.Item onclick={() => navigator.clipboard.writeText(id)}>
      Copy ID
    </DropdownMenu.Item>
    <DropdownMenu.Separator />
    <DropdownMenu.Item>View details</DropdownMenu.Item>
    <DropdownMenu.Item>Edit</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu.Root>

Styling Data Tables with Tailwind v4.1

Define CSS Variables for Table States in src/app.css:

@import "tailwindcss";

@layer theme {
  :root {
    /* Table colors */
    --color-table-bg: 0 0% 100%;
    --color-table-row-hover: 0 0% 96.1%;
    --color-table-row-selected: 210 40% 96%;
    --color-table-border: 0 0% 89.8%;
    --color-table-text: 0 0% 3.6%;
    --color-table-header-bg: 0 0% 94.1%;
  }

  .dark {
    --color-table-bg: 0 0% 14.9%;
    --color-table-row-hover: 0 0% 22%;
    --color-table-row-selected: 210 100% 35%;
    --color-table-border: 0 0% 22%;
    --color-table-text: 0 0% 98%;
    --color-table-header-bg: 0 0% 22%;
  }
}

@layer utilities {
  .table-cell {
    @apply px-4 py-3 text-sm;
  }

  .table-row-hover {
    @apply hover:bg-[hsl(var(--color-table-row-hover))] transition-colors;
  }

  .table-row-selected {
    @apply bg-[hsl(var(--color-table-row-selected))] border-l-4 border-l-primary;
  }

  .table-header {
    @apply bg-[hsl(var(--color-table-header-bg))] font-semibold text-xs uppercase tracking-wide;
  }
}

Apply Row States in your table component:

<Table.Body>
  {#each table.getRowModel().rows as row (row.id)}
    {@const rowSelected = row.getIsSelected()}
    <Table.Row
      class={cn(
        "table-row-hover",
        rowSelected && "table-row-selected"
      )}
      data-state={rowSelected && "selected"}
    >
      {#each row.getVisibleCells() as cell (cell.id)}
        <Table.Cell class="table-cell">
          <FlexRender
            content={cell.column.columnDef.cell}
            context={cell.getContext()}
          />
        </Table.Cell>
      {/each}
    </Table.Row>
  {/each}
</Table.Body>

Key Patterns for TanStack Tables

  1. Svelte 5 State Management: Always use $state and get accessors
  2. State Updater Pattern: All handlers follow (updater) => state = typeof updater === "function"? updater(state): updater
  3. Cell Rendering:

- Simple HTML: createRawSnippetrenderSnippet - Components: renderComponent for interactive UI - Plain text: Direct string or number

  1. Row Models: Add the appropriate row model for each feature (pagination, sorting, filtering)

Common Pitfalls

  • Forgetting get accessors in createSvelteTable state config
  • Not binding both oninput and onchange for filter inputs
  • Missing row models (e.g., getFilteredRowModel for filtering)
  • Using wrong import path for data-table helpers

For comprehensive DataTable reference including:

  • Advanced sorting and filtering patterns
  • Column visibility controls
  • Responsive table layouts
  • Performance optimization (virtual scrolling, debouncing)
  • Complete working examples with all features

See: shadcn-datatable.md and datatable-tanstack-svelte5.md reference documents

Modal/Dialog

pnpm dlx shadcn-svelte@latest add dialog button
<script lang="ts">
  import * as Dialog from "$lib/components/ui/dialog";
  import { Button } from "$lib/components/ui/button";

  let open = false;
</script>

<Dialog.Root bind:open>
  <Dialog.Trigger asChild let:builder>
    <Button builders={[builder]}>Open Dialog</Button>
  </Dialog.Trigger>
  <Dialog.Content>
    <Dialog.Header>
      <Dialog.Title>Dialog Title</Dialog.Title>
      <Dialog.Description>This is a dialog.</Dialog.Description>
    </Dialog.Header>
    <p>Your content here</p>
    <Dialog.Footer>
      <Button on:click={() => (open = false)}>Close</Button>
    </Dialog.Footer>
  </Dialog.Content>
</Dialog.Root>

Drawer (Mobile-Friendly Sidebar)

pnpm dlx shadcn-svelte@latest add drawer button
<script lang="ts">
  import * as Drawer from "$lib/components/ui/drawer";
  import { Button } from "$lib/components/ui/button";

  let open = false;
</script>

<Drawer.Root bind:open>
  <Drawer.Trigger asChild let:builder>
    <Button builders={[builder]} variant="outline">Open Drawer</Button>
  </Drawer.Trigger>
  <Drawer.Content>
    <Drawer.Header>
      <Drawer.Title>Navigation</Drawer.Title>
    </Drawer.Header>
    <nav class="flex flex-col gap-2 p-4">
      <a href="/">Home</a>
      <a href="/about">About</a>
    </nav>
    <Drawer.Footer>
      <Drawer.Close asChild let:builder>
        <Button builders={[builder]} variant="outline">Close</Button>
      </Drawer.Close>
    </Drawer.Footer>
  </Drawer.Content>
</Drawer.Root>

Component Organization

Project Structure

src/
├── lib/
│   ├── components/
│   │   ├── ui/              (shadcn-svelte components)
│   │   │   ├── button/
│   │   │   ├── card/
│   │   │   ├── dialog/
│   │   │   └── [...]
│   │   └── custom/          (your custom components)
│   │       └── header.svelte
│   └── utils/
│       └── cn.ts            (class utility from init)
└── routes/

Import Patterns

// Named imports (preferred for tree-shaking)
import { Button } from "$lib/components/ui/button";
import { Dialog, DialogTrigger, DialogContent } from "$lib/components/ui/dialog";

// Namespace imports
import * as Button from "$lib/components/ui/button";
import * as Dialog from "$lib/components/ui/dialog";

Customization

Theme via CSS Variables (Tailwind v4.1)

Edit src/app.css to define theme colors as CSS variables. Tailwind v4.1 auto-scans these:

@import "tailwindcss";

@layer theme {
  :root {
    --color-background: 0 0% 100%;
    --color-foreground: 0 0% 3.6%;
    --color-primary: 0 0% 9%;
    --color-primary-foreground: 0 0% 100%;
    --color-secondary: 0 0% 96.1%;
    --color-secondary-foreground: 0 0% 9%;
    --color-destructive: 0 84% 60%;
    --color-muted: 0 0% 96.1%;
    --color-muted-foreground: 0 0% 45.1%;
    --color-border: 0 0% 89.8%;
  }

  .dark {
    --color-background: 0 0% 3.6%;
    --color-foreground: 0 0% 98%;
    --color-primary: 0 0% 98%;
    --color-primary-foreground: 0 0% 9%;
    --color-secondary: 0 0% 14.9%;
    --color-secondary-foreground: 0 0% 98%;
    --color-destructive: 0 84% 60%;
    --color-muted: 0 0% 14.9%;
    --color-muted-foreground: 0 0% 63.9%;
    --color-border: 0 0% 14.9%;
  }
}

@layer utilities {
  .btn-custom {
    @apply px-4 py-2 rounded-lg font-semibold transition-colors;
  }
}

Reference in tailwind.config.js (if needed):

export default {
  theme: {
    colors: {
      background: 'hsl(var(--color-background))',
      foreground: 'hsl(var(--color-foreground))',
      primary: 'hsl(var(--color-primary))',
      'primary-foreground': 'hsl(var(--color-primary-foreground))',
      // ... map CSS variables to theme
    },
    extend: {
      spacing: {
        gutter: '1rem',
      },
    },
  },
}

Override Component Styles

Modify components in src/lib/components/ui/[name]/ directly. Tailwind v4.1 automatically applies classes:

<!-- src/lib/components/ui/button/button.svelte -->
<script lang="ts">
  import { cn } from "$lib/utils";

  interface Props {
    variant?: "default" | "outline" | "ghost";
    size?: "sm" | "md" | "lg";
    class?: string;
  }

  let { variant = "default", size = "md", class: className }: Props = $props();

  const baseClasses = cn(
    "inline-flex items-center justify-center font-semibold transition-colors",
    {
      "bg-primary text-primary-foreground hover:bg-primary/90": variant === "default",
      "border border-border bg-background hover:bg-muted": variant === "outline",
      "hover:bg-muted": variant === "ghost",
    },
    {
      "h-8 px-3 text-xs": size === "sm",
      "h-10 px-4 text-sm": size === "md",
      "h-12 px-6 text-base": size === "lg",
    },
    className
  );
</script>

<button class={baseClasses}>
  <slot />
</button>

Tailwind v4.1 Content Scanning

No manual content paths needed—Tailwind v4.1 auto-scans your SvelteKit project:

// tailwind.config.js (minimal, Vite handles scanning)
export default {
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#f9fafb',
          600: '#1f2937',
        },
      },
    },
  },
}

For custom @source directive in CSS:

@import "tailwindcss";

@source "../src/lib/components";

Key Dependencies

Automatically installed with init and Tailwind v4.1:

PackagePurpose
@tailwindcss/viteVite plugin for zero-runtime CSS with v4.1
tailwindcssTailwind CSS framework (v4.1+)
clsx / tailwind-mergeClass utility functions via cn()
@lucide/svelteIcon library (650+ icons)
bits-uiHeadless UI primitives (accessibility)
sveltekitFull-stack framework
viteBuild tool (handles CSS imports)

Not needed in v4.1:

  • PostCSS
  • Autoprefixer
  • tailwind.config.ts for basic projects

Advanced Topics

Dark Mode

Use mode-watcher for automatic dark mode switching:

pnpm i mode-watcher
<script lang="ts">
  import { modeWatcher } from "mode-watcher";
</script>

<div use:modeWatcher>
  <!-- Your app content -->
</div>

Icons with Lucide

pnpm dlx shadcn-svelte@latest add button
<script lang="ts">
  import { Button } from "$lib/components/ui/button";
  import { Heart } from "@lucide/svelte";
</script>

<Button>
  <Heart class="w-4 h-4 mr-2" />
  Save
</Button>

Creating Custom Components

Copy shadcn component structure as template:

<!-- src/lib/components/custom/my-card.svelte -->
<script lang="ts">
  import { cn } from "$lib/utils";

  interface Props {
    title: string;
    class?: string;
  }

  let { title, class: className, children }: Props & { children?: any } = $props();
</script>

<div class={cn("rounded-lg border p-4", className)}>
  <h3>{title}</h3>
  {#if children}
    <slot />
  {/if}
</div>

Building Component Registries

To create a custom registry for sharing components:

// registry.json
{
  "$schema": "https://shadcn-svelte.com/schema/registry.json",
  "name": "my-components",
  "homepage": "https://my-components.com",
  "items": [
    {
      "name": "custom-card",
      "type": "registry:component",
      "title": "Custom Card",
      "description": "Extended card component",
      "files": [
        {
          "path": "./src/lib/custom-card.svelte",
          "type": "registry:component"
        }
      ]
    }
  ]
}

Build registry: pnpm run registry:build

Troubleshooting

Component Not Found

Verify install location: src/lib/components/ui/[component]/

pnpm dlx shadcn-svelte@latest list    # Check installed components
pnpm dlx shadcn-svelte@latest add button --overwrite  # Reinstall

Styling Issues

  1. Ensure Tailwind CSS is configured in tailwind.config.ts
  2. Check that CSS variables are defined in src/app.css
  3. Verify component imports use correct path aliases

TypeScript Errors

Update TypeScript settings in svelte.config.js:

const config: Config = {
  kit: {
    alias: {
      "$lib": "./src/lib",
      "$components": "./src/lib/components",
    },
  },
};

Command and Hook

/shadcn Command

Interactive assistant for shadcn-svelte component development:

/shadcn              # Show help and available topics
/shadcn add          # Component installation guidance
/shadcn form         # Form patterns with superforms
/shadcn table        # DataTable with TanStack Table v8
/shadcn dialog       # Modal/drawer/sheet patterns
/shadcn theme        # CSS variables and customization
/shadcn debug        # Troubleshooting common issues
/shadcn button       # Specific component guidance

Development Hook

A hook is available that triggers when editing files in $lib/components/ui/:

Install hook script:

# Script location: ~/.claude/hooks/shadcn-component-reminder.sh
chmod +x ~/.claude/hooks/shadcn-component-reminder.sh

Add to ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/shadcn-component-reminder.sh",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

The hook provides contextual reminders about shadcn patterns when editing component files.

Resources

Summary

shadcn-svelte provides production-grade UI components that you control. Start with init, add components via CLI, customize in-place, and build accessible applications with TypeScript and Tailwind. The copy-paste model means you own your UI layer—no library lock-in.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

28.8%
按下载量换算21

OpenCode

27.1%
按下载量换算20

Antigravity

17.57%
按下载量换算13

windsurf

11.82%
按下载量换算9

Gemini CLI

8.35%
按下载量换算6

Codex

3.44%
按下载量换算3

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills