Shared props
Every component that has a variant, size, density, colour or rounding takes the same prop, with the same values and the same meaning.
The vocabulary
variant:elevatedraises the colour as text on a surface with the theme's shadow,flatfills with the colour,tonaltints with it,outlineddraws it as text and border,textas text only, andplainis text with no hover or press wash.size:xstoxl. Each step is half a step of φ in height and a quarter step in text (Design scale).density:compact,defaultorcomfortablemoves heights and paddings a quarter step of φ, never the text.color: an intent (primary,success,warning,error,info,up,down),neutral, or a custom colour you register. Any other value is a type error.rounded:truekeeps the component's own radius,falseornonesquares it,sm–xlpick a theme radius andfullmakes a pill in every theme.
Set them once for a subtree with Defaults. Every value follows the active theme, so switch the theme or pack in the top bar and the preview below restyles.
Preview
| Variant | primary | success | warning | error | info | up | down | neutral |
|---|---|---|---|---|---|---|---|---|
| elevated | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
| flat | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
| tonal | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
| outlined | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
| text | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
| plain | Pay | Pay | Pay | Pay | Pay | Pay | Pay | Pay |
How it works
Each prop becomes a class, and each class only sets custom properties. The component decides where they apply, so one meaning works for a filled button, an outlined field and a tinted chip.
| Prop | Sets |
|---|---|
color | --sv-color,--sv-on-color |
variant | --sv-variant-bg,--sv-variant-fg,--sv-variant-border |
size | --sv-size-height,--sv-size-text |
density | --sv-density |
rounded | --sv-rounded |
Hover and press mix --sv-variant-fg over --sv-variant-bg by --sv-state-hover (8%) and --sv-state-press (13%). The classes live in
the sv.base layer, so a component can refine a value and your own unlayered CSS always
wins.
Custom colours
Add the colour to your themes with defineTheme, then register its name. The theme
stylesheet adds its sv-color-brand class, so it works like an intent, server-rendered
and without inline styles.
// themes.ts: add the colour to every theme you register
import { defineTheme, monolithDark, monolithLight } from 'sveltier';
export const themes = {
'brand-light': defineTheme({ colors: { brand: 'oklch(0.55 0.15 300)' } }, monolithLight),
'brand-dark': defineTheme({ colors: { brand: 'oklch(0.75 0.12 300)' } }, monolithDark)
};
// app.d.ts: make it a valid `color`
declare module 'sveltier' {
interface CustomColors {
brand: true;
}
}Your own components
sharedClasses is public, so your components can join the same system. Pass every shared
prop the component has, defaults included: the variables inherit, and a missing class would let a
nested component pick up its parent's value. For the same reason, only read the variables of props
your component has.
// app.d.ts
import type { Color, Size, Variant } from 'sveltier';
declare module 'sveltier' {
interface ComponentDefaults {
Pill: { variant: Variant; size: Size; color: Color };
}
}<script lang="ts">
import {
sharedClasses,
useDefaults,
type Color,
type ComponentDefaults,
type Size,
type Variant
} from 'sveltier';
interface Props {
label: string;
variant?: Variant;
size?: Size;
color?: Color;
}
let { label, variant, size, color }: Props = $props();
const resolve = useDefaults<ComponentDefaults['Pill']>('Pill', {
variant: 'tonal',
size: 'sm',
color: 'neutral'
});
// Every shared prop the component has, defaults included.
const p = $derived(resolve({ variant, size, color }));
</script>
<span class={['pill', sharedClasses(p)]}>{label}</span>
<style>
.pill {
display: inline-grid;
place-items: center;
block-size: var(--sv-size-height);
padding-inline: calc(var(--sv-size-height) * 0.382);
border: var(--sv-hairline) solid var(--sv-variant-border);
border-radius: var(--sv-radius-full);
background: var(--sv-variant-bg);
color: var(--sv-variant-fg);
font-size: var(--sv-size-text);
}
</style>See sharedClasses for the full API.