Skip to main content

Starwind UI v3.0 is now available! Migration guide

Svelte Usage

Use Svelte 5.29 or newer within Svelte 5. Complete the Svelte setup for your host first. Send feedback through the Starwind UI issue tracker.

These examples use @/components/starwind. In SvelteKit use $lib/starwind; Astro islands use the configured starwind-svelte directory. Each component page links its generated API and Primitive reference. Installed Svelte prop types define which props accept bindings.

Bind Values in a Form

Use Svelte’s $state with a supported bind: prop. Input supports bind:value and a standalone Checkbox supports bind:checked. Native attributes such as name, required, and type reach the form control. Read submitted values with FormData.

<script lang="ts">
import { Button } from "@/components/starwind/button";
import { Checkbox } from "@/components/starwind/checkbox";
import { Input } from "@/components/starwind/input";
import { Label } from "@/components/starwind/label";
let email = $state("");
let subscribed = $state(false);
let status = $state("");
function submit(event: SubmitEvent & { currentTarget: HTMLFormElement }) {
event.preventDefault();
const data = new FormData(event.currentTarget);
status = `Saved ${data.get("email")}. Updates: ${data.has("updates") ? "yes" : "no"}.`;
}
</script>
<form class="grid w-full max-w-sm gap-4" onsubmit={submit}>
<div class="grid gap-2">
<Label for="svelte-profile-email">Email</Label>
<Input id="svelte-profile-email" name="email" type="email" required bind:value={email} />
</div>
<Checkbox
name="updates"
value="yes"
label="Email me product updates"
bind:checked={subscribed}
/>
<Button type="submit">Save preferences</Button>
<output aria-live="polite">{status}</output>
</form>

defaultValue, defaultChecked, and defaultOpen supply initial state. A supported bound prop receives accepted changes from the component. A later defined prop value can also set its state. Changing the parent prop does not replay the user-change callback. For Runtime-backed models, canceled proposals leave the bound value at its accepted state. Use the change detail’s cancel() method when a component documents a cancelable transition.

Callbacks and Child Snippets

Svelte 5 components use callback props. Native handlers use names such as onclick and onsubmit. Starwind callbacks keep their public names, such as onOpenChange(nextOpen, detail).

This dialog keeps open in sync through bind:open. The callback can prevent closing while the checkbox is selected. Clear it to allow the Close button, Escape key, or outside interaction to close the dialog.

<script lang="ts">
import { Button } from "@/components/starwind/button";
import { Checkbox } from "@/components/starwind/checkbox";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/starwind/dialog";
let open = $state(false);
let keepOpen = $state(false);
let status = $state("Ready");
</script>
<div class="grid gap-4">
<Dialog
bind:open
onOpenChange={(nextOpen, detail) => {
if (!nextOpen && keepOpen) {
detail.cancel();
status = "Clear Keep this dialog open to close it.";
}
}}
onCloseComplete={() => status = "Closed"}
>
<DialogTrigger>
{#snippet child({ props, children })}
<Button {...props} variant="outline">{@render children?.()}</Button>
{/snippet}
Edit preferences
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Preferences</DialogTitle>
<DialogDescription>Choose when to allow this dialog to close.</DialogDescription>
</DialogHeader>
<Checkbox label="Keep this dialog open" bind:checked={keepOpen} />
<DialogFooter>
<DialogClose>
{#snippet child({ props, children })}
<Button {...props}>{@render children?.()}</Button>
{/snippet}
Close
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
<output aria-live="polite">{open ? "Dialog open" : "Dialog closed"}. {status}</output>
</div>

The child snippet receives the part’s props and optional children. Spread the complete props object onto one compatible element or a component that forwards it. Render children to keep the trigger’s label. This preserves event handlers, ARIA attributes, and attachments on the button that owns the action.

The expected element follows the part’s type. For example, DialogTrigger uses a button, while HoverCardTrigger uses an anchor. The first examples on those pages show each composition. Keep a compound component inside one Svelte tree so its parts share context.