Skip to main content

Overview

The context module provides utilities for managing Svelte context and the preset system. Presets allow you to customize component appearance and behavior globally across your application.

Installation

npm install @svelte-atoms/core

Import

import { getPreset, setPreset } from '@svelte-atoms/core/context';
import type { Preset, PresetEntry, PresetModuleName } from '@svelte-atoms/core/context';

API Reference

setPreset

Sets or merges preset configuration for components. Presets allow you to customize component styles, variants, and behavior globally.

Signature

function setPreset(preset: Partial<Preset>): Partial<Preset>

Parameters

preset
Partial<Preset>
Preset configuration object with component-specific customizations

Returns

The merged preset configuration

Example

<script>
  import { setPreset } from '@svelte-atoms/core/context';

  setPreset({
    button: (bond) => ({
      class: 'rounded-lg font-semibold',
      variants: {
        variant: {
          primary: 'bg-blue-500 text-white',
          secondary: 'bg-gray-200 text-gray-800'
        },
        size: {
          sm: 'px-2 py-1 text-sm',
          md: 'px-4 py-2',
          lg: 'px-6 py-3 text-lg'
        }
      },
      defaults: {
        variant: 'primary',
        size: 'md'
      }
    }),
    input: (bond) => ({
      class: 'border-2 rounded focus:ring-2'
    })
  });
</script>

getPreset

Retrieves preset configuration for a specific component or all presets.

Signatures

// Get specific preset
function getPreset<K extends PresetModuleName>(key: K): PresetEntry | undefined

// Get all presets
function getPreset(): Partial<Preset> | undefined

Parameters

key
PresetModuleName
Optional component name to retrieve specific preset

Returns

The preset entry for the specified component, or all presets if no key provided

Example

<script>
  import { getPreset } from '@svelte-atoms/core/context';

  // Get specific preset
  const buttonPreset = getPreset('button');

  // Get all presets
  const allPresets = getPreset();

  console.log(buttonPreset, allPresets);
</script>

Type Definitions

PresetModuleName

Union type of all available component preset names.
type PresetModuleName =
  | 'accordion'
  | 'alert'
  | 'badge'
  | 'button'
  | 'checkbox'
  | 'datagrid'
  | 'datagrid.header'
  | 'datagrid.th'
  | 'datagrid.td'
  | 'datagrid.tr'
  | 'dialog'
  | 'dropdown'
  | 'input'
  | 'label'
  | 'popover'
  | 'radio'
  | 'tabs'
  // ... and many more

PresetEntry

Function that returns preset configuration for a component.
type PresetEntry = (
  bond: Bond | undefined | null,
  ...args: any[]
) => PresetEntryRecord | (() => PresetEntryRecord)

PresetEntryRecord

Configuration object for a component preset.
interface PresetEntryRecord {
  class?: ClassValue;
  as?: string;
  base?: Base;
  variants?: Record<string, Record<string, any>>;
  compounds?: Array<Record<string, any>>;
  defaults?: Record<string, any>;
  attachments?: Attachment[];
  [key: string]: unknown;
}
class
ClassValue
CSS classes to apply
as
string
HTML element tag name to render as
base
Base
Base component or snippet to use
variants
Record<string, Record<string, any>>
Variant definitions for different states
compounds
Array<Record<string, any>>
Compound variant rules
defaults
Record<string, any>
Default variant values
attachments
Attachment[]
Svelte attachments to apply

Preset

Complete preset configuration mapping component names to preset entries.
type Preset = Record<PresetModuleName, PresetEntry>

Advanced Usage

Global Theme Configuration

