Skip to content

Repository files navigation

@viewflow/material

npm license: AGPL-3.0 + exception

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 — with one exception: material-data-table and material-breadcrumbs enhance real light-DOM markup (a server-rendered <table>, a real <nav>) rather than a shadow root, so their styling ships as a second, optional stylesheet (material.css). There is no runtime stylesheet fetch and no build step for consumers.

Install

npm install @viewflow/material

Or load it from a CDN with no install:

<script type="module" src="https://unpkg.com/@viewflow/material"></script>

Quick start

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.css carries 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.

Using material-data-table or material-breadcrumbs? Add @viewflow/material/material.css next to theme.css — see Light-DOM components.

Loading options

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';

What the components handle

  • 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 a name and 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> inside material-data-table or a real <form> post, instead of owning a client-side data model.
  • Plain events. Every interaction is a CustomEvent you read with addEventListener (valueChange, materialSort, …).
  • RTL and i18n. Set dir="rtl" on any subtree and layout, animation, and keyboard direction follow. Strings and formats come from your gettext and Intl, English by default.
  • Accessibility. Keyboard navigation, focus rings, 48dp touch targets, Windows High Contrast, and prefers-reduced-motion are built in.

Components

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.

Theming

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.

Light-DOM components

material-data-table and material-breadcrumbs enhance real server-rendered markup — a <table>, a <nav> — instead of owning a shadow root, so their styling can't be bundled into a JS chunk the way every other component's is. It ships as material.css, loaded the same way as theme.css:

<link rel="stylesheet" href="https://unpkg.com/@viewflow/material/css/theme.css">
<link rel="stylesheet" href="https://unpkg.com/@viewflow/material/css/material.css">

Skip it and the rest of the library still works — only these two render unstyled. Any future component built the same server-first way (enhancing markup that has to exist without JS) joins this file rather than getting its own.

Documentation

Each area has a reference under skills/material-web-components/references/:

Development

Build from source and run the dev server:

git clone https://github.com/viewflow/material
cd material && npm install
npm start        # http://localhost:3333

npm 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 + material.css + Stencil dist/ + single-file CDN bundle

npm publish runs this build first through prepublishOnly.

Add a component:

npx stencil generate material-card

Keep 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, plus the source npm run build:material:pkg reads to produce the published css/material.css (see Light-DOM components above). A component's own shadow-DOM styles never depend on it; only the two light-DOM components it @imports under layer(components) do.

License

@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.

About

Material 3 web components built with Stencil. External Tailwind stylesheet, swappable theme, framework-agnostic.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages