Material 3 web components built with Stencil. More than 70 custom elements — buttons, text fields, dialogs, data tables — that style themselves from CSS custom properties and run in any page, with or without a framework.
Each component bundles its own CSS into its shadow root. The only stylesheet you
load is a theme file of --md-sys-color-* tokens. There is no runtime stylesheet
fetch and no build step for consumers.
npm install @viewflow/materialOr load it from a CDN with no install:
<script type="module" src="https://unpkg.com/@viewflow/material"></script>A page needs three things: the theme stylesheet, a theme class on <html>, and
the Material Symbols font.
<html lang="en" class="light">
<head>
<link rel="stylesheet" href="https://unpkg.com/@viewflow/material/css/theme.css">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0">
<script type="module" src="https://unpkg.com/@viewflow/material"></script>
</head>
<body>
<material-button variant="filled" label="It works" icon="check"></material-button>
</body>
</html>theme.csscarries the--md-sys-color-*custom properties. They cascade into every shadow tree, so components render themed with no per-component setup.- The
<html>class picks the theme:light,dark, or one of the four contrast variants. No class means no tokens. - The Material Symbols font renders the
icon="..."ligatures. Without it, icons show as their text names.
| Method | Source | Use it when |
|---|---|---|
| Single bundle | unpkg.com/@viewflow/material (~590 KB, all elements eager) |
You want one file and use many components. |
| Lazy loader | .../dist/material/material.esm.js (small entry) |
A page uses a few components; chunks load on demand. |
With a bundler:
import { defineCustomElements } from '@viewflow/material/loader';
import '@viewflow/material/theme.css';
defineCustomElements();Or import only the elements you use. Each one registers itself:
import '@viewflow/material/dist/components/material-button.js';- Self-contained styles. No stylesheet to fetch, no adopted-stylesheet wiring, no flash of unstyled content. A component renders correctly the moment it upgrades.
- Form association. Put a field in a
<form>with anameand it posts its value, runs constraint validation (required,checkValidity(),reportValidity()), and resets with the form. No hidden inputs. - Server-first. Components enhance server-rendered markup, such as a real
<table>insidematerial-data-tableor a real<form>post, instead of owning a client-side data model. - Plain events. Every interaction is a
CustomEventyou read withaddEventListener(valueChange,materialSort, …). - RTL and i18n. Set
dir="rtl"on any subtree and layout, animation, and keyboard direction follow. Strings and formats come from yourgettextandIntl, English by default. - Accessibility. Keyboard navigation, focus rings, 48dp touch targets,
Windows High Contrast, and
prefers-reduced-motionare built in.
| Group | Elements | Reference |
|---|---|---|
| Actions | button, icon-button, fab, fab-menu, split-button, button-group, chip, chip-set | actions.md |
| Text fields | textfield, textarea, number-field, masked-field, date-field, time-field, datetime-field, date-range-field, file-field, json-field | fields.md |
| Selection | checkbox, radio, switch, slider, select, autocomplete, dropzone | forms.md |
| Navigation | app-bar, toolbar, navigation-bar, navigation-rail, navigation-group, navigation-item, tabs, breadcrumbs, pagination, stepper | navigation.md |
| Overlays | dialog, bottom-sheet, side-sheet, menu, tooltip, snackbar, command-palette | overlays.md |
| Data & display | data-table, list, card, avatar, badge, divider, tree, transfer, calendar, carousel, rich-text, time-picker | display.md, data-table.md, lists.md |
| Progress | linear-progress, circular-progress, loading-indicator, skeleton | progress.md |
| Search | search, search-app-bar | search.md |
Tags and attributes are kebab-case (<material-date-field first-day-of-week="1">).
Boolean attributes follow HTML rules: present means true.
theme.css holds the tokens from
Material Theme Builder,
scoped to six classes: light, dark, and a medium- and high-contrast variant of
each. Switch themes by changing the <html> class.
To use your own palette, export a new set from the builder (Export → Web → CSS),
replace the six files in src/theme/, and rebuild. Component code never changes,
because every element reads the same --md-sys-color-* names. See
theming.md.
Each area has a reference under skills/material-web-components/references/:
- setup.md — loading the library on a page
- theming.md — tokens and palettes
- forms.md / fields.md — form controls and validation
- navigation.md, overlays.md, display.md, lists.md, data-table.md, progress.md, search.md, stepper.md
- i18n.md — catalogs and formats
- integrations.md — what you wire up (endpoints, persistence, file upload, maps)
Build from source and run the dev server:
git clone https://github.com/viewflow/material
cd material && npm install
npm start # http://localhost:3333npm start runs three watchers: theme bundling, Tailwind for the demo pages, and
Stencil's dev server. Every component has a demo page at
src/demos/<component>.html, which is where behavior is checked. There are no unit
tests; the components are mostly CSS, so demo pages carry the test cases.
Build the package:
npm run build # theme.css + Stencil dist/ + single-file CDN bundlenpm publish runs this build first through prepublishOnly.
Add a component:
npx stencil generate material-cardKeep each component's styles in its own shadow root and read var(--md-sys-color-*)
directly. src/global/material.css is a Tailwind entry for the demo and showcase
pages only; no <material-*> element depends on it.
@viewflow/material is an Open Source project. It uses the AGPL license,
The GNU Affero General Public License v3.0,
with the additional permissions in LICENSE_EXCEPTION.
The exception permits you to use this package in a project that has a license which is not compatible with the AGPL. A proprietary project is included. Your own code keeps your own license, and you do not release its source. The condition is that you do not change the source code of this package — importing the components, styling them through CSS custom properties, and shipping the bundle as-is all stay within the exception.
If you do change this package, the AGPL applies to your modified version of it.
The license scheme is the same as the license scheme of the GCC Runtime Library. The text above is a summary. Read LICENSE_EXCEPTION for the conditions.