Skip to content

Installation

For an existing framework application, use its complete setup guide. Each guide covers package installation, global CSS, component registration, event handling and its server-rendered integration.

AppSetup
React or Next.jsReact and Next.js
Angular or Angular SSRAngular
Vue or NuxtVue and Nuxt
Svelte or SvelteKitSvelte and SvelteKit
Plain HTMLFollow the Vite example below.

Keep AWC framework packages on the same release as @awc-ui/core. Framework wrappers have their own registration path; do not add a global /define import unless the framework guide calls for it. For server rendering, use the relevant server entry and the framework’s client adoption setup.

Use Node 22.13+ (22.x) or Node 24+ for this Vite development setup:

Terminal window
mkdir awc-example
cd awc-example
npm init -y
npm install @awc-ui/core
npm install --save-dev vite@7

Create index.html in that directory:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AWC UI example</title>
</head>
<body>
<script type="module">
import '@awc-ui/core/define';
document.querySelector('md-button').addEventListener('mdClick', () => {
document.querySelector('output').textContent = 'Created!';
});
</script>
<md-button variant="filled">Create</md-button>
<output aria-live="polite"></output>
</body>
</html>

Start the app:

Terminal window
npx vite

Open the local URL printed by Vite and select Create. “Created!” should appear beside the styled button. Run npx vite build for production output. Vite resolves the npm import in this HTML module. Opening the file directly or serving it through a plain static server cannot resolve that import.

@awc-ui/core/define registers the components and loads the bundled tokens CSS. You do not need a separate tokens package for this path. The example uses a text button; add the fonts below when you use icons or want Roboto typography.

Add these to your HTML <head> for icons and typography:

<!-- Material Symbols Outlined — the icon font the library is built around.
The four axis ranges are required: a default request returns a static
instance and the FILL transition silently stops working. -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200&display=swap"
/>
<!-- Roboto (default MD3 body font) -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
/>

Or install from npm:

Terminal window
npm install material-icons material-symbols
import "material-icons/iconfont/material-icons.css";
import "material-symbols/outlined.css";

The Vite example above is the recommended first setup. After it works, choose a more selective registration path if your bundle needs it. These are client-side bundler imports; /define imports CSS and is not a plain Node SSR entry.

import "@awc-ui/core/define";

This registers every component and loads the AWC UI design-token stylesheet.

import { defineCustomElements } from "@awc-ui/core/loader";
defineCustomElements(window);
import "@awc-ui/core/css/tokens.css";

The loader defines the tags at bootstrap, then loads each component implementation on demand when its element is used.

import "@awc-ui/core/components/md-button";
import "@awc-ui/core/components/md-text-field";
import "@awc-ui/core/css/tokens.css";

Only the imported components are included in your bundle.

The tokens CSS is loaded by /define. For loader or per-component imports, use the core package’s embedded stylesheet:

import "@awc-ui/core/css/tokens.css";

This provides the --md-sys-* CSS custom properties for colors, typography, shape, elevation and motion. Install @awc-ui/tokens separately when you want tokens independently of core; then use @awc-ui/tokens/tokens.css instead of loading both token sheets.

Components register before their code arrives. With /define or the loader, the runtime defines every tag at bootstrap and then fetches each component’s chunk on demand — so for a moment a layout-critical element like md-navigation-rail exists in the DOM with none of its own CSS, occupying no space. When the chunk lands, everything around it moves.

Opt in to size floors that hold the space in advance:

import "@awc-ui/core/css/tokens.css";
import "@awc-ui/core/css/pre-upgrade.css";

The sheet reserves the settled box of the components that carry page layout — md-navigation-rail, md-app-bar, md-toolbar, md-navigation-bar and md-fab — using each component’s own public custom property and default, so a reservation cannot drift from the thing it reserves for. They are minimums, so a component that settles at its floor does not move at all, and one that settles larger simply overrides it.

Every rule is gated on :not(.hydrated) and stops applying the moment that element renders.

If you write reservations of your own, gate them on .hydrated — not :not(:defined). The lazy runtime calls customElements.define() for every tag in one pass at bootstrap and only then fetches the chunks, so :defined flips while the element is still an empty box: the reservation evaporates before the styles it was standing in for arrive. .hydrated is the per-element flag the runtime sets when a component has rendered, which is the moment its box becomes real.

This is a floor, not a measurement: it cannot know how wide a button’s label will make it, or how tall a table will be once its data loads. It removes the shift that comes from a component having no size at all.

  • Quick Start — build your first page with AWC UI components
  • Web Components — use custom elements in plain HTML or any framework
  • React, Angular, Vue, or Svelte — framework-specific setup and SSR
  • Components — browse all 56 MD3 components, each with HTML, React, Angular, Vue, and Svelte tabs in-page
  • Theming — customize colors, shapes, and typography