Create new Svelte 5 components with best practices, runes, snippets, and Tailwind CSS styling. Use when creating new .svelte files or refactoring components.
This skill helps you create well-structured Svelte 5 components following project conventions.
All components must follow the coding standards defined in ../../instructions/svelte-coding-standards.instructions.md.
Key principles:
$state() for reactive state$derived() for computed values (never $effect)$effect() only for DOM manipulation, browser APIs, or external subscriptionslet { prop } = $props()onclick instead of on:click{#snippet} and {@render} instead of slots<script lang="ts">
// Props (if needed)
// let { propName } = $props<{ propName: Type }>()
// Local state
// let value = $state('')
// Derived state
// const computed = $derived(someCalculation)
// Event handlers
// function handleClick() { }
</script>
<!-- Markup with Tailwind classes -->
<div>
<!-- Content -->
</div>
See templates/input-component.svelte for a complete example.
See templates/list-component.svelte for a complete example.
See templates/snippet-component.svelte for a complete example.
Components use Tailwind CSS with support for dark mode:
<div class="bg-white dark:bg-neutral-800
text-stone-700 dark:text-neutral-200
border border-stone-200 dark:border-neutral-700
rounded-xl px-4 py-2">
</div>
Common patterns:
bg-white / bg-stone-50dark:bg-neutral-800 / dark:bg-neutral-700text-stone-700 dark:text-neutral-200border-stone-200 dark:border-neutral-700hover:bg-stone-100 dark:hover:bg-neutral-700focus-visible:ring-2 focus-visible:ring-blue-500src/lib/ComponentName.sveltesvelte/transition and svelte/easing$effect for state synchronizationfunction handleKeydown(e: KeyboardEvent) {
if (e.key === 'Enter') {
e.preventDefault()
// Handle enter
} else if (e.key === 'Escape') {
e.preventDefault()
// Handle escape
}
}
let processingIds = $state(new Set<string>())
function handleToggle(id: string) {
if (processingIds.has(id)) return
processingIds = new Set([...processingIds, id])
setTimeout(() => {
// Perform action
processingIds = new Set([...processingIds].filter(i => i !== id))
}, 300)
}
<script>
import { fade, fly } from 'svelte/transition'
import { cubicOut } from 'svelte/easing'
</script>
<div in:fly={{ y: -20, duration: 300, easing: cubicOut }}
out:fly={{ y: 20, duration: 300, easing: cubicOut }}>
</div>
When creating a component:
.svelte file in the appropriate location