Mozilla Nova-styled web components written in TypeScript with Lit. The design tokens are compiled from Firefox's Nova design system, and the icons and illustrations from FirefoxUX/acorn-icons, so the components match Firefox and can be kept up to date with it.
Status: early proof of concept (see AMOENG-2723). Published to GitHub Packages under the
alphadist-tag; the API may change.
<moz-provider>provides ambient theme, locale, and high-contrast state to its descendants.- The Nova design tokens, as CSS custom properties and a typed map.
- A set of Nova-styled components:
- Actions:
<moz-button>(default / primary / destructive / ghost / muted, plus icon-only),<moz-chip>. - Surfaces & layout:
<moz-card>,<moz-details>,<moz-dialog>,<moz-box-group>with<moz-box-item>/<moz-box-button>/<moz-box-link>. - Navigation & structure:
<moz-page-nav>,<moz-breadcrumb>,<moz-segmented-control>,<moz-page-header>. - Forms:
<moz-input-text>(text / email / url / tel),<moz-input-search>(debounced search field),<moz-checkbox>(with<moz-checkbox-all>for select-all and<moz-checkbox-visual>for display-only),<moz-radio-group>with<moz-radio>,<moz-toggle>(a switch),<moz-label>,<moz-fieldset>— form-associated, with built-in labelling, description, and validation. - Status & feedback:
<moz-message-bar>,<moz-badge>,<moz-status-badge>(a status-colored pill),<moz-status-dot>(a status dot),<moz-five-star>(a read-only or selectable star rating). - Primitives:
<moz-icon>renders a named icon from the Nova set;<moz-illustration>renders a named illustration (kit pieces and pictograms), following the ambient theme for its light/dark variants.
- Actions:
These are standard custom elements, so they work in plain HTML and in any framework (React, Vue, Svelte, and so on). Typed React wrappers are included for a more idiomatic React API.
Published to GitHub Packages under the @mozilla scope. GitHub Packages requires a token for every install, public packages included, so point the @mozilla scope at the GitHub npm registry and authenticate.
Add to an .npmrc (in the project, or ~/.npmrc):
@mozilla:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
GITHUB_TOKEN must be a classic personal access token with the read:packages scope; fine-grained tokens don't work with the npm registry. Keep it in the environment rather than committing it. Then:
npm install @mozilla/acorn-web-components@alphaReleases publish only under the alpha dist-tag (never latest), so the @alpha qualifier is required — a bare install would resolve the nonexistent latest and fail.
lit and @lit/context are dependencies and install automatically. react and react-dom are optional peer dependencies, needed only if you use the @mozilla/acorn-web-components/react entry.
Load the token layer once at your app root, then import and use the components.
// Once, at the app entry: the foundation (tokens + document defaults).
import '@mozilla/acorn-web-components/foundation.css';
// Import the components you use (they self-register):
import '@mozilla/acorn-web-components/components/moz-button';
import '@mozilla/acorn-web-components/components/moz-icon';foundation.css is everything you need, but you can also import style sheets individually if you need finer control over load order.
<moz-button variant="primary" icon-start="edit">Edit</moz-button>
<moz-icon name="settings" size="large" label="Settings"></moz-icon>Importing from the package root (import '@mozilla/acorn-web-components') registers every component. Importing a per-component subpath pulls in only what you use.
Most theming is pure CSS: the tokens use light-dark(), so light and dark follow color-scheme. Wrap a subtree in <moz-provider> to control that, plus locale and high contrast, from the app:
<moz-provider theme="auto" locale="en-US" contrast="auto">
<!-- your app -->
</moz-provider>theme:light|dark|auto(setscolor-scheme).contrast:auto|high.highturns on the higher-contrast token set for everything inside. High contrast also responds to the OS automatically through@media (prefers-contrast)and@media (forced-colors).locale: BCP-47 locale, broadcast for future internationalization.
Per-component appearance is set through the token scales rather than arbitrary values (see each component below).
The React entry provides typed wrappers so props and events follow React conventions:
import { MozButton, MozProvider } from '@mozilla/acorn-web-components/react';
import '@mozilla/acorn-web-components/foundation.css';
export function App() {
return (
<MozProvider theme="auto">
<MozButton variant="primary" onClick={save}>Save</MozButton>
</MozProvider>
);
}The tokens ship as CSS custom properties in tokens.css (foundation, on :root), and also as a typed map:
import { tokens, type TokenName } from '@mozilla/acorn-web-components/tokens';
// tokens['--color-accent-primary'] === 'light-dark(var(--color-violet-50), var(--color-violet-30))'Component-specific tokens (--button-*, and so on) are scoped to each component's shadow root, so they don't leak into the global surface by default.
If, for example, you have an exisiting app in a previous design system, and want to attempt a blanket update without consuming these components. all-tokens.css re-exports the full set of tokens — foundation plus every component's tokens — on :root:
import '@mozilla/acorn-web-components/all-tokens.css';It's larger than tokens.css and everything sits in the @layer acorn.tokens cascade layer, so your own unlayered CSS overrides it without a specificity fight. Set color-scheme on :root (or use <moz-provider>) so the light-dark() values resolve.
| Entry | Contents |
|---|---|
@mozilla/acorn-web-components |
All components + tokens/option maps + types |
@mozilla/acorn-web-components/components/<name> |
A single component (e.g. moz-button) |
@mozilla/acorn-web-components/foundation.css |
Tokens + base defaults (one import) |
@mozilla/acorn-web-components/tokens.css |
Foundation tokens as CSS custom properties |
@mozilla/acorn-web-components/all-tokens.css |
Every token (foundation + all component tokens) on :root (opt-in; larger than tokens.css) |
@mozilla/acorn-web-components/base.css |
Document defaults (font family/size, color-scheme) |
@mozilla/acorn-web-components/tokens/<name>.css |
Raw per-component :host token CSS (advanced; components already bundle these) |
@mozilla/acorn-web-components/tokens |
Typed token map + TokenName |
@mozilla/acorn-web-components/react |
Typed React wrappers |
A Custom Elements Manifest (custom-elements.json) ships for editor autocomplete and tooling.
A live example of the components in action can be found in the pinguino DevHub AMO rebuild. Please note this is currently a work in progress.
Runnable usage examples live in examples/, served against the library source (no build step):
npm run exampleThis opens a dev server whose landing page links to each example. See examples/README.md for the list.
See DEVELOPMENT.md for how to build and work on the library, and how the tokens and icons are compiled from Firefox.
Licensed under the Mozilla Public License 2.0.