Validate WCAG 2.1 Level AA compliance and accessibility best practices. Use when performing accessibility audits and WCAG certification.
日本語の概要は準備中です。原文の説明を表示しています。
Create distinctive, production-grade Svelte/TypeScript frontends with exceptional design quality
インストールする前に、エージェントに与えられる指示の中身を確認できます。
This skill guides the creation of distinctive, production-grade Svelte frontends that combine Svelte's reactive elegance with exceptional design quality. It integrates all design frameworks: intentional thinking, typography, color, motion, spatial composition, and anti-pattern awareness.
Before writing any code, establish intentional design direction:
The Four Critical Questions:
Deliberately reject these patterns:
Typography:
Color & Theme:
Layout & Space:
Motion:
Always use TypeScript in Svelte components:
<script lang="ts">
import type { ComponentProps } from 'svelte'
interface Props {
title: string
count: number
onAction?: () => void
}
let { title, count, onAction }: Props = $props()
</script>
$:Leverage Svelte's reactive declarations for dynamic styling and state:
<script lang="ts">
let theme: 'light' | 'dark' = $state('light')
let isHovered = $state(false)
// Reactive computed values
let backgroundColor = $derived(
theme === 'light' ? 'var(--color-bg-light)' : 'var(--color-bg-dark)'
)
let shadowIntensity = $derived(isHovered ? '0.2' : '0.1')
</script>
Svelte's scoped styles are default. Use CSS custom properties for theming:
<style>
:global(:root) {
--color-primary: #8b4513;
--color-accent: #d4a574;
--color-bg: #faf8f3;
--font-display: 'Playfair Display', serif;
--font-body: 'IBM Plex Sans', sans-serif;
--spacing-unit: 8px;
}
.card {
background: var(--color-bg);
padding: calc(var(--spacing-unit) * 3);
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, var(--shadow-intensity));
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.card:hover {
--shadow-intensity: 0.15;
transform: translateY(-4px);
}
</style>
Use Svelte's built-in transitions for elegant animations:
<script lang="ts">
import { fade, fly, scale, slide } from 'svelte/transition'
import { cubicOut, elasticOut } from 'svelte/easing'
let isVisible = $state(true)
let showDetails = $state(false)
</script>
<!-- Fade in on mount -->
<div in:fade={{ duration: 300 }} out:fade={{ duration: 200 }}>
Content
</div>
<!-- Orchestrated entrance with stagger -->
<div
in:fly={{ y: 50, duration: 600, delay: 100, easing: cubicOut }}
out:fly={{ y: 20, duration: 300 }}
>
Hero section
</div>
<!-- Elastic expand on interaction -->
{#if showDetails}
<div
in:scale={{ start: 0.95, duration: 400, easing: elasticOut }}
out:scale={{ duration: 200 }}
>
Detailed content
</div>
{/if}
<!-- Slide for list items (staggered) -->
<ul>
{#each items as item (item.id)}
<li
in:slide={{ duration: 400, delay: index * 50 }}
out:slide={{ duration: 200 }}
>
{item.name}
</li>
{/each}
</ul>
Use Svelte stores for theme, animations, and global UI state:
<!-- lib/stores/theme.ts -->
import { writable, derived } from 'svelte/store'
export const isDarkMode = writable(false)
export const themeVariables = derived(isDarkMode, ($isDarkMode) => ({
bgColor: $isDarkMode ? '#1a1a1a' : '#faf8f3',
textColor: $isDarkMode ? '#f5f5f5' : '#333333',
accentColor: '#d4a574',
shadows: $isDarkMode ? 'rgba(0,0,0,0.4)' : 'rgba(0,0,0,0.1)',
}))
<!-- Usage in component -->
<script lang="ts">
import { isDarkMode, themeVariables } from '$lib/stores/theme'
</script>
<div style:background-color={$themeVariables.bgColor}>
Content
</div>
Svelte's approach to accessibility:
<script lang="ts">
let isMenuOpen = $state(false)
let focusedIndex = $state(-1)
</script>
<!-- Semantic structure -->
<nav aria-label="Main navigation">
<button
aria-expanded={isMenuOpen}
aria-controls="main-menu"
aria-label="Toggle navigation menu"
>
Menu
</button>
<ul id="main-menu" role="menubar" hidden={!isMenuOpen}>
{#each menuItems as item (item.id)}
<li role="none">
<a href={item.href} role="menuitem">
{item.label}
</a>
</li>
{/each}
</ul>
</nav>
<!-- Form accessibility -->
<form>
<label for="email">Email address</label>
<input
id="email"
type="email"
required
aria-required="true"
aria-describedby="email-hint"
/>
<small id="email-hint">We'll never share your email.</small>
</form>
Use Svelte's class directives and media queries:
<script lang="ts">
let viewport: 'mobile' | 'tablet' | 'desktop' = $state('mobile')
let windowWidth = $state(0)
$effect(() => {
if (windowWidth < 640) viewport = 'mobile'
else if (windowWidth < 1024) viewport = 'tablet'
else viewport = 'desktop'
})
</script>
<svelte:window bind:innerWidth={windowWidth} />
<div class="container" class:is-mobile={viewport === 'mobile'}>
<header class:is-compact={viewport === 'mobile'}>
<!-- Mobile-optimized header -->
</header>
</div>
<style>
.container {
padding: calc(var(--spacing-unit) * 4);
}
.container.is-mobile {
padding: calc(var(--spacing-unit) * 2);
}
header.is-compact {
font-size: 18px;
}
@media (min-width: 640px) {
header {
font-size: 24px;
}
}
</style>
Input: Feature requirements, target users, problem statement
Actions:
Deliverable: Design brief with clear direction
Input: Design brief and tone direction
Actions:
Deliverable: Design tokens in CSS variables and Svelte stores
<!-- $lib/styles/tokens.css -->
:root {
/* Typography */
--font-display: 'Playfair Display', serif;
--font-body: 'IBM Plex Sans', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--size-display: 88px;
--size-h1: 48px;
--size-h2: 28px;
--size-body: 16px;
--size-small: 12px;
/* Colors */
--color-bg: #faf8f3;
--color-text: #2a2a2a;
--color-accent: #d4a574;
--color-accent-dark: #8b4513;
/* Motion */
--easing-out: cubic-bezier(0.16, 0.04, 0.04, 1);
--easing-elastic: cubic-bezier(0.34, 1.56, 0.64, 1);
--duration-quick: 200ms;
--duration-standard: 400ms;
--duration-slow: 600ms;
}
Input: Design tokens and feature requirements
Actions:
Deliverable: Typed component structure
<!-- lib/components/Button.svelte -->
<script lang="ts">
import { cubicOut } from 'svelte/easing'
interface Props {
variant?: 'primary' | 'secondary' | 'outline'
size?: 'small' | 'medium' | 'large'
disabled?: boolean
ariaLabel?: string
onclick?: () => void
}
let {
variant = 'primary',
size = 'medium',
disabled = false,
ariaLabel,
onclick,
}: Props = $props()
</script>
<button
class="button {variant} {size}"
{disabled}
aria-label={ariaLabel}
on:click={onclick}
in:scale={{ start: 0.95, duration: 200, easing: cubicOut }}
>
<slot />
</button>
Input: Component structure and design tokens
Actions:
Deliverable: Transition patterns and animation sequences
Input: Component library and motion patterns
Actions:
Deliverable: Responsive component library
Input: Design tokens and component library
Actions:
Deliverable: Fully themed component system
Input: All components and interactions
Actions:
Deliverable: Fully accessible component library
Input: Complete feature implementation
Actions:
will-change, GPU acceleration)Deliverable: Production-ready application
Use these checks before finalizing any design or component:
Typography:
Color & Theme:
Layout & Space:
Motion & Animation:
Svelte-Specific:
<script lang="ts">$:<script lang="ts">
import { fly, scale } from 'svelte/transition'
import { cubicOut, elasticOut } from 'svelte/easing'
let isHovered = $state(false)
interface Props {
title: string
description: string
image?: string
}
let { title, description, image }: Props = $props()
</script>
<article
in:fly={{ y: 40, duration: 500, easing: cubicOut }}
class="card"
on:mouseenter={() => (isHovered = true)}
on:mouseleave={() => (isHovered = false)}
>
{#if image}
<img src={image} alt="" class="card-image" />
{/if}
<div class="card-content">
<h3>{title}</h3>
<p>{description}</p>
{#if isHovered}
<button
in:scale={{ start: 0.8, duration: 300, easing: elasticOut }}
class="card-action"
>
Learn More
</button>
{/if}
</div>
</article>
<style>
.card {
background: var(--color-bg);
border-radius: 12px;
overflow: hidden;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
cursor: pointer;
}
.card:hover {
transform: translateY(-12px);
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.15);
}
.card-image {
width: 100%;
height: 240px;
object-fit: cover;
}
.card-content {
padding: calc(var(--spacing-unit) * 3);
}
h3 {
font-family: var(--font-display);
font-size: var(--size-h2);
font-weight: 700;
margin: 0 0 calc(var(--spacing-unit) * 2) 0;
color: var(--color-text);
}
p {
font-family: var(--font-body);
font-size: var(--size-body);
line-height: 1.6;
color: rgba(0, 0, 0, 0.7);
margin: 0;
}
.card-action {
margin-top: calc(var(--spacing-unit) * 2);
padding: calc(var(--spacing-unit) * 1.5) calc(var(--spacing-unit) * 3);
background: var(--color-accent);
color: white;
border: none;
border-radius: 6px;
font-family: var(--font-body);
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease-out;
}
.card-action:hover {
background: var(--color-accent-dark);
transform: scale(1.05);
}
</style>
<script lang="ts">
import { slide } from 'svelte/transition'
import { cubicOut } from 'svelte/easing'
interface ListItem {
id: string
label: string
}
interface Props {
items: ListItem[]
}
let { items }: Props = $props()
</script>
<ul class="list">
{#each items as item, index (item.id)}
<li
in:slide={{
duration: 400,
delay: index * 50,
easing: cubicOut,
}}
out:slide={{ duration: 200 }}
>
<span class="list-number">{index + 1}</span>
<span class="list-label">{item.label}</span>
</li>
{/each}
</ul>
<style>
.list {
list-style: none;
padding: 0;
margin: 0;
}
li {
display: flex;
align-items: center;
padding: calc(var(--spacing-unit) * 2) calc(var(--spacing-unit) * 3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease-out;
}
li:hover {
background-color: rgba(0, 0, 0, 0.02);
}
.list-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
margin-right: calc(var(--spacing-unit) * 2);
background: var(--color-accent);
color: white;
border-radius: 50%;
font-weight: 600;
font-size: 13px;
}
.list-label {
font-family: var(--font-body);
font-size: var(--size-body);
color: var(--color-text);
}
</style>
$derived for computed values and $effect for side effectssvelte/transition for all animations:global() sparinglywritable for theme, animation state, and global UI statebind: carefully, memoize expensive computations with $derivedReady to build distinctive, intentional Svelte frontends? Start with Phase 1: Design Thinking & Intent Definition. Never skip the pre-coding work.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Validate WCAG 2.1 Level AA compliance and accessibility best practices. Use when performing accessibility audits and WCAG certification.
日本語の概要は準備中です。原文の説明を表示しています。
Analyze feature requirements, dependencies, and security considerations. Use when starting feature implementation from GitHub issues to understand scope, technical feasibility, and risks.
日本語の概要は準備中です。原文の説明を表示しています。
Run SQL queries against psql, BigQuery, or MySQL from the terminal, including natural-language-to-SQL and schema exploration. Use when analyzing data, inspecting DB state, or debugging tables. Trigger on "query the database", "SQL", "show me data from", "explore table".
日本語の概要は準備中です。原文の説明を表示しています。
Design REST APIs or function contracts with clear request/response specifications, error handling patterns, authentication strategies, and comprehensive documentation.
日本語の概要は準備中です。原文の説明を表示しています。
Generate comprehensive API endpoint tests for REST and GraphQL APIs. Creates tests for all HTTP methods, status codes, authentication, and validation.
日本語の概要は準備中です。原文の説明を表示しています。
Design component architecture and module structure using established architectural patterns for clean, maintainable, and scalable systems.
日本語の概要は準備中です。原文の説明を表示しています。