关于 svelte-components
面向 Svelte 开发者的组件规范指南,涵盖组件结构、Svelte runes、属性和交互约定,并要求在 UI 开发中检查视觉效果与键盘可访问性。
主要功能
- 01组件命名与目录组织
- 02Svelte runes 和属性用法
- 03shadcn-svelte 组件规范
- 04事件与 snippet 模式
- 05视觉和键盘可访问性检查
适用场景
- 01构建一致的 Svelte 组件
- 02检查组件结构与状态管理
- 03验证 UI 外观和交互
MCP 相关
该技能指导 UI 开发者使用 Chrome MCP 截取快照或屏幕截图,并检查渲染、交互状态和响应式布局。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ exceptionless/ exceptionless --skill svelte-components安装后在 Claude Code 中输入/svelte-components确认已加载。
详细介绍
Svelte 组件
文档: svelte.dev | 使用
context7查阅 API 参考
使用 Chrome MCP 进行视觉验证
务必通过 Chrome MCP 对 UI 更改进行视觉验证:
- 修改组件后,使用 Chrome MCP 获取快照或截图
- 确认组件渲染正确且符合预期设计
- 在适用时测试交互状态(悬停、聚焦、禁用)
- 检查不同视口尺寸下的响应行为
- 默认使用
/next网站路径进行验证
这一视觉验证流程可以发现自动化测试可能遗漏的样式问题、布局问题和无障碍回归问题。
文件组织
命名约定
- 所有组件文件均使用 kebab-case:
stack-status-badge.svelte、user-profile-card.svelte - 与功能切片放在一起,并与 API 控制器保持一致
目录结构
src/lib/features/
├── organizations/ # Matches OrganizationController
│ ├── components/
│ │ ├── organization-card.svelte
│ │ └── organization-switcher.svelte
│ ├── api.svelte.ts
│ ├── models.ts
│ └── schemas.ts
├── stacks/ # Matches StackController
│ └── components/
│ └── stack-status-badge.svelte
└── shared/ # Shared across features
└── components/
├── data-table/
├── navigation/
└── typography/
始终使用 shadcn-svelte 组件
按钮、输入框或表单元素不得使用原生 HTML:
<script lang="ts">
import { Button } from '$comp/ui/button';
import { Input } from '$comp/ui/input';
import * as Card from '$comp/ui/card';
</script>
<Card.Root>
<Card.Header>
<Card.Title>Settings</Card.Title>
</Card.Header>
<Card.Content>
<Input placeholder="Enter value" />
</Card.Content>
<Card.Footer>
<Button>Save</Button>
</Card.Footer>
</Card.Root>
<button class="...">Save</button>
<input type="text" />
Runes
$state - 响应式状态
<script lang="ts">
let count = $state(0);
let user = $state<User | null>(null);
let items = $state<string[]>([]);
</script>
$derived - 计算值
<script lang="ts">
let count = $state(0);
let doubled = $derived(count * 2);
let isEven = $derived(count % 2 === 0);
// Complex derived
let summary = $derived.by(() => {
return items.filter(i => i.active).map(i => i.name).join(', ');
});
</script>
$effect - 副作用
<script lang="ts">
let searchTerm = $state('');
$effect(() => {
console.log('Search term changed:', searchTerm);
return () => console.log('Cleaning up');
});
</script>
Props
<script lang="ts">
interface Props {
name: string;
count?: number;
onUpdate?: (value: number) => void;
children?: import('svelte').Snippet;
}
let { name, count = 0, onUpdate, children }: Props = $props();
</script>
事件处理
使用 onclick,而不是 on:click:
<Button onclick={() => handleClick()}>Click me</Button>
<Input oninput={(e) => (value = e.currentTarget.value)} />
Snippets(内容投影)
使用 snippets 替代 <slot>。示例来自 src/Exceptionless.Web/ClientApp/src/routes/(auth)/login/+page.svelte:
<form.Subscribe selector={(state) => state.errors}>
{#snippet children(errors)}
<ErrorMessage message={getFormErrorMessages(errors)}></ErrorMessage>
{/snippet}
</form.Subscribe>
<form.Field name="email">
{#snippet children(field)}
<Field.Field data-invalid={ariaInvalid(field)}>
<Field.Label for={field.name}>Email</Field.Label>
<Input
id={field.name}
value={field.state.value}
oninput={(e) => field.handleChange(e.currentTarget.value)}
/>
<Field.Error errors={mapFieldErrors(field.state.meta.errors)} />
</Field.Field>
{/snippet}
</form.Field>
类名合并
使用数组语法设置条件类名:
<div class={['flex items-center', expanded && 'bg-muted', className]}>
Content
</div>
<Button class={['w-full', isActive && 'bg-primary']}>Save</Button>
键盘无障碍
所有交互组件都必须支持键盘操作:
- 使用
Button组件(自动处理焦点) - 确保自定义交互包含
tabindex和键盘事件处理器 - 使用纯键盘导航进行测试
请参阅 无障碍,了解 WCAG 指南。
导入
<script lang="ts">
// Use $app/state instead of $app/stores
import { page } from '$app/state';
// Access page data
let currentPath = $derived(page.url.pathname);
</script>
参考资料
- shadcn-svelte — UI 组件模式和触发器 snippets
- 无障碍 — WCAG 指南和键盘导航
评论
支持 Markdown