New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

material-web-dx

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

material-web-dx

A DX library on top of Material Web — functional component API, theme builder, accessibility built-in

latest
npmnpm
Version
0.1.1
Version published
Weekly downloads
1
-66.67%
Maintainers
1
Weekly downloads
 
Created
Source

Material Web DX

A developer experience library on top of Material Web. It provides a default theme, dynamic color generation, dark mode, accessibility helpers, and per-component typed theme directives — so you can use Material Web components with minimal setup.

Install

npm install material-web-dx @material/web lit-html

@material/web and lit-html are peer dependencies.

Quick start

1. Import the base tokens and default theme

// Sizing, shape, typography fixes for Material Web
import "material-web-dx/theme/tokens.css";

// Default color palette (seed #5389df, Fidelity variant)
// Includes both light and dark mode
import "material-web-dx/theme/default.css";

That's it. No JavaScript required for a working theme. All Material Web components will pick up the colors and sizing automatically.

2. Register the Material Web components you need

import "@material/web/button/filled-button.js";
import "@material/web/button/outlined-button.js";
import "@material/web/textfield/outlined-text-field.js";

3. Use them in your HTML

<md-filled-button>Save</md-filled-button>
<md-outlined-text-field placeholder="Email" type="email"></md-outlined-text-field>

Dark mode

The default theme CSS supports dark mode out of the box. It activates via:

MethodHow
OS preferenceprefers-color-scheme: dark media query (automatic)
Explicit classAdd class="dark" to <html>
Data attributeAdd data-theme="dark" to <html>

To force light mode even when the OS is set to dark:

<html class="light">

or

<html data-theme="light">

Programmatic dark mode

import { toggleDarkMode, setDarkMode } from "material-web-dx";

// Toggle between light and dark
toggleDarkMode();

// Set explicitly
setDarkMode(true);  // dark
setDarkMode(false); // light

Custom themes

If the default palette doesn't fit your brand, generate a theme from any seed color:

import "material-web-dx/theme/tokens.css";
import { applyTheme } from "material-web-dx";

// Generate and apply a complete M3 color scheme from a single hex color
applyTheme("#6750A4", { variant: "Tonal Spot", dark: false });

Scheme variants

VariantDescription
Tonal SpotBalanced, muted tones (Material default)
FidelityColors stay close to the seed
VibrantSaturated, energetic palette
ExpressiveBold, dramatic color shifts
NeutralMinimal color, mostly greys
MonochromeSingle-hue greyscale
ContentDerived from image content colors

Generate without applying

import { generateTheme } from "material-web-dx";

const tokens = generateTheme("#6750A4", { dark: true, variant: "Vibrant" });
// tokens is a Record<string, string> of color token names to hex values
// e.g. { "primary": "#d0bcff", "on-primary": "#381e72", ... }

Export and use a custom theme file

You can export a generated theme as CSS or SCSS and save it as a static file in your project. This is ideal for production apps where you want zero runtime theme generation — just a plain CSS file checked into your repo.

Step 1: Generate the CSS

import { exportThemeCSS, exportThemeSCSS } from "material-web-dx";

const css = exportThemeCSS("#6750A4", { variant: "Fidelity" });
const scss = exportThemeSCSS("#6750A4", { variant: "Fidelity", dark: true });

// Copy the output and save it as a file
console.log(css);

You can also use the interactive Theme Builder on the docs site — pick your seed color and variant, then click "Export CSS" or "Export SCSS" and copy the output.

Step 2: Save as a file

Save the exported output as my-theme.css (or _my-theme.scss) in your project:

/* my-theme.css — exported from Material Web DX */
:root {
  --md-sys-color-primary: #6750a4;
  --md-sys-color-on-primary: #ffffff;
  --md-sys-color-primary-container: #eaddff;
  /* ... all 35 color tokens ... */
}

Step 3: Import it instead of the default theme

// Base sizing/shape/typography fixes (always needed)
import "material-web-dx/theme/tokens.css";

// Your custom color theme instead of the default
import "./my-theme.css";

That's it — no JavaScript, no runtime color generation. The tokens.css file handles sizing and shape, your custom file handles colors. All Material Web components pick up both automatically.

If you need both light and dark variants, export each separately and combine them:

/* my-theme.css */

/* Light */
:root {
  --md-sys-color-primary: #6750a4;
  /* ... */
}

/* Dark — activates via class, attribute, or OS preference */
:root.dark,
:root[data-theme="dark"] {
  --md-sys-color-primary: #d0bcff;
  /* ... */
}

