Getting started
M3Nerd ships Svelte 5 components and pure CSS tokens. There is no runtime theming layer — if you can edit CSS variables, you can retheme the whole library.
Install
npm i m3nerd Requires Svelte 5 (>= 5.46). The package is ESM-only and peer-depends on svelte.
Usage
Import the stylesheet once at your app root, then use components anywhere:
<script lang="ts">
import 'm3nerd/styles.css';
import { Button, Card, TextField } from 'm3nerd';
</script>
<Card variant="elevated">
<TextField label="Email" placeholder="you@example.com" />
<Button variant="filled" onclick={submit}>Subscribe</Button>
</Card> The m3nerd/styles.css export resolves from the published package (see exports in package.json).
Theming
Every color, shape, and density value is a CSS custom property. Override them on :root (or any subtree). Light and dark values both travel in light-dark(), so a single override updates both schemes.
| Token / attribute | Default | Notes |
|---|---|---|
--m3-sys-primary | light-dark(#006a6a, #4fd8eb) | Brand color for filled buttons, focus rings, links |
--m3-sys-surface | light-dark(#fef7ff, #141218) | Base page surface; switches with color-scheme |
--m3-sys-surface-container | light-dark(#efedf1, #211f26) | Cards, nav bars, and elevated panels |
--m3-sys-shape-medium | 12px | One step of the 10-step corner radius scale |
data-density="compact" | scale 0.875 | Tighter control heights and rows (spacious = 1.125) |
data-focus-mode="tv" | 64px targets | 10-foot mode: larger targets, focus scale 1.05 |
data-theme="dark" | auto | Forces color-scheme; remove attribute to follow the system |
:root {
--m3-sys-primary: light-dark(#b3261e, #ffb4ab);
--m3-sys-shape-medium: 16px;
}
:root[data-theme='dark'] {
color-scheme: dark;
}Adaptivity
Five breakpoints, matching the Material Foundations spec. Components branch on tokens and CSS media/container queries — no resize observers in userland.
| Breakpoint | Width | Typical layout |
|---|---|---|
| compact | < 600px | Phones — bottom nav bar, single column |
| medium | 600–839px | Large phones / small tablets — navigation rail |
| expanded | 840–1199px | Tablets — two-pane layouts, denser rows |
| large | 1200–1599px | Notebooks — expanded rail, side sheets |
| xlarge | ≥ 1600px | Desktop / TV — max-width content, 10-foot focus |
Density
Set data-density on <html> to trade comfort for rows. compact shrinks control heights to 0.875×; spacious grows them to
1.125×.
<html data-density="compact"> TV focus mode
Set data-focus-mode="tv" for 10-foot interfaces: 64px touch targets, 52px
controls, larger body type, and a glowing focus ring that scales the focused element.
<html data-focus-mode="tv">Motion
Official Material 3 Expressive springs, pre-converted to cubic-bezier and duration pairs.
Spatial tokens may overshoot; effect tokens (color, opacity) are critically damped. prefers-reduced-motion collapses every composite token to 1ms.
| Token | Value | Notes |
|---|---|---|
--m3-motion-spatial-default | 500ms cubic-bezier(0.38, 1.21, 0.22, 1) | Hero spatial moves; may overshoot |
--m3-motion-spatial-fast | 350ms cubic-bezier(0.42, 1.67, 0.21, 0.9) | Snappy spatial moves; may overshoot |
--m3-motion-spatial-slow | 650ms cubic-bezier(0.39, 1.29, 0.35, 0.98) | Large spatial moves; may overshoot |
--m3-motion-default | 200ms cubic-bezier(0.34, 0.8, 0.34, 1) | Effects — color and opacity; never overshoots |
--m3-motion-fast | 150ms cubic-bezier(0.31, 0.94, 0.34, 1) | State layers and micro-interactions |
--m3-motion-slow | 300ms cubic-bezier(0.34, 0.88, 0.34, 1) | Slower effects; never overshoots |
--m3-motion-standard-default | 200ms cubic-bezier(0.27, 1.06, 0.18, 1) | Calmer standard scheme for non-hero surfaces |