Clay1.0
Get started
Documentation

Up and running in a minute.

Clay is a CSS file and an optional ~15kb (gzipped) runtime. There's no build step, no framework lock-in and no dependencies. These docs cover installing it, picking a platform, theming it and taking your tokens native.

Getting started

Installation

Use whichever fits your stack. All options ship the same files.

CDN (fastest)

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/clay-ds@1/dist/clay.min.css">
<script src="https://cdn.jsdelivr.net/npm/clay-ds@1/dist/clay.min.js" defer></script>
<link rel="stylesheet" href="https://unpkg.com/clay-ds@1/dist/clay.min.css">
<!-- or straight from GitHub releases -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/litu173/clay-design-system@v1.0.0/dist/clay.min.css">

Package managers

npm install clay-ds
# or
pnpm add clay-ds
yarn add clay-ds
bun add clay-ds
import 'clay-ds/dist/clay.css';
import Clay from 'clay-ds';

Clay.init({ os: 'auto', mode: 'auto' });

Download

Grab clay.css, clay.js and tokens.json and self-host them.

Getting started

Quick start

Here's a complete page. Copy it into an .html file and open it.

<!doctype html>
<html lang="en" data-clay-os="auto" data-clay-mode="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/clay-ds@1/dist/clay.min.css">
  <script src="https://cdn.jsdelivr.net/npm/clay-ds@1/dist/clay.min.js" data-clay-auto data-os="auto" data-mode="auto" defer></script>
</head>
<body class="clay">
  <main class="clay-container clay-stack" style="padding-block:48px">
    <h1 class="clay-h1">Hello, Clay</h1>
    <div class="clay-card"><div class="clay-card-body">
      <div class="clay-field">
        <label for="email">Email</label>
        <input id="email" class="clay-input" placeholder="you@example.com">
      </div>
      <label class="clay-choice"><input type="checkbox" role="switch" class="clay-switch" checked> Subscribe</label>
      <button class="clay-btn" data-clay-toast="Welcome aboard!" data-clay-toast-type="success">Sign up</button>
    </div></div>
  </main>
</body>
</html>
Getting started

Choosing a platform

Set data-clay-os to web, ios, android, macos, windows, linux or auto (detect from the visitor's device). Set data-clay-mode to light, dark or auto. Keep both attributes on the same element. You can nest them to show several platforms on one page.

<section data-clay-os="ios" data-clay-mode="dark" class="clay"> …iOS preview… </section>
<section data-clay-os="windows" data-clay-mode="light" class="clay"> …Windows preview… </section>

Platform specs

The defaults each preset ships with, all drawn from the platform's official guidelines.

TokenWebiOSAndroidmacOSWindowsLinux
GuidelineClayHIGMaterial 3HIGFluent 2Adwaita
Accent#6d5efc#007aff#6750a4#007aff#0f6cbd#3584e4
TypefaceInterSF ProRobotoSF ProSegoe UI VariableCantarell
Body size16px17pt16sp13pt14px15px
Control height404440283234
Button radius1212full646
Card radius17141210812
Dialog radius24142812814
Switch44×2651×3152×3238×2240×2048×26
Input styleOutlinedFilledOutlinedBezelUnderline accentFilled
Press feedbackScale .97Scale .98RippleDarkenDarkenDarken
Tip: In hybrid apps built with Capacitor, Ionic, Electron, Tauri or a PWA, use data-clay-os="auto". The same build then looks like iOS on an iPhone, Material on a Pixel and Fluent on Windows.
Theming

CSS variables

Every decision is a --clay-* custom property. Override them globally, per section or per component. Colour ramps, soft tints and hover states are derived automatically.

:root {
  --clay-primary: #e11d48;         /* brand colour, ramps derive from it */
  --clay-on-primary: #ffffff;      /* text on primary */
  --clay-radius: 16px;             /* base radius, sm/lg/xl derive from it */
  --clay-font: "Sora", system-ui, sans-serif;
  --clay-font-scale: 1.05;         /* multiply the entire type ramp */
  --clay-density: 0.9;             /* compact controls and spacing */
  --clay-shadow-strength: 1.4;     /* deeper shadows */
}

/* Scoped: a marketing band with its own personality */
.promo { --clay-primary: #059669; --clay-btn-radius: 999px; }
GroupKey tokens
Colour--clay-primary --clay-on-primary --clay-secondary --clay-success|warning|danger|info --clay-bg --clay-surface[-2|-3] --clay-border[-strong] --clay-text[-2|-3] --clay-primary-50…900
Shape--clay-radius[-xs|-sm|-lg|-xl|-full] --clay-btn-radius --clay-input-radius --clay-card-radius --clay-dialog-radius
Type--clay-font --clay-font-display --clay-font-mono --clay-font-scale --clay-fs-display…caption --clay-fw-*
Space--clay-space --clay-density --clay-control-h-base
Depth--clay-shadow-1…4 --clay-shadow-strength --clay-glass
Motion--clay-dur --clay-dur-slow --clay-ease --clay-ease-spring --clay-press-scale --clay-ripple
Components--clay-switch-w|h|thumb --clay-range-* --clay-seg-* --clay-tab-ind-* --clay-input-focus --clay-list-sep-inset …
Theming

JavaScript API

The runtime is optional, and every component works as plain HTML and CSS. The runtime adds live theming, OS detection, toasts, dialog animation, menus, tabs, the calendar and token export.

// Boot: reads data-clay-* attributes and applies defaults
Clay.init({ os: 'auto', mode: 'auto', theme: 'ocean' });

// Theme live, null falls back to the platform preset
Clay.setTheme({ primary: '#7c3aed', radius: 18, font: 'Plus Jakarta Sans', density: 0.9 });
Clay.setOS('android');          // switch preset (resets colour/shape/type overrides)
Clay.setMode('dark');
Clay.onChange(theme => localStorage.setItem('theme', JSON.stringify(theme)));

// Feedback
Clay.toast({ title: 'Saved', message: 'All changes synced', type: 'success', action: { label: 'Undo', onClick: undo } });
Clay.dialog.open('#confirm');

// Tokens
const t = Clay.tokens();        // resolved values for the current theme
const swift = Clay.export('swiftui');
MethodDescription
init(options)Boot Clay on options.target (default <html>). Options: os, mode, theme, primary, secondary, radius, font, fontScale, density, space, shadow, motion.
setTheme(patch)Merge and apply theme options. Pass theme: 'rose' to load a brand theme. Returns the new theme.
setOS(os, keep?)Switch platform preset. Pass keep = true to keep colour, shape and type overrides.
setMode(mode)'light' | 'dark' | 'auto'. Auto follows the system setting live.
getTheme() / reset()Read the current options, or return to the platform defaults.
onChange(fn)Subscribe to theme changes. Returns an unsubscribe function.
detectOS()Best guess of the visitor's platform.
tokens(el?)Resolved tokens (hex colours, px sizes) for any element.
export(format)css, scss, json, figma, tailwind, swiftui, compose, flutter, xaml, gtk
toast(opts){ title, message, type, action, duration, position: 'corner'|'top'|'bottom' }
dialog.open / closeAnimated open and close for any <dialog class="clay-dialog">.
icon(name)Inline SVG string for a built-in icon.
contrast(hex) / contrastRatio(a, b)Pick readable text colour and check WCAG ratios.
upgrade(scope?)Hydrate icons, sliders and calendars in content added later (e.g. after a SPA route change).

Declarative attributes

AttributeEffect
data-clay-open="#id"Opens a dialog, sheet or drawer.
data-clay-closeCloses the nearest dialog (its value becomes returnValue).
data-clay-menuToggles the parent .clay-dropdown.
data-clay-toast="Title"Shows a toast. Add -message, -type and -action variants.
data-clay-tooltip="Text"CSS tooltip on hover or focus.
data-clay-icon="name"Put it on an <i> to render an icon.
data-clay-calendarRenders an interactive month view.
Theming

Token export

This is your current theme, compiled live for every platform. Change anything in the Foundations panel on the components page and the code below updates.

Guides

Frameworks

Clay is plain classes, so every framework just works. Here are the idiomatic setups.

import 'clay-ds/dist/clay.css';
import Clay from 'clay-ds';
import { useEffect } from 'react';

export default function RootLayout({ children }) {
  useEffect(() => { Clay.init({ os: 'auto', mode: 'auto' }); }, []);
  return (
    <html lang="en" data-clay-os="web" data-clay-mode="light">
      <body className="clay">{children}</body>
    </html>
  );
}

// Anywhere:
export const Button = ({ variant, ...p }) =>
  <button className={`clay-btn ${variant ? 'clay-btn--' + variant : ''}`} {...p} />;
import 'clay-ds/dist/clay.css';
import Clay from 'clay-ds';
createApp(App).mount('#app');
Clay.init({ os: 'auto' });
// <button class="clay-btn clay-btn--tonal" @click="save">Save</button>
<script>
  import 'clay-ds/dist/clay.css';
  import Clay from 'clay-ds';
  import { onMount } from 'svelte';
  onMount(() => Clay.init({ os: 'auto', mode: 'auto' }));
</script>
<slot />
"styles": ["node_modules/clay-ds/dist/clay.css", "src/styles.css"],
"scripts": ["node_modules/clay-ds/dist/clay.js"]
// Use Clay tokens as Tailwind utilities: bg-primary, rounded-lg, text-foreground-muted…
module.exports = {
  presets: [require('clay-ds/tailwind')],
  content: ['./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}'],
};
Guides

Native apps

Design in the browser and ship natively. Export your theme from the Foundations panel, drop the file into your project and reference the tokens.

PlatformExportUse it
iOS / iPadOS / macOSClayTheme.swiftText("Hi").foregroundStyle(Clay.Colors.primary)
AndroidClayTheme.ktWrap your app in ClayTheme { … } (Material 3)
Flutter (all OS)clay_theme.dartMaterialApp(theme: clayTheme)
WindowsClayTheme.xamlMerge into App.xaml resources (WinUI 3 / WPF)
Linuxgtk.cssOverrides libadwaita named colours (GTK 4)
Figmaclay.tokens.jsonImport with Tokens Studio or Variables (DTCG format)
React Native / Expoclay-tokens.jsonStyleSheet.create({ btn: { backgroundColor: t.color.primary } })
Guides

Accessibility

Clay targets WCAG 2.2 AA. Here's what's built in and what you're responsible for.

Built inYour part
Native elements (button, dialog, details, inputs) with correct semanticsGive icon-only buttons an aria-label
Visible focus rings on every interactive elementPair every input with a <label>
Keyboard support for tabs, menus, dialogs and OTP fieldsUse aria-invalid and aria-describedby for errors
Auto contrast for text on primary, plus a contrast checker in the Foundations panelCheck custom brand colours reach 4.5:1
prefers-reduced-motion and prefers-color-scheme supportKeep touch targets ≥ 44px (density ≥ 1 on mobile)
Guides

Browser support

Clay works in all evergreen browsers: Chrome, Edge and Opera 111+, Safari 16.2+ (iOS 16.2+) and Firefox 113+. It relies on color-mix(), <dialog>, :focus-visible and CSS custom properties. In Android WebView and WKWebView it follows the system engine.

Release notes

Changelog

  1. 1.0.0 · October 2026
    First release: six platform presets, 180+ components, per-platform catalogs, live Foundations panel, 10 export formats, 80+ icons.
  2. Next · planned
    visionOS and watchOS presets, KDE Breeze, RTL showcase, web components wrapper, Figma library.