Quick Start

Get up and running with Svelte Atoms in minutes. This guide will walk you through installation, configuration, and your first component.

Requirements

Make sure your project meets the following requirements:

  • Svelte 5

    Svelte Atoms is built for Svelte 5 and uses the new Runes API.

  • Tailwind CSS (Version 4)

    Components are styled with Tailwind CSS utilities for easy customization.

  • Node.js 18+

    Modern Node.js version for build tools and development.

Installation

Install @svelte-atoms/core using your preferred package manager:

npm install @svelte-atoms/core

Configuration

After installing the package, you need to configure your project to use the Svelte Atoms components and styling system.

1

Import Internal Styles

Import the internal style file in your root layout file (e.g., src/routes/+layout.svelte) to load the base styles for all components:

src/routes/+layout.svelte Svelte
<script>
  import '@svelte-atoms/core/styles/tw';
  import './app.css'; // Override @svelte-atoms/core styles here

  let { children } = $props;
</script>

{@render children?.()}

Important

Make sure to import the internal styles before your app.css to ensure proper style precedence.

2

Setup App CSS for Tailwind

Create or update your app.css file to include Tailwind directives and CSS variables that Svelte Atoms uses:

src/app.css CSS
@import 'tailwindcss';
@source './../node_modules/@svelte-atoms/core/**/*.{js,ts,svelte}'

:root {
	--background: oklch(1 0 0);
	--foreground: oklch(0.145 0 0);
	--card: oklch(1 0 0);
	--card-foreground: oklch(0.145 0 0);
	--popover: oklch(1 0 0);
	--popover-foreground: oklch(0.145 0 0);
	--primary: oklch(0.205 0 0);
	--primary-foreground: oklch(0.985 0 0);
	--secondary: oklch(0.97 0 0);
	--secondary-foreground: oklch(0.205 0 0);
	--muted: oklch(0.97 0 0);
	--muted-foreground: oklch(0.556 0 0);
	--accent: oklch(0.97 0 0);
	--accent-foreground: oklch(0.205 0 0);
	--destructive: oklch(0.577 0.245 27.325);
	--destructive-foreground: oklch(1 0 0);
	--border: oklch(0.922 0 0);
	--input: oklch(0.922 0 0);
	--ring: oklch(0.708 0 0);
	--chart-1: oklch(0.646 0.222 41.116);
	--chart-2: oklch(0.6 0.118 184.704);
	--chart-3: oklch(0.398 0.07 227.392);
	--chart-4: oklch(0.828 0.189 84.429);
	--chart-5: oklch(0.769 0.188 70.08);
	--radius: 0.625rem;
	--sidebar: oklch(0.985 0 0);
	--sidebar-foreground: oklch(0.145 0 0);
	--sidebar-primary: oklch(0.205 0 0);
	--sidebar-primary-foreground: oklch(0.985 0 0);
	--sidebar-accent: oklch(0.97 0 0);
	--sidebar-accent-foreground: oklch(0.205 0 0);
	--sidebar-border: oklch(0.922 0 0);
	--sidebar-ring: oklch(0.708 0 0);
	--radius: 0.625rem;
	--shadow-x: 0px;
	--shadow-y: 1px;
	--shadow-blur: 2px;
	--shadow-spread: 0px;
	--shadow-opacity: 0.18;
	--shadow-color: hsl(0 0% 0%);
	--tracking-normal: 0em;
	--spacing: 0.25rem;
}

.dark {
	--background: oklch(0.145 0 0);
	--foreground: oklch(0.985 0 0);
	--card: oklch(0.205 0 0);
	--card-foreground: oklch(0.985 0 0);
	--popover: oklch(0.205 0 0);
	--popover-foreground: oklch(0.985 0 0);
	--primary: oklch(0.922 0 0);
	--primary-foreground: oklch(0.205 0 0);
	--secondary: oklch(0.269 0 0);
	--secondary-foreground: oklch(0.985 0 0);
	--muted: oklch(0.269 0 0);
	--muted-foreground: oklch(0.708 0 0);
	--accent: oklch(0.269 0 0);
	--accent-foreground: oklch(0.985 0 0);
	--destructive: oklch(0.704 0.191 22.216);
	--destructive-foreground: oklch(0.985 0 0);
	--border: oklch(1 0 0 / 10%);
	--input: oklch(1 0 0 / 15%);
	--ring: oklch(0.556 0 0);
	--chart-1: oklch(0.488 0.243 264.376);
	--chart-2: oklch(0.696 0.17 162.48);
	--chart-3: oklch(0.769 0.188 70.08);
	--chart-4: oklch(0.627 0.265 303.9);
	--chart-5: oklch(0.645 0.246 16.439);
	--sidebar: oklch(0.205 0 0);
	--sidebar-foreground: oklch(0.985 0 0);
	--sidebar-primary: oklch(0.488 0.243 264.376);
	--sidebar-primary-foreground: oklch(0.985 0 0);
	--sidebar-accent: oklch(0.269 0 0);
	--sidebar-accent-foreground: oklch(0.985 0 0);
	--sidebar-border: oklch(1 0 0 / 10%);
	--sidebar-ring: oklch(0.556 0 0);
	--shadow-color: hsl(0, 0%, 100%);
}