@media (prefers-color-scheme: dark) {
  :root:not(.light):not([data-theme="light"]) {
    --md-sys-color-primary: #d0bcff;
    /* ... */
  }
}

Listen for theme changes

import { onThemeChange } from "material-web-dx";

const unsubscribe = onThemeChange((state) => {
  console.log(state.seedHex, state.variant, state.dark, state.tokens);
});

// Later: unsubscribe();

Semantic color variables

Access M3 system colors as CSS variable references:

import { colors } from "material-web-dx";

// colors.primary       → "var(--md-sys-color-primary)"
// colors.onPrimary     → "var(--md-sys-color-on-primary)"
// colors.surface       → "var(--md-sys-color-surface)"
// colors.error         → "var(--md-sys-color-error)"
// ... all 35 M3 system colors

Supported components

Material Web DX works with all Material Web components. The base token overrides in tokens.css fix sizing and spacing for the following:

Buttons

ComponentElement
Filled button<md-filled-button>
Outlined button<md-outlined-button>
Text button<md-text-button>
Filled tonal button<md-filled-tonal-button>
<md-filled-button>Save</md-filled-button>
<md-outlined-button>Cancel</md-outlined-button>
<md-text-button>Learn more</md-text-button>
<md-filled-tonal-button>Draft</md-filled-tonal-button>

<!-- With icons -->
<md-filled-button>
  <md-icon slot="icon">add</md-icon>
  Create
</md-filled-button>

Icon button

ComponentElement
Icon button<md-icon-button>
<md-icon-button aria-label="Settings">
  <md-icon>settings</md-icon>
</md-icon-button>

Text fields

ComponentElement
Filled text field<md-filled-text-field>
Outlined text field<md-outlined-text-field>
<md-filled-text-field placeholder="First name"></md-filled-text-field>
<md-outlined-text-field placeholder="Email" type="email">
  <md-icon slot="leading-icon">mail</md-icon>
</md-outlined-text-field>

<!-- With validation -->
<md-filled-text-field
  placeholder="Required field"
  error
  error-text="This field is required"
></md-filled-text-field>

Select

ComponentElement
Filled select<md-filled-select>
Outlined select<md-outlined-select>
<md-outlined-select>
  <md-select-option selected value="">
    <div slot="headline">Choose a country</div>
  </md-select-option>
  <md-select-option value="us">
    <div slot="headline">United States</div>
  </md-select-option>
  <md-select-option value="uk">
    <div slot="headline">United Kingdom</div>
  </md-select-option>
</md-outlined-select>

Selection controls

ComponentElement
Checkbox<md-checkbox>
Switch<md-switch>
Radio<md-radio>
Slider<md-slider>
<!-- Checkbox -->
<label><md-checkbox checked touch-target="wrapper"></md-checkbox> Notifications</label>

<!-- Switch -->
<label><md-switch selected></md-switch> Wi-Fi</label>

<!-- Radio group -->
<label><md-radio name="size" value="s" checked></md-radio> Small</label>
<label><md-radio name="size" value="m"></md-radio> Medium</label>
<label><md-radio name="size" value="l"></md-radio> Large</label>

<!-- Slider -->
<md-slider value="40"></md-slider>
<md-slider range value-start="20" value-end="70"></md-slider>

Chips

ComponentElement
Chip set<md-chip-set>
Filter chip<md-filter-chip>
Assist chip<md-assist-chip>
<md-chip-set>
  <md-filter-chip label="Running" selected></md-filter-chip>
  <md-filter-chip label="Cycling"></md-filter-chip>
</md-chip-set>

<md-chip-set>
  <md-assist-chip label="Share">
    <md-icon slot="icon">share</md-icon>
  </md-assist-chip>
</md-chip-set>

Tabs

ComponentElement
Tabs container<md-tabs>
Primary tab<md-primary-tab>
Secondary tab<md-secondary-tab>
<md-tabs>
  <md-primary-tab>
    <md-icon slot="icon">flight</md-icon>
    Flights
  </md-primary-tab>
  <md-primary-tab>
    <md-icon slot="icon">hotel</md-icon>
    Hotels
  </md-primary-tab>
</md-tabs>

<md-tabs>
  <md-secondary-tab>Overview</md-secondary-tab>
  <md-secondary-tab>Specs</md-secondary-tab>
  <md-secondary-tab>Reviews</md-secondary-tab>
</md-tabs>

List

ComponentElement
List<md-list>
List item<md-list-item>
Divider<md-divider>
<md-list>
  <md-list-item>
    <md-icon slot="start">person</md-icon>
    <div slot="headline">Alice Johnson</div>
    <div slot="supporting-text">Product Designer</div>
    <md-icon slot="end">chevron_right</md-icon>
  </md-list-item>
  <md-divider></md-divider>
  <md-list-item>
    <md-icon slot="start">person</md-icon>
    <div slot="headline">Bob Smith</div>
    <div slot="supporting-text">Engineer</div>
    <md-icon slot="end">chevron_right</md-icon>
  </md-list-item>
</md-list>

Dialog

ComponentElement
Dialog<md-dialog>
<md-dialog id="my-dialog">
  <div slot="headline">Save changes?</div>
  <form slot="content" method="dialog">
    Your unsaved changes will be lost.
  </form>
  <div slot="actions">
    <md-text-button @click=${() => dialog.close()}>Discard</md-text-button>
    <md-filled-button @click=${() => dialog.close()}>Save</md-filled-button>
  </div>
</md-dialog>

FAB (Floating Action Button)

ComponentElement
FAB<md-fab>
<!-- Icon only -->
<md-fab><md-icon slot="icon">edit</md-icon></md-fab>

<!-- Extended with label -->
<md-fab label="Compose"><md-icon slot="icon">create</md-icon></md-fab>

<!-- Sizes: small, medium (default), large -->
<md-fab size="small"><md-icon slot="icon">add</md-icon></md-fab>
<md-fab size="large"><md-icon slot="icon">add</md-icon></md-fab>

<!-- Color variants: primary (default), secondary, tertiary -->
<md-fab variant="secondary" label="Navigate">
  <md-icon slot="icon">navigation</md-icon>
</md-fab>

Progress indicators

ComponentElement
Linear progress<md-linear-progress>
Circular progress<md-circular-progress>
<!-- Determinate -->
<md-linear-progress value="0.6"></md-linear-progress>
<md-circular-progress value="0.7"></md-circular-progress>

<!-- Indeterminate -->
<md-linear-progress indeterminate></md-linear-progress>
<md-circular-progress indeterminate></md-circular-progress>

Menu

ComponentElement
Menu<md-menu>
Menu item<md-menu-item>
<div style="position: relative">
  <md-filled-button id="anchor">Open menu</md-filled-button>
  <md-menu anchor="anchor">
    <md-menu-item>
      <div slot="headline">Cut</div>
    </md-menu-item>
    <md-menu-item>
      <div slot="headline">Copy</div>
    </md-menu-item>
    <md-menu-item>
      <div slot="headline">Paste</div>
    </md-menu-item>
  </md-menu>
</div>

Accessibility helpers

Focus trap

Trap keyboard focus inside a container (useful for modals and dialogs):

import { focusTrap } from "material-web-dx";

const release = focusTrap(dialogElement);

// When the dialog closes:
release();

Keyboard navigation

Add arrow-key navigation to lists, menus, or tabs:

import { keyboardNav } from "material-web-dx";

const cleanup = keyboardNav(listElement, {
  direction: "vertical",  // "horizontal" | "vertical" | "both"
  wrap: true,              // wrap around at edges
  selector: "md-list-item" // custom selector for focusable items
});

// Later: cleanup();

ARIA helpers

import { uniqueId, spreadAttrs } from "material-web-dx";

const id = uniqueId("dialog"); // "dialog-1", "dialog-2", ...

const attrs = spreadAttrs({
  "aria-label": "Close",
  "aria-hidden": undefined,  // omitted
  "aria-expanded": false,    // omitted
});
// { "aria-label": "Close" }

What's included

Import pathWhat it does
material-web-dx/theme/tokens.cssBase sizing, shape, typography fixes
material-web-dx/theme/default.cssDefault color theme (light + dark)
material-web-dxTheme API, directives, components, a11y
material-web-dx/directivesPer-component typed theme directives
material-web-dx/a11yFocus trap, keyboard nav, ARIA helpers

Theme API reference

FunctionDescription
applyTheme(seed, options?)Generate and apply a color scheme to the document
generateTheme(seed, options?)Generate a color scheme without applying
applyColorTokens(tokenMap)Apply a custom set of color tokens
toggleDarkMode()Toggle between light and dark mode
setDarkMode(isDark)Set dark mode on or off
onThemeChange(listener)Subscribe to theme state changes; returns unsubscribe fn
exportThemeCSS(seed, options?)Export theme as a CSS string
exportThemeSCSS(seed, options?)Export theme as an SCSS string

ThemeOptions

interface ThemeOptions {
  dark?: boolean;    // default: false
  variant?: string;  // default: "Fidelity"
}

License

MIT

Keywords

material-web

FAQs

Package last updated on 17 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts