# Sveltier > A Svelte 5 UI framework with five built-in design languages, a zero-dependency theme engine and flash-free server-side theming. ## Setup ```sh pnpm add sveltier ``` ```svelte {@render children()} ``` ## Conventions Install `sveltier`, wrap the app in `UIProvider` with at least one theme pack (for example `monolith` from `sveltier/themes/monolith`), and import components from `sveltier`. - Svelte 5 only: runes (`$state`, `$derived`, `$effect`, `$props`, `$bindable`), snippets and callback props. Never write Svelte 4 syntax: no `export let`, no `on:click` (use `onclick`), no `` (use snippets and `{@render}`), no `createEventDispatcher`, no `$:`. Svelte's own tools for agents, including an MCP server and an autofixer, are listed at https://svelte.dev/docs/ai. - Every component takes the same names for the same things: `variant` (elevated, flat, tonal, outlined, text, plain), `size` (xs to xl), `density` (compact, default, comfortable), `color` (an intent such as primary or error, neutral, or a custom colour), `rounded`, `disabled`, `loading`. - Content goes in snippets (`children`, `prepend`, `append`, `actions`), events are callback props (`onclick`), and two-way values use `bind:` (`bind:value`, `bind:selected`, `bind:open`). - Every component passes other attributes to its root element, merges `class`, and exposes the element as a bindable `ref`. Form fields are the exception: their attributes and `ref` go to the native control (`name`, `placeholder`, `autocomplete` reach the ``), while `class` and `style` stay on the field. - Form fields validate with the HTML constraints first (`required`, `minlength`, `maxlength`, `pattern`, `type="email"`), then `rules` (functions returning `true` or a message), and show `error` from outside (a server's answer) as given. Messages appear when the user leaves a field they changed, then follow every change. - Defaults for a whole app or section go in the `defaults` of `UIProvider` or a `DefaultsProvider`, by component name; a prop on the component still wins. - Style your own elements with the theme's CSS variables, never fixed values: `--sv-color-*` for colour, `--sv-space-*` for spacing, `--sv-radius-md` for one-line controls. A theme may make `--sv-radius-md` a pill, so a box that grows with its content takes `min(var(--sv-radius-md), var(--sv-radius-lg))`. ## Components ### Alert Docs: ./components/alert A message about something that happened or needs attention. ```svelte The card ending 4471 was declined by the issuer. {#snippet actions()} {/snippet} Transfer sent. ``` `AlertProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'tonal'` | Visual weight. | | `color` | `Color` | `'info'` | The colour, when there is no `type` to take it from. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the padding. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | Corner rounding. `true` keeps the theme's radius. | | `type` | `'info' \| 'success' \| 'warning' \| 'error'` | | What kind of message: sets the colour and the icon. Warnings and errors are announced at once (`role="alert"`), the others politely (`role="status"`). | | `title` | `string` | | A short summary, above the text. | | `icon` | `boolean` | `true` | Shows the icon of the `type`. | | `open` | `boolean` | `true` | Shown while true; a closable alert sets it to false. Bindable. | | `closable` | `boolean` | `false` | Adds a button that closes the alert and calls `onclose`. | | `closeLabel` | `string` | | The name of the close button. Defaults to the locale's `close`. | | `onclose` | `() => void` | | Called when the close button closes the alert. | | `prepend` | `Snippet` | | Content in place of the type's icon. | | `actions` | `Snippet` | | Buttons or links after the text, such as `Retry`. | | `children` | `Snippet` | | The message. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ### Avatar Docs: ./components/avatar A picture of a person or an account: an image, or initials or an icon when there is none or it fails to load. ```svelte AM Alex Morgan AM ``` `AvatarProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Width and height: the control height of the size. | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'tonal'` | How the fallback is painted. | | `color` | `Color` | `'neutral'` | The colour of the fallback. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'full'` | Corner rounding. | | `src` | `string` | | The image. | | `alt` | `string` | | Who or what the avatar shows, for screen readers. Leave it out when a name is shown next to the avatar: it is then decorative and hidden from them. | | `children` | `Snippet` | | Initials or an icon, shown while there is no image or it failed to load. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLSpanElement \| null` | | The root element, bindable with `bind:ref`. | ### Badge Docs: ./components/badge A count or a dot pinned to the top end corner of its content, or standing alone in a line when it has none. A count of 0 hides it. ```svelte Savings ``` `BadgeProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `color` | `Color` | `'primary'` | The badge's fill. | | `max` | `number` | `99` | Counts above it show as `max+`. | | `content` | `number \| string` | | What the badge says: usually a count. | | `dot` | `boolean` | `false` | A dot instead of the content. | | `label` | `string` | | What the content counts, read after it by screen readers: `unread messages` reads "3 unread messages". With `dot`, the whole announcement. With an `id`, this text has the id `{id}-label`, for the `aria-describedby` of a button the badge is pinned to. | | `children` | `Snippet` | | The content the badge is pinned to. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLSpanElement \| null` | | The root element, bindable with `bind:ref`. | ### Button Docs: ./components/button A button, or a link that looks like one (`href`). Every other attribute of ` ``` `ButtonProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'flat'` | Visual weight. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Height and text size. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the height and padding, never the text. | | `color` | `Color` | `'primary'` | The colour the variant is painted with. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | Corner rounding. `true` keeps the theme's radius. | | `block` | `boolean` | `false` | Takes the full width of its container. | | `disabled` | `boolean` | `false` | A disabled button cannot be focused or pressed; a disabled link loses its `href`. | | `as` | `'button' \| 'a'` | | The element to render. Defaults to `'a'` when `href` is given, otherwise `'button'`. | | `icon` | `boolean` | `false` | Square, for a single icon as the content. Give it an `aria-label`. | | `loading` | `boolean` | `false` | Shows a spinner and ignores presses, while the button keeps focus and its label for screen readers, which also hear that it is loading. | | `prepend` | `Snippet` | | Content before the label, usually an icon. | | `append` | `Snippet` | | Content after the label, usually an icon. | | `children` | `Snippet` | | The label. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLButtonElement \| HTMLAnchorElement \| null` | | The root element, bindable with `bind:ref`. | ### ButtonGroup Docs: ./components/button-group Buttons joined into one control: shared borders, square inner corners, and the same variant, size, density and colour unless a Button says otherwise. Give it an `aria-label`. ```svelte ``` `ButtonGroupProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'outlined'` | The variant of the Buttons. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | The size of the Buttons. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | The density of the Buttons. | | `color` | `Color` | `'primary'` | The colour of the Buttons. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | The rounding of the group's outer corners; inner corners are square. | | `children` | `Snippet` | | The Buttons. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ### Card Docs: ./components/card A surface that groups content about one thing: a header, the content and actions. Links and buttons inside it are what is clickable, not the card. ```svelte {#snippet prepend()}SV{/snippet}