@theme inline {
	--color-background: var(--background);
	--color-foreground: var(--foreground);
	--color-card: var(--card);
	--color-card-foreground: var(--card-foreground);
	--color-popover: var(--popover);
	--color-popover-foreground: var(--popover-foreground);
	--color-primary: var(--primary);
	--color-primary-foreground: var(--primary-foreground);
	--color-secondary: var(--secondary);
	--color-secondary-foreground: var(--secondary-foreground);
	--color-muted: var(--muted);
	--color-muted-foreground: var(--muted-foreground);
	--color-accent: var(--accent);
	--color-accent-foreground: var(--accent-foreground);
	--color-destructive: var(--destructive);
	--color-destructive-foreground: var(--destructive-foreground);
	--color-border: var(--border);
	--color-input: var(--input);
	--color-ring: var(--ring);
	--color-chart-1: var(--chart-1);
	--color-chart-2: var(--chart-2);
	--color-chart-3: var(--chart-3);
	--color-chart-4: var(--chart-4);
	--color-chart-5: var(--chart-5);
	--color-sidebar: var(--sidebar);
	--color-sidebar-foreground: var(--sidebar-foreground);
	--color-sidebar-primary: var(--sidebar-primary);
	--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
	--color-sidebar-accent: var(--sidebar-accent);
	--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
	--color-sidebar-border: var(--sidebar-border);
	--color-sidebar-ring: var(--sidebar-ring);

	--radius-inherit: inherit;
}

These CSS variables provide a complete theming system with light and dark mode support. You can customize these values to match your brand colors.

Note

Make sure to include node_modules/@svelte-atoms/core/**/* in your content array so Tailwind can detect classes used in the library components.

3

Configure Component Preset

Create a preset file to customize the default styles for Svelte Atoms components. This allows you to define your own variants and default classes:

src/preset.ts TypeScript
import { type Preset } from '@svelte-atoms/core';

export const preset: Partial<Preset> = {
  button: () => ({
    class: 'flex items-center px-3 py-2 h-12 transition-colors',
    variants: {
      variant: {
        primary: {
          class: 'bg-primary text-primary-foreground hover:bg-primary/80'
        },
        outline: {
          class: 'border border-border hover:bg-accent'
        }
      }
    },
    defaults: {
      variant: 'primary'
    }
  }),
  badge: () => ({
    class: 'inline-flex items-center rounded-md px-2 py-1 text-xs',
    variants: {
      variant: {
        primary: {
          class: 'bg-primary text-primary-foreground'
        },
        secondary: {
          class: 'bg-secondary text-secondary-foreground'
        }
      }
    }
  })
};

Your First Component

Now that everything is configured, let's create a simple example using a Button component:

src/routes/+page.svelte Svelte
<script lang="ts">
  import { Button } from '@svelte-atoms/core';
  
  let count = $state(0);
</script>

<div class="flex items-center gap-4 p-8">
  <Button onclick={() => count++}>
    Clicked {count} {count === 1 ? 'time' : 'times'}
  </Button>
  
  <Button variant="outline" onclick={() => count = 0}>
    Reset
  </Button>
</div>

Success!

You now have a working setup with Svelte Atoms. The components are fully styled and ready to use.

Next Steps

Now that you have Svelte Atoms set up, here are some recommended next steps:

Browse Components

Explore the full library of accessible, composable components.

View all components

Learn the Philosophy

Understand the Bond architecture and design principles behind Svelte Atoms.

Read the philosophy

Styling Guide

Learn how to customize component styles and create your own design system.

Styling guide

Accessibility

Discover how Svelte Atoms ensures your applications are accessible to everyone.

Accessibility guide

Need Help?

If you're still having issues, check out our GitHub repository for more examples and to report bugs.

View on GitHub