<!-- App.svelte -->
<script>
  import { setPreset } from '@svelte-atoms/core/context';

  setPreset({
    // Button presets
    button: () => ({
      class: 'transition-colors duration-200 font-medium',
      variants: {
        variant: {
          primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
          secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
          destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
          outline: 'border border-input bg-background hover:bg-accent',
          ghost: 'hover:bg-accent hover:text-accent-foreground'
        },
        size: {
          sm: 'h-8 px-3 text-xs',
          md: 'h-10 px-4 py-2',
          lg: 'h-12 px-6 text-lg',
          icon: 'h-10 w-10'
        }
      },
      compounds: [
        {
          variant: 'outline',
          size: 'sm',
          class: 'border-2'
        }
      ],
      defaults: {
        variant: 'primary',
        size: 'md'
      }
    }),

    // Input presets
    input: () => ({
      class: 'flex w-full rounded-md border bg-background px-3 py-2',
      variants: {
        size: {
          sm: 'h-8 text-sm',
          md: 'h-10',
          lg: 'h-12 text-lg'
        },
        error: {
          true: 'border-destructive focus-visible:ring-destructive',
          false: 'border-input focus-visible:ring-ring'
        }
      },
      defaults: {
        size: 'md',
        error: false
      }
    }),

    // DataGrid presets
    datagrid: () => ({
      class: 'w-full border rounded-lg overflow-hidden'
    }),
    'datagrid.th': () => ({
      class: 'bg-muted/50 font-semibold text-left px-4 py-3'
    }),
    'datagrid.td': () => ({
      class: 'px-4 py-3 border-t'
    })
  });
</script>

<slot />

Dynamic Presets with Bond

<script>
  import { setPreset } from '@svelte-atoms/core/context';

  setPreset({
    dropdown: (bond) => {
      const isOpen = bond?.state.open ?? false;
      
      return {
        class: [
          'dropdown-root',
          isOpen && 'dropdown-open'
        ],
        variants: {
          placement: {
            top: 'dropdown-top',
            bottom: 'dropdown-bottom',
            left: 'dropdown-left',
            right: 'dropdown-right'
          }
        }
      };
    }
  });
</script>

Conditional Attachments

<script>
  import { setPreset } from '@svelte-atoms/core/context';
  import { clickout, resizeObserver } from '@svelte-atoms/core/attachments';

  setPreset({
    dialog: (bond) => ({
      attachments: [
        clickout((ev) => bond?.close()),
        resizeObserver((entries) => {
          // Handle resize
        })
      ]
    })
  });
</script>

Nested Preset Configuration

<script>
  import { setPreset } from '@svelte-atoms/core/context';

  // Set global presets
  setPreset({
    button: () => ({ class: 'global-button' })
  });
</script>

<!-- Component tree -->
<div>
  <Button>Uses global preset</Button>

  <SpecialSection>
    <script>
      // Override presets for this section
      setPreset({
        button: () => ({ class: 'special-button' })
      });
    </script>

    <Button>Uses special preset</Button>
  </SpecialSection>
</div>

Available Components

Presets are available for all Svelte Atoms components:

Layout Components

  • accordion, accordion.item, accordion.item.body, accordion.item.header
  • card, card.header, card.body, card.footer
  • tabs, tab, tab.header, tab.body
  • dialog, drawer, popover

Form Components

  • button, input, checkbox, radio
  • dropdown, combobox, field
  • label, form

Data Components

  • datagrid, datagrid.header, datagrid.body, datagrid.footer
  • datagrid.tr, datagrid.th, datagrid.td
  • list, list.item, tree

Feedback Components

  • alert, badge, icon
  • divider, breadcrumb

Utility Components

  • portal, layer, scrollable
  • stepper, calendar, datepicker
See PresetModuleName for the complete list.

Best Practices

1. Set Presets at Root Level

<!-- +layout.svelte -->
<script>
  import { setPreset } from '@svelte-atoms/core/context';
  import { presets } from './presets';

  setPreset(presets);
</script>

<slot />

2. Organize Presets in Separate File

// presets.ts
import type { Preset } from '@svelte-atoms/core/context';

export const presets: Partial<Preset> = {
  button: () => ({ /* ... */ }),
  input: () => ({ /* ... */ }),
  // ...
};

3. Use TypeScript for Type Safety

import type { PresetEntry } from '@svelte-atoms/core/context';

const buttonPreset: PresetEntry = (bond) => ({
  class: 'btn',
  variants: {
    // TypeScript ensures correct structure
  }
});

4. Merge with Existing Presets

<script>
  import { getPreset, setPreset } from '@svelte-atoms/core/context';

  const existing = getPreset();
  
  setPreset({
    ...existing,
    button: () => ({
      // Your custom button preset
    })
  });
</script>

Performance Considerations

  • Preset functions are called during component rendering
  • Keep preset functions lightweight
  • Use derived values instead of expensive computations
  • Presets are merged, not replaced, allowing incremental customization

Build docs developers (and LLMs) love