$12,480.00

{#snippet actions()} {/snippet}
``` `CardProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'elevated'` | Visual weight: a raised surface by default. | | `color` | `Color` | `'neutral'` | The colour the variant is painted with. Neutral cards use the theme's surface, text and border colours. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the padding and the space between sections. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | Corner rounding. `true` keeps the theme's radius. | | `title` | `string` | | The title, in the header. | | `subtitle` | `string` | | A line under the title. | | `level` | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | | Makes the title a heading of this level (`

`, `

`…), so it is in the page's outline. Without it the title is styled text. | | `prepend` | `Snippet` | | Content before the title, such as an avatar or an icon. | | `append` | `Snippet` | | Content after the title, such as a menu button. | | `actions` | `Snippet` | | Buttons or links at the bottom. | | `children` | `Snippet` | | The content. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ### Chip Docs: ./components/chip A compact label: a tag (optionally `closable`), a filter that toggles (`selected`), an action (`onclick`) or a link (`href`). ```svelte Card Transfer ``` `ChipProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'tonal'` | Visual weight. A selected chip is `flat`. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'sm'` | Height and text size. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the height and padding, never the text. | | `color` | `Color` | `'neutral'` | The colour the variant is painted with. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | Corner rounding. `true` keeps the pill. | | `disabled` | `boolean` | `false` | A disabled chip cannot be pressed; a disabled link loses its `href`. | | `selected` | `boolean` | | Makes the chip a toggle button (`aria-pressed`) that flips it when pressed: a filter. Bindable. Shows a check while selected. | | `closable` | `boolean` | `false` | Adds a button that removes the chip by calling `onclose`. Only for chips that are not themselves buttons or links. | | `closeLabel` | `string` | | The name of the close button, such as `Remove Euro`. Defaults to the locale's `close`. | | `onclose` | `() => void` | | Called by the close button. | | `prepend` | `Snippet` | | Content before the label, usually an icon or an avatar. | | `append` | `Snippet` | | Content after the label. | | `children` | `Snippet` | | The label. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLSpanElement \| HTMLButtonElement \| HTMLAnchorElement \| null` | | The root element, bindable with `bind:ref`. | ### Divider Docs: ./components/divider A hairline between groups of content: an `
`, which assistive technology reads as a separator. ```svelte

Available

Pending

``` `DividerProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `vertical` | `boolean` | `false` | Runs top to bottom, between items in a row, and stretches to the row's height. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLHRElement \| null` | | The root element, bindable with `bind:ref`. | ### Icon Docs: ./components/icon An icon: SVG path data, or any icon of your own as `children`. Decorative unless it has a `label`. ```svelte ``` `IconProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `path` | `string` | | SVG path data, filled with the current colour: the format of path-based icon sets such as Material Design Icons. Several shapes go in one string (`M… Z M… Z`). | | `viewBox` | `string` | `'0 0 24 24'` | The coordinate box of `path`. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | | The text size the icon is drawn at, φ^½ larger. Without it, the icon follows the text around it. | | `color` | `Color` | | The icon's colour. Without it, the icon takes the colour of the text around it. | | `label` | `string` | | A name for an icon that means something on its own, for assistive technology. Without it, the icon is decorative and hidden from it. | | `children` | `Snippet` | | Any other icon (an ``, an icon component), sized and coloured like a path. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLSpanElement \| null` | | The root element, bindable with `bind:ref`. | ### List and ListItem Docs: ./components/list A list of rows: `ListItem`s. Density and colour are set here, for every item. ```svelte {#snippet append()}$12,480.00{/snippet} ``` `ListProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the height and padding of its items. | | `color` | `Color` | `'primary'` | The colour of the active item. | | `nav` | `boolean` | `false` | Rounded rows set in from the edges, for navigation. | | `children` | `Snippet` | | The `ListItem`s. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLUListElement \| null` | | The root element, bindable with `bind:ref`. | `ListItemProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `title` | `string` | | The main line. | | `subtitle` | `string` | | A second line, under the title. | | `href` | `string` | | Makes the row a link. | | `target` | `HTMLAnchorAttributes['target']` | | Where a link opens, as on ``. | | `rel` | `string` | | The relationship of a link, as on ``. | | `onclick` | `(event: MouseEvent) => void` | | Makes the row a button that calls this. | | `active` | `boolean` | `false` | The current page or the selected row: tinted in the list's colour, and `aria-current="page"` on a link. | | `disabled` | `boolean` | `false` | A disabled row cannot be pressed; a disabled link loses its `href`. | | `prepend` | `Snippet` | | Content before the text, such as an avatar or an icon. | | `append` | `Snippet` | | Content after the row's link or button, such as a value or a menu button. | | `children` | `Snippet` | | More content under the title and subtitle. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLLIElement \| null` | | The root element, bindable with `bind:ref`. | ### ProgressLinear and ProgressCircular Docs: ./components/progress A horizontal progress bar. ```svelte 62% ``` `ProgressLinearProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `color` | `Color` | `'primary'` | The colour of the bar; its track is a tint of it. | | `value` | `number` | | How far along, from 0 to 100. Values outside are clamped. | | `indeterminate` | `boolean` | `false` | Busy for an unknown time: no value, and moving. | | `label` | `string` | | The name screen readers give the bar, such as `Uploading statement`. Defaults to the locale's `loading` when indeterminate and `progress` otherwise. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | `ProgressCircularProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `color` | `Color` | `'primary'` | The colour of the arc; its track is a tint of it. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | The diameter: the control height of the size. | | `value` | `number` | | How far along, from 0 to 100. Values outside are clamped. | | `indeterminate` | `boolean` | `false` | Busy for an unknown time: no value, and moving. | | `label` | `string` | | The name screen readers give the bar, such as `Uploading statement`. Defaults to the locale's `loading` when indeterminate and `progress` otherwise. | | `children` | `Snippet` | | Content in the centre, such as the percentage. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ### SegmentedControl Docs: ./components/segmented-control One choice among a few options, side by side, as a radio group with one tab stop. Name it with `aria-label`. ```svelte ``` `SegmentedControlProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `variant` | `'elevated' \| 'flat' \| 'tonal' \| 'outlined' \| 'text' \| 'plain'` | `'elevated'` | How the selected segment is painted: a raised surface by default. | | `color` | `Color` | `'neutral'` | The colour of the selected segment. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Height and text size. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the height and padding, never the text. | | `rounded` | `boolean \| 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `true` | Corner rounding. `true` keeps the theme's radius. | | `options` | `readonly SegmentedControlOption[]` | | The choices, in order. | | `value` | `T` | | The chosen value. Bindable. | | `onchange` | `(value: T) => void` | | Called with the value the user picks. | | `disabled` | `boolean` | `false` | Disables every option. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ### Skeleton Docs: ./components/skeleton A placeholder in the shape of content that is still loading. Hidden from assistive technology: mark the region that is loading with `aria-busy="true"` instead. ```svelte
{#if loading} {:else} … {/if}
``` `SkeletonProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `type` | `'text' \| 'rect' \| 'circle'` | `'text'` | Lines of text, a golden rectangle that fills the width (an image, a chart), or a circle (an avatar). | | `lines` | `number` | `1` | Lines of text; the last of several is φ⁻¹ as wide. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | The diameter of a circle: the control height of the size. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLSpanElement \| null` | | The root element, bindable with `bind:ref`. | ### Tabs Docs: ./components/tabs Tabs and the panel of the selected one. Name the tab list with `aria-label` or `aria-labelledby`, which go to it. ```svelte {#snippet panel(item)} {/snippet} ``` `TabsProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `color` | `Color` | `'primary'` | The colour of the selected tab and its underline. | | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Height and text size of the tabs. | | `density` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Multiplies the height and padding of the tabs, never the text. | | `grow` | `boolean` | `false` | Tabs share the full width equally. | | `items` | `readonly TabsItem[]` | | The tabs, in order. | | `value` | `T` | | The selected tab. Bindable; the first enabled tab when not set. | | `onchange` | `(value: T) => void` | | Called with the value of the tab the user selects. | | `activation` | `'automatic' \| 'manual'` | `'automatic'` | `automatic` selects a tab as soon as the arrow keys reach it; `manual` waits for Enter or Space, for panels that are slow to show. | | `panel` | `Snippet<[TabsItem]>` | | The content of the selected tab's panel. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLDivElement \| null` | | The root element, bindable with `bind:ref`. | ## Forms ### Form Docs: ./forms/form A `
` that checks its fields when it is submitted. An invalid form does not submit: every field shows its message and the first invalid one takes focus. A valid form calls `onsubmit`, or submits as HTML does when there is no `onsubmit`, so SvelteKit form actions work as they are. Other attributes go to the `
`. Through `bind:this` it offers `validate()`, `reset()` and `resetValidation()`. ```svelte
``` `FormProps`: | Prop | Type | Default | Description | | --- | --- | --- | --- | | `validateOn` | `'blur' \| 'input' \| 'submit'` | `'blur'` | When the fields show their messages, unless a field sets its own. | | `disabled` | `boolean` | `false` | Disables every control inside, Buttons included, for example while a submission runs. | | `onsubmit` | `(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement; }) => void` | | Called when the form is submitted and every field is valid. Without it, the form submits as HTML does; call `event.preventDefault()` to handle the submission yourself. | | `children` | `Snippet` | | The fields and buttons. | | `class` | `ClassValue \| null` | | Classes added after the component's own: a string, an array or an object. | | `ref` | `HTMLFormElement \| null` | | The root element, bindable with `bind:ref`. | ### TextField Docs: ./forms/text-field A single line of text with a label, a hint and validation. `class` and `style` apply to the field; `id`, `ref` and every other attribute (`name`, `placeholder`, `autocomplete`, `minlength`, `pattern`, events) go to the `