Custom Theme
Material Design 3 derives an entire colour system from a small number of seed colours. You do not pick 60 values by hand — you pick a brand colour and the algorithm produces the tonal palettes and role mappings.
The Theme Generator does this in the browser and hands you a ready-to-use CSS file.
Step 1 — Generate
Section titled “Step 1 — Generate”Open the Theme Generator and:
- Enter your brand colour as the primary seed (hex, e.g.
#6750A4). - Optionally set secondary, tertiary and neutral seeds. Leave them blank and MD3 derives them from the primary.
- Preview live — the panel renders real AWC UI components in both light and dark mode, so you see buttons, fields and surfaces, not swatches.
- Check contrast. The generator validates role pairings against WCAG AA and flags any that fail.
- Click Download theme.css.
Step 2 — Import
Section titled “Step 2 — Import”Drop the file in your project and import it after the base tokens:
import '@awc-ui/core/define'; // componentsimport '@awc-ui/tokens'; // base MD3 tokensimport './theme.css'; // ← your generated theme, lastWith a plain <link>:
<link rel="stylesheet" href="/node_modules/@awc-ui/tokens/tokens.css"><link rel="stylesheet" href="/theme.css">That is the whole integration. Every component picks the theme up immediately — the tokens are inherited custom properties, so there is nothing to configure per component.
Framework specifics
Section titled “Framework specifics”// Next.js — app/layout.tsximport '@awc-ui/tokens';import '@/styles/theme.css';
// Nuxt — nuxt.config.tsexport default defineNuxtConfig({ css: ['@awc-ui/tokens/tokens.css', '~/assets/theme.css'],});
// Angular — angular.json "styles" (order is the array order)"styles": [ "node_modules/@awc-ui/tokens/tokens.css", "src/theme.css"]
// Vite / SvelteKit — in your root entryimport '@awc-ui/tokens';import './theme.css';What the file contains
Section titled “What the file contains”A generated theme is plain CSS custom properties — no build step, no runtime:
:root { --md-sys-color-primary: #6750A4; --md-sys-color-on-primary: #FFFFFF; --md-sys-color-primary-container: #EADDFF; --md-sys-color-on-primary-container: #21005D; /* …secondary, tertiary, error, surface, outline… */}
[data-theme="dark"] { --md-sys-color-primary: #D0BCFF; --md-sys-color-on-primary: #381E72; /* …the dark counterpart of every role… */}Both themes ship in one file, so dark mode works the
moment you set data-theme="dark".
Because it is only custom properties you can commit it, diff it, and hand-edit a role if you need to.
Generating in code
Section titled “Generating in code”For build-time or server-side generation, use @awc-ui/theme directly — the
same engine the generator page runs:
import { computeTheme, generateCss } from '@awc-ui/theme';
// secondaryHex / tertiaryHex are optional — omit them and M3 derives both// from the primary, which is what the generator page does by default.const theme = computeTheme({ primaryHex: '#6750A4' });const css = generateCss(theme); // the same CSS the download producesgenerateCss returns a string of plain CSS custom properties — no
JavaScript, no imports. Write it to a file and ship the file.
Useful for multi-tenant apps where each customer has a brand colour:
// Per-tenant stylesheet at build timefor (const tenant of tenants) { await writeFile( `dist/themes/${tenant.id}.css`, generateCss(computeTheme({ primaryHex: tenant.brandColor })), );}@awc-ui/theme also exposes applyTheme for switching at runtime and a
worker entry point for off-main-thread computation on large palettes. Reach for
those only when the user picks colours in your app — a fixed brand theme
should be generated once at build time.
Hand-editing after generation
Section titled “Hand-editing after generation”Change a role and everything using it follows — that is the point of the role layer:
/* theme.css — after the generated block */:root { --md-sys-color-primary: #005AC1;}Colour is only part of a theme. The typeface is a separate token:
:root { --md-sys-typescale-font-family: 'Inter', system-ui, sans-serif;}And the icon font is swappable independently:
:root { --md-sys-icon-font-family: 'Material Symbols Rounded';}Remember to actually load the font — the library does not inject it.
Related
Section titled “Related”- Theming Overview — how the token layers fit together
- Design Tokens — the full role reference
- Dark Mode — switching between the two blocks
- Customization — per-component overrides