Preset System

Style once. Apply everywhere.

Powerful preset system for global component styling and theming in Svelte Atoms.

What is the Preset System?

Define component styling globally and override it at any level of your application hierarchy.

The Preset System is a theming mechanism built on Svelte's context API. Set base styles at the app root, override them per route, or narrow them further per component subtree — all without changing the components themselves.

Presets deep-merge across context layers, so a route-level override only needs to specify what changes. The rest is inherited automatically.

Hierarchical preset system (global → route → component)

Dynamic presets with reactive bond state

Compound component support with dot notation

$preset placeholder for controlled insertion

Automatic class merging and conflict resolution

Type-safe preset definitions

Zero runtime overhead

Works with any styling approach

Preset Levels

Three scopes — global, route, component — each narrower than the last.

Global Preset

App root (+layout.svelte)

01

Scope

Entire application

Use case

Define base theme and default component styles

Priority

Lowest (overridden by route and component presets)

Route Preset

Route layout files

02

Scope

Specific route and its children

Use case

Section-specific theming (admin panel, dashboard, etc.)

Priority

Medium (overrides global, overridden by component)

Component Preset

Individual components

03

Scope

Component subtree only

Use case

Component-specific overrides for unique instances

Priority

Highest (overrides both global and route presets)

Global preset configuration

Define your base theme at the application root for consistent styling across every page.

Route-level overrides

Extend or override presets for specific routes — only specify what changes.

Component-level customization

Scope presets to a specific subtree without affecting the global theme.

Compound component presets

Configure nested components with dot notation for precise sub-component control.

Use 'parent.child' notation to style sub-components independently. This is especially useful for compound components like Alert, Card, Dialog, and Accordion, where each part needs its own styling.

Reactive state-based styling

Access component bond state for dynamic presets that update automatically.

Preset functions receive the component's bond as a parameter. To make styles reactive, return a factory function instead of a plain object — the factory is re-evaluated whenever bond state changes.

Static vs reactive

Static preset

Return a record directly: () => ({class: '...'}). Evaluated once at context setup.

Reactive preset

Return a factory: (bond) => () => ({class: '...'}). Re-evaluated on every render when bond state changes.

The $preset placeholder

Control exactly where preset classes are inserted in your class list.

Place the string '$preset' anywhere in a class array and it will be replaced by the resolved preset classes at that position. This gives you full control over specificity ordering.

Extending and composing presets

Build upon existing preset definitions with automatic deep merging.

setPreset() always merges into the existing context. Variants, sizes, and other nested records are combined — you never lose what was already defined at a higher level.

Best practices

Guidelines for effective preset architecture.

01

Set global presets at app root

Define your base theme in +layout.svelte. Everything else inherits from this baseline.

02

Override at route level for sections

Use route layout files to customize entire sections (admin panel, dashboard, marketing) without touching the global theme.

03

Use component-level presets sparingly

Only when a specific subtree needs unique styling that cannot be expressed at route level.

04

Use dot notation for compound components

'card.title' targets exactly the title sub-component — more precise than overriding the whole card.

05

Return a factory for reactive styles

Returning () => ({...}) instead of a plain object makes the preset recompute when bond state changes.

06

Prefer presets for patterns, props for one-offs

If only one instance needs a style, pass it via class prop. Presets are for reusable global patterns.

07

Merge, do not replace

setPreset deep-merges into the current context — extend existing presets rather than reimplementing from scratch.

Common use cases

Real-world scenarios where the preset system shines.

Multi-Tenant Applications

Different organizations get their own branded themes. Set presets from tenant config at root without touching component code.

Dashboard vs Marketing Site

Use route-level presets for compact dashboard styles and spacious marketing layouts — same components, different feel.

Component Library Theming

Ship default presets with your library that consumers can override or extend at any level without forking components.

Accessibility Defaults

Set aria-* attributes, role, and tabindex globally so every instance of a component starts accessible without per-use boilerplate.

API reference

Core functions and types for the preset system.

setPreset(preset)

Sets or deep-merges preset configuration into the current Svelte context. Call at component init time in any +layout.svelte or component.

setPreset(preset: Partial<Preset>): void
getPreset(key?)

Retrieves preset configuration from context. Pass a key for a specific entry; omit for the full preset map.

getPreset<K>(key?: K): PresetEntry | Partial<Preset>
mergePreset(callback)

Low-level merge function that receives the current preset and returns the merged result. Used internally by setPreset.

mergePreset(callback: (current: Partial<Preset> | undefined) => Partial<Preset>): void
PresetEntry

The type of each preset value. Receives the component bond and returns either a record (static) or a factory returning a record (reactive).

type PresetEntry = (bond: Bond | null) => PresetEntryRecord | (() => PresetEntryRecord)

© 2026 Svelte Atoms. Open source under the MIT license.

Built with Svelte 5 · Runes · TailwindCSS