GitHub ↗

skin-material

A Material Design skin for Fluixi UI — activate with data-ui="material".


Restyles the components to a Material 3 flavour: pill buttons with per-variant elevation and a click-origin ripple, M3 switch geometry, filled text fields, M3 surface radii, emphasized motion, and self-hosted Roboto. It composes with the data-theme and data-accent axes.

Installation

pnpm add @fluixi-ui/skin-material

Usage

Import the stylesheet after the tokens + preset, then set data-ui="material":

import '@fluixi-ui/tokens/preset.css';
import '@fluixi-ui/skin-material/styles.css';

document.documentElement.dataset.ui = 'material';

Or drive it reactively — lazy-loading the CSS only when the skin is active:

import { createTheme } from '@fluixi/core';

const skin = createTheme({
  attribute: 'data-ui',
  themes: ['fluixi', 'material'],
  default: 'fluixi',
  load: (s) => s === 'material' && import('@fluixi-ui/skin-material/styles.css'),
});
skin.init();

The ripple

The CSS state layer covers hover / focus / press, but a true click-origin ripple needs the pointer position — so it's a tiny JS primitive. Call installRipple once; it delegates a single pointerdown listener that spawns the ripple inside any Material control:

import { installRipple } from '@fluixi-ui/skin-material/ripple';

installRipple(); // returns a disposer

What it restyles

  • Buttons — pill shape; solid rests on elevation and lifts on hover (contained), while outline / ghost / soft stay flat (per-variant, as Material assigns it); currentColor state layer + ripple.
  • Selection controls — M3 switch (52×32, growing thumb), rounded checkbox, filled slider thumb.
  • Fields — filled text field / combobox (bottom border thickens to primary on focus).
  • Menus & lists — full-bleed rows with roomier padding.
  • Surfaces — M3 corner radii (dialog 28px, hover-card 12px, tooltip 4px); elevation from the shadow tokens.
  • Tabs — 3px rounded primary indicator.

How it works

All rules live in the flx.skin cascade layer, which sits above flx.components (the default look), so they win wherever they match — while your CSS stays unlayered and wins over both. Everything is scoped to [data-ui="material"], so the skin only applies where you opt in.


Part of the Fluixi UI component library. Made with ☕ by the Fluixi team.