Skip to content
EspañolEnglish

Your theme

Try your brand colour here: the library derives every colour role of the light and dark themes while respecting contrast. What you see is the library itself, running.

Brand colour
Second colour
Third colour
Theme

Your hex gives hue 219.5° and chroma 0.146. The lightness of each role is left alone, which is why contrast holds.

As it appears on the document
Shipping method
Before you confirm
The Professional plan includes priority support and unlimited users.
ActivePendingReview
Application progress72%

The three brand colours

SecondaryTertiary
data-tone="secondary"
Profile completed72%
data-tone="tertiary"
Profile completed72%

Your theme in one file

In your project the theme is not written by hand: it is declared in amset-ui.config.js and generated with npx amset-ui theme. Every key is optional.

KeyWhat it is
paletteUp to eight colours in hexadecimal: brand, secondary, tertiary, error, success, warning, info and neutral. Each one is derived: from one colour come all its roles (the normal one, the hover one, the pressed one, the soft one, the text...) keeping the lightness of each, in light and in dark.
colorsAn exact role, not derived: colors: { dark: { ink: '#E6FAFF' } }. So that a colour that already exists in your product comes out as it is.
baseThe global tokens that are not colours: radius, border-width, font...
componentsThe knobs of each component: components: { button: { radius: '999px' } } writes --amset-button-radius. The list comes from npx amset-ui knobs.
selectorThe root of the theme. By default :root; with another selector, a different brand per section.
outThe file it writes. By default amset-theme.css.

A misspelt key does not go unnoticed: the command names it and says which ones are valid. This is a real example, with what it writes:

amset-ui.config.js
export default {  palette: { brand: '#7c3aed', secondary: '#0f766e' },  colors: { dark: { ink: '#f5f3ff' } },  base: { radius: '10px' },  components: { button: { radius: '999px' } },  out: 'app/amset-theme.css',}
The configuration.
npx amset-ui theme
Aviso: accent-active (light) pedia una saturacion de 0.2336 y la pantalla solo llega a 0.2222. Se ha bajado para que el color sea el mismo en todas partes.Aviso: accent-soft (light) pedia una saturacion de 0.0273 y la pantalla solo llega a 0.0234. Se ha bajado para que el color sea el mismo en todas partes.Aviso: secondary-hover (light) pedia una saturacion de 0.0861 y la pantalla solo llega a 0.0787. Se ha bajado para que el color sea el mismo en todas partes.Aviso: secondary-active (light) pedia una saturacion de 0.081 y la pantalla solo llega a 0.07. Se ha bajado para que el color sea el mismo en todas partes.Aviso: secondary-text (light) pedia una saturacion de 0.0861 y la pantalla solo llega a 0.0823. Se ha bajado para que el color sea el mismo en todas partes.Aviso: accent-text (dark) pedia una saturacion de 0.1363 y la pantalla solo llega a 0.117. Se ha bajado para que el color sea el mismo en todas partes.Aviso: focus (dark) pedia una saturacion de 0.1363 y la pantalla solo llega a 0.117. Se ha bajado para que el color sea el mismo en todas partes.Aviso: secondary-hover (dark) pedia una saturacion de 0.0861 y la pantalla solo llega a 0.0823. Se ha bajado para que el color sea el mismo en todas partes.Aviso: secondary-active (dark) pedia una saturacion de 0.081 y la pantalla solo llega a 0.0735. Se ha bajado para que el color sea el mismo en todas partes.Escrito app/amset-theme.css (3.1 kB).Importalo despues de @amset/ui/styles.css.
Exit code 0 What it says when generating it: the colours it has had to adjust so they look the same on any screen.
app/amset-theme.css
/* Generado por "npx amset-ui theme" - no editar a mano. * Va sin @layer a proposito: asi gana sobre la capa amset-ui sin !important. * Importalo DESPUES de @amset/ui/styles.css. */:root {  --amset-accent: oklch(0.5 0.2466 293.01);  --amset-accent-hover: oklch(0.45 0.2466 293.01);  --amset-accent-active: oklch(0.4 0.2222 293.01);  --amset-accent-text: oklch(0.47 0.2466 293.01);  --amset-accent-soft: oklch(0.955 0.0234 293.01);  --amset-accent-ink: oklch(0.985 0.0077 293.01);  --amset-secondary: oklch(0.5 0.0861 186.39);  --amset-secondary-hover: oklch(0.45 0.0787 186.39);  --amset-secondary-active: oklch(0.4 0.07 186.39);  --amset-secondary-text: oklch(0.47 0.0823 186.39);  --amset-secondary-soft: oklch(0.955 0.0101 186.39);  --amset-secondary-ink: oklch(0.985 0.003 186.39);  --amset-focus: oklch(0.5 0.2466 293.01);  --amset-radius: 10px;} [data-theme='dark'] {  --amset-accent: oklch(0.52 0.2466 293.01);  --amset-accent-hover: oklch(0.47 0.2466 293.01);  --amset-accent-active: oklch(0.42 0.2334 293.01);  --amset-accent-text: oklch(0.79 0.117 293.01);  --amset-accent-soft: oklch(0.32 0.0908 293.01);  --amset-accent-ink: oklch(0.985 0.0077 293.01);  --amset-secondary: oklch(0.52 0.0861 186.39);  --amset-secondary-hover: oklch(0.47 0.0823 186.39);  --amset-secondary-active: oklch(0.42 0.0735 186.39);  --amset-secondary-text: oklch(0.79 0.0506 186.39);  --amset-secondary-soft: oklch(0.32 0.0329 186.39);  --amset-secondary-ink: oklch(0.985 0.003 186.39);  --amset-focus: oklch(0.79 0.117 293.01);  --amset-ink: #f5f3ff;} @media (prefers-color-scheme: dark) {  :root:not([data-theme='light']) {    --amset-accent: oklch(0.52 0.2466 293.01);    --amset-accent-hover: oklch(0.47 0.2466 293.01);    --amset-accent-active: oklch(0.42 0.2334 293.01);    --amset-accent-text: oklch(0.79 0.117 293.01);    --amset-accent-soft: oklch(0.32 0.0908 293.01);    --amset-accent-ink: oklch(0.985 0.0077 293.01);    --amset-secondary: oklch(0.52 0.0861 186.39);    --amset-secondary-hover: oklch(0.47 0.0823 186.39);    --amset-secondary-active: oklch(0.42 0.0735 186.39);    --amset-secondary-text: oklch(0.79 0.0506 186.39);    --amset-secondary-soft: oklch(0.32 0.0329 186.39);    --amset-secondary-ink: oklch(0.985 0.003 186.39);    --amset-focus: oklch(0.79 0.117 293.01);    --amset-ink: #f5f3ff;  }} @media print {  :root,  [data-theme='dark'],  :root:not([data-theme='light']) {    --amset-accent: oklch(0.5 0.2466 293.01);    --amset-accent-hover: oklch(0.45 0.2466 293.01);    --amset-accent-active: oklch(0.4 0.2222 293.01);    --amset-accent-text: oklch(0.47 0.2466 293.01);    --amset-accent-soft: oklch(0.955 0.0234 293.01);    --amset-accent-ink: oklch(0.985 0.0077 293.01);    --amset-secondary: oklch(0.5 0.0861 186.39);    --amset-secondary-hover: oklch(0.45 0.0787 186.39);    --amset-secondary-active: oklch(0.4 0.07 186.39);    --amset-secondary-text: oklch(0.47 0.0823 186.39);    --amset-secondary-soft: oklch(0.955 0.0101 186.39);    --amset-secondary-ink: oklch(0.985 0.003 186.39);    --amset-focus: oklch(0.5 0.2466 293.01);  }} .amset-button {  --amset-button-radius: 999px;}
The CSS it generates.

The colours in the CSS come out as oklch(). You give your palette in hex, and the result can come out in hex too: npx amset-ui theme --format hex writes each colour as #rrggbb (or #rrggbbaa when it has transparency). It is the same theme converted, not recalculated. It helps if your tool cannot read oklch(), like Figma.

Code
npx amset-ui theme --format hex

Inside, the theme is calculated and measured in OKLCH, which describes a colour the way a person sees it: lightness, chroma (how much colour it has) and hue. oklch(0.45 0.2466 293.01) is lightness 0.45, chroma 0.2466 and hue 293°. Only the hue and the chroma are taken from your hex; the lightness of each role (normal, hover, pressed, text) is left as it is, and that is what holds the contrast in light and in dark. In a hex that lightness cannot be read directly, so contrast is measured on the OKLCH value, and the command does not write a palette that falls short of WCAG AA.

When it goes to hex each channel is rounded to 8 bits, so two almost identical tones can end up as the same hex. The palette colours always fit in sRGB, and nothing else is lost. To adjust a colour by hand use colors: the generated CSS is rewritten every time you run the command.

Where the generated CSS goes

It is imported after the library. It has no @layer on purpose: that way it beats the amset-ui layer without a single !important. And the knobs are written on each component's selector, not on :root, because each component's stylesheet declares its knob inside its own rule.

app/globals.css
/* The global CSS: the library first, then your theme */@import '@amset/ui/styles/base.css';@import './amset-theme.css';

Three brand colours

Besides the accent (brand) there are a second and a third colour, secondary and tertiary, with their contrast pairs measured in light and in dark. Components with tone accept them directly; those without it (checkboxes, switches, sliders, tabs, steps, the calendar, the focus ring) take them from data-tone on the component itself or on any container.

Code
<Button tone="secondary">Second colour</Button> <section data-tone="tertiary">  {/* Checkboxes, switches, tabs and the focus ring take the third colour */}</section>

The same tokens in Figma

The library's repository includes a Figma plugin that adds the tokens as Variables with their two modes, light and dark, and draws the components from the playground.

What the plugin exports and what it does not.