Theming
Light, dark or the reader's system setting, and every colour, font and radius as a CSS custom property.
The widget is styled entirely by CSS custom properties declared on its root element, .mv-root.
You change how it looks by setting those properties, through the config or through your own CSS.
Light, dark and system
appearance takes "system", "light" or "dark". The default, "system", follows the reader's
operating system setting. "light" and "dark" override that setting in both directions. The
widget writes an explicit choice to a data-mv-theme attribute on its root.
Through the config
theme sets properties as inline styles on the root, which take precedence over any stylesheet:
<MavnaWidget
config={{
integrator: "your-product",
theme: {
tokens: { "--mv-surface": "#101014", "--mv-ink": "#f4f4f5" },
font: "inherit",
radius: "12px",
},
}}
/>tokens takes any of the properties listed below. font, fontMono, radius and radiusLg set
--mv-font, --mv-font-mono, --mv-radius and --mv-radius-lg.
Through CSS
The widget declares its properties on .mv-root, so a .mv-root rule in your stylesheet ties with
it on specificity and the order your bundler emits the stylesheets decides which wins. Doubling the
class wins outright:
.mv-root.mv-root {
--mv-surface: #101014;
--mv-ink: #f4f4f5;
}Setting the properties on an ancestor element has no effect, because the widget declares them on its own root.
To change the dark theme as well, set your properties in a rule for
.mv-root[data-mv-theme="dark"] too.
The signal colour
--mv-signal and the properties derived from it are the widget's only colour. The widget uses it
for problems: error notes, an address that is not valid, the warning before sending the same
transfer again, and the button that finishes a delayed delivery.
Every property
Read from the widget's stylesheet, packages/widget/src/widget.css, when this site is built. The
values are shown as declared; you can set any value CSS accepts.
| Token | Light | Dark |
|---|---|---|
--mv-ground | oklch(0.985 0 0) | oklch(0.145 0 0) |
--mv-surface | oklch(1 0 0) | oklch(0.205 0 0) |
--mv-surface-2 | oklch(0.97 0 0) | oklch(0.245 0 0) |
--mv-surface-3 | oklch(0.94 0 0) | oklch(0.275 0 0) |
--mv-surface-4 | oklch(0.9 0 0) | oklch(0.32 0 0) |
--mv-ink | oklch(0.205 0 0) | oklch(0.985 0 0) |
--mv-white | oklch(0.205 0 0) | oklch(0.985 0 0) |
--mv-line | oklch(0.205 0 0) | oklch(0.985 0 0) |
--mv-on-light | oklch(0.985 0 0) | oklch(0.145 0 0) |
--mv-ink-strong | oklch(0.28 0 0) | oklch(0.9 0 0) |
--mv-cta-hover | oklch(0.32 0 0) | oklch(0.88 0 0) |
--mv-ink-2 | oklch(0.36 0 0) | oklch(0.8 0 0) |
--mv-ink-3 | oklch(0.42 0 0) | oklch(0.75 0 0) |
--mv-knob | oklch(0.3 0 0) | oklch(0.8 0 0) |
--mv-muted | oklch(0.46 0 0) | oklch(0.72 0 0) |
--mv-muted-b | oklch(0.48 0 0) | oklch(0.7 0 0) |
--mv-muted-2 | oklch(0.49 0 0) | oklch(0.685 0 0) |
--mv-faint | oklch(0.5 0 0) | oklch(0.67 0 0) |
--mv-faint-2 | oklch(0.51 0 0) | oklch(0.66 0 0) |
--mv-faintest | oklch(0.52 0 0) | oklch(0.65 0 0) |
--mv-rule-hair | oklch(0 0 0 / 0.07) | oklch(1 0 0 / 0.08) |
--mv-rule | oklch(0 0 0 / 0.1) | oklch(1 0 0 / 0.12) |
--mv-rule-2 | oklch(0 0 0 / 0.12) | oklch(1 0 0 / 0.16) |
--mv-rule-strong | oklch(0 0 0 / 0.18) | oklch(1 0 0 / 0.24) |
--mv-rule-hover | oklch(0 0 0 / 0.18) | oklch(1 0 0 / 0.24) |
--mv-rule-max | oklch(0 0 0 / 0.24) | oklch(1 0 0 / 0.34) |
--mv-focus | oklch(0 0 0 / 0.2) | oklch(1 0 0 / 0.18) |
--mv-fill-dim | oklch(0 0 0 / 0.14) | oklch(1 0 0 / 0.22) |
--mv-track-neutral | oklch(0 0 0 / 0.16) | oklch(1 0 0 / 0.3) |
--mv-signal | oklch(0.55 0.2 25) | oklch(0.74 0.16 22) |
--mv-signal-strong | oklch(0.55 0.22 25) | oklch(0.7 0.19 22) |
--mv-signal-line | color-mix(in oklab, var(--mv-signal-strong) 60%, transparent) | same |
--mv-signal-outline | color-mix(in oklab, var(--mv-signal-strong) 50%, transparent) | same |
--mv-signal-tint | color-mix(in oklab, var(--mv-signal-strong) 16%, transparent) | same |
--mv-scrim | oklch(0 0 0 / 0.35) | oklch(0 0 0 / 0.7) |
--mv-1 | 4px | same |
--mv-2 | 8px | same |
--mv-3 | 12px | same |
--mv-4 | 16px | same |
--mv-5 | 24px | same |
--mv-6 | 32px | same |
--mv-7 | 48px | same |
--mv-font | ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji" | same |
--mv-font-mono | ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace | same |
--mv-radius | 5.2px | same |
--mv-radius-lg | 7.2px | same |
--mv-ease | cubic-bezier(0.2, 0, 0, 1) | same |
--mv-swell | cubic-bezier(0.4, 0, 0.6, 1) | same |
--mv-fast | 140ms | same |
--mv-slow | 420ms | same |
--mv-hull | 14px | same |
Class names and the structure of the widget's HTML are not part of its interface. They start with
mv- so they cannot collide with yours, and they can change in any release.