npm package: @poupe/tailwindcss
Description: TailwindCSS v4 plugin for Poupe UI framework with theme customization support
Author: Alejandro Mery
Latest version: 0.5.0

# @poupe/tailwindcss

[![jsDocs.io](https://img.shields.io/badge/jsDocs.io-reference-blue)](https://www.jsdocs.io/package/@poupe/tailwindcss)
[![npm version](https://img.shields.io/npm/v/@poupe/tailwindcss.svg)](https://www.npmjs.com/package/@poupe/tailwindcss)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENCE.txt)

TailwindCSS v4 plugin for Material Design 3 themes with automatic
dark mode, elevation shadows, scrim overlays, and component utilities.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
  - [Basic Configuration](#basic-configuration)
  - [Using Flat Plugin Bridge](#using-flat-plugin-bridge)
  - [CSS Import with @plugin](#css-import-with-plugin)
  - [Creating Themes Programmatically](#creating-themes-programmatically)
- [Color System](#color-system)
- [Shadow System](#shadow-system)
- [Scrim Utilities](#scrim-utilities)
- [Surface Components](#surface-components)
- [Dark Mode](#dark-mode)
- [Configuration Options](#configuration-options)
- [API Reference](#api-reference)
- [Integration with Poupe Ecosystem](#integration-with-poupe-ecosystem)
- [Requirements](#requirements)
- [License](#license)

## Features

- 🎨 Material Design 3 color system with automatic dark themes
- 🌓 Built-in dark mode support (class or media query)
- ✨ Elevation shadows with z-level utilities (z1-z5)
- 🎭 Scrim overlays with Material Design z-index layering
- 🛠️ Surface component utilities with proper contrast
- 📦 Lightweight, tree-shakable API
- 🧩 CSS variables for external customization

## Installation

```bash
# npm
npm install -D @poupe/tailwindcss tailwindcss@4

# yarn
yarn add -D @poupe/tailwindcss tailwindcss@4

# pnpm
pnpm add -D @poupe/tailwindcss tailwindcss@4
```

## Usage

### Basic Configuration

`tailwind.config.ts`:

```typescript
import { themePlugin } from '@poupe/tailwindcss'

export default {
  plugins: [
    themePlugin({
      colors: {
        primary: '#1976d2',
        secondary: '#9c27b0',
      }
    }),
  ],
}
```

### Flat Plugin API

More concise configuration:

```typescript
import flatPlugin from '@poupe/tailwindcss'

export default {
  plugins: [
    flatPlugin({
      primary: '#6750A4',
      secondary: '#958DA5',
      error: '#B3261E',

      // Custom shades: [color, harmonize, ...shades]
      neutral: ['#E4E1F6', true, 50, 100, 200, 300, 400, 500,
                600, 700, 800, 900]
    }),
  ],
}
```

### CSS @plugin

Direct CSS integration:

```css
@import 'tailwindcss';

@plugin '@poupe/tailwindcss' {
  primary: #6750A4;
  secondary: #958DA5;
}
```

### CSS Assets

The package provides two pre-built CSS files that extend TailwindCSS v4:

#### `style.css`
Minimal theme-agnostic utilities and components:
- Surface component utilities
- Shadow system utilities (z1-z5)
- Scrim overlay utilities
- Material Design z-index system
- No color values - bring your own theme

Usage with TailwindCSS:
```css
/* Import together with TailwindCSS base */
@import 'tailwindcss';
@import '@poupe/tailwindcss';  /* or '@poupe/tailwindcss/style.css' */
```

#### `default.css`
Complete example with Material Design 3 theme:
- Full set of Material Design 3 CSS custom properties
- Default color values for all theme colors
- Complete shadow and elevation system
- All surface and scrim utilities
- Fixed color surface combinations
- Ready-to-use example theme

Usage:
```css
/* Import together with TailwindCSS base */
@import 'tailwindcss';
@import '@poupe/tailwindcss/default.css';
/* Override any variables as needed */
```

**Note**: These CSS files contain TailwindCSS v4 directives (@theme,
@utility) and must be used together with TailwindCSS base styles.

Shadow utilities:

```html
<div class="shadow-z1">Level 1</div>
<div class="shadow-z2">Level 2 (default)</div>
<div class="shadow-z3">Level 3</div>
<div class="shadow-z4">Level 4</div>
<div class="shadow-z5">Level 5</div>
<div class="inset-shadow">Inset Shadow</div>
```

## Scrim Utilities

Modal backdrop overlays with Material Design z-index layering:

```html
<!-- Semantic z-index levels -->
<div class="scrim-modal">Modal backdrop</div>
<div class="scrim-drawer">Drawer backdrop</div>
<div class="scrim-elevated">High priority overlay</div>

<!-- With opacity modifiers -->
<div class="scrim-modal/50">Modal with 50% opacity</div>
<div class="scrim-drawer/75">Drawer with 75% opacity</div>
<div class="scrim-content/25">Content overlay with 25% opacity</div>

<!-- Arbitrary z-index values with opacity -->
<div class="scrim-[1250]">Custom z-index</div>
<div class="scrim-[1250]/40">Custom z-index with 40% opacity</div>
<div class="scrim-[var(--custom-z)]/60">CSS variable with 60% opacity</div>
```

Material Design z-index scale:

```css
--md-z-navigation-persistent: 1000;  /* Mobile stepper, bottom nav */
--md-z-navigation-floating: 1050;    /* FAB, speed dial */
--md-z-navigation-top: 1100;         /* App bar, top navigation */
--md-z-drawer: 1200;                 /* Navigation drawer */
--md-z-modal: 1300;                  /* Modal dialogs */
--md-z-snackbar: 1400;               /* Snackbars, toasts */
--md-z-tooltip: 1500;                /* Tooltips */
```

Scrim variants (simplified naming):
- `scrim-base` (950) - Basic overlay, below navigation
- `scrim-content` (975) - Content overlay
- `scrim-drawer` (1250) - Drawer overlays
- `scrim-modal` (1275) - Modal preparation
- `scrim-elevated` (1350) - High-priority overlays
- `scrim-system` (1450) - System-level scrims

### Opacity Support

All scrim utilities support Tailwind's opacity modifier syntax:
- Default opacity: 32% (when no modifier is used)
- Custom opacity: `scrim-modal/50`, `scrim-drawer/75`, etc.
- Arbitrary z-index with opacity: `scrim-[100]/25`

**Technical Implementation:**
- Uses `--md-scrim-rgb` variable (following the same pattern as
  `--md-shadow-rgb`)
- TailwindCSS v4 `--modifier([percentage])` for capturing modifier values
- CSS custom properties enable dynamic opacity:
  `var(--md-scrim-opacity, 32%)`
- Automatic theme switching for scrim colors in dark/light modes
- Bridge pattern converts v4 syntax to v3 matchUtilities for broad
  compatibility

## Shape System

Material Design 3 shape utilities with extensible architecture:

### Shape Scale

```html
<!-- Shape scale utilities -->
<div class="shape-none">No rounding (0px)</div>
<div class="shape-extra-small">Extra small (4px)</div>
<div class="shape-small">Small (8px)</div>
<div class="shape-medium">Medium (12px)</div>
<div class="shape-large">Large (16px)</div>
<div class="shape-extra-large">Extra large (28px)</div>
<div class="shape-full">Full rounding (999px)</div>
```

### Shape Families

```html
<!-- Default rounded corners -->
<div class="shape-medium shape-rounded">Rounded corners</div>

<!-- iOS-style squircle (smooth corners) -->
<div class="shape-medium shape-squircle">Squircle shape</div>
```

### CSS Variables

All shapes use CSS variables for customization:

```css
:root {
  --md-shape-none: 0px;
  --md-shape-extra-small: 4px;
  --md-shape-small: 8px;
  --md-shape-medium: 12px;
  --md-shape-large: 16px;
  --md-shape-extra-large: 28px;
  --md-shape-full: 999px;
}
```

### Component-Specific Shapes

Material Design 3 component shape tokens with sensible defaults:

```html
<!-- Component shapes with default values -->
<button class="shape-button">Pill button (full rounding)</button>
<div class="shape-card">Card with medium rounding</div>
<button class="shape-fab">FAB with large rounding</button>
<input class="shape-text-field" placeholder="Text field">
<div class="shape-dialog">Dialog with extra-large rounding</div>
<span class="shape-chip">Chip with small rounding</span>

<!-- Squircle variants for smooth corners -->
<button class="shape-squircle-button">Smooth pill button</button>
<div class="shape-squircle-card">Smooth card</div>
```

Component shapes cascade through CSS variables:
- `--md-shape-button` → `--md-shape-full` → `999px`
- `--md-shape-card` → `--md-shape-medium` → `12px`
- `--md-shape-fab` → `--md-shape-large` → `16px`
- `--md-shape-text-field` → `--md-shape-extra-small` → `4px`
- `--md-shape-dialog` → `--md-shape-extra-large` → `28px`
- `--md-shape-chip` → `--md-shape-small` → `8px`

### Squircle Implementation

- Uses SVG masks for true iOS-style smooth corners
- Graceful fallback to border-radius for unsupported browsers
- Configurable corner smoothing via `--md-shape-corner-smooth`
- Future-ready for additional shape families (cut corners, diamonds, etc.)

### Programmatic Theme Generation

Generate CSS themes programmatically:

```typescript
import { makeThemeFromPartialOptions, formatTheme } from
  '@poupe/tailwindcss'

const theme = makeThemeFromPartialOptions({
  colors: {
    primary: { value: '#6750A4' },
    secondary: { value: '#958DA5' },
  },
})

const css = formatTheme(theme, 'class', '  ')
console.log(css.join('\n'))
```

## Color System

Comprehensive color palette with Tailwind CSS and CSS named colors:

- **Tailwind Colors**: Modern palette (slate, gray/grey, zinc, neutral,
  stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan,
  sky, blue, indigo, violet, purple, fuchsia, pink, rose)
- **CSS Named Colors**: Complete CSS specification fallback (149 colors)
- **Color Priority**: Tailwind colors take precedence over CSS named
  colors
- **Material Design 3**: Semantic colors with automatic dark themes
- **Color Shades**: Automatic shade variants (50-900)
- **CSS Variables**: All colors accessible as `--md-*`

```css
:root {
  --md-primary: 103, 80, 164;
  --md-primary-50: 244, 242, 250;
  --md-primary-500: 103, 80, 164;
  --md-primary-900: 30, 27, 38;
}
```

### Color Resolution

Colors are resolved with priority order:

```typescript
import { withKnownColor } from '@poupe/tailwindcss'

// Tailwind colors (highest priority)
withKnownColor('blue')     // '#3b82f6' (Tailwind blue)
withKnownColor('red')      // '#ef4444' (Tailwind red)
withKnownColor('gray')     // '#6b7280' (Tailwind gray)
withKnownColor('grey')     // '#6b7280' (British spelling alias)

// CSS named colors (fallback)
withKnownColor('crimson')  // '#dc143c' (CSS named color)
withKnownColor('navy')     // '#000080' (CSS named color)

// Unknown colors (unchanged)
withKnownColor('#custom')  // '#custom' (unchanged)
```

### Color Customization

Various color definition formats:

```typescript
flatPlugin({
  primary: '#6750A4',                      // Basic color
  secondary: ['#958DA5', false],           // No harmonization
  neutral: [50, 100, 200, 300, 400, 500], // Custom shades
  tertiary: ['#B58392', true, 50, 500],    // Harmonize + shades
})
```

## Shadow System

Material Design 3 elevation system with 5 z-levels:

- **z1**: Subtle elevation
- **z2/DEFAULT**: Standard floating elements
- **z3**: Prominent UI elements
- **z4**: Important modal windows
- **z5**: Critical/focused elements

Shadow utilities use `--md-shadow-rgb` variable for customization, while
scrim utilities use `--md-scrim-rgb`:

```css
--shadow-z1: 0 1px 4px 0 rgba(var(--md-shadow-rgb), 0.37);
--shadow-z2: 0 2px 2px 0 rgba(var(--md-shadow-rgb), 0.20),
             0 6px 10px 0 rgba(var(--md-shadow-rgb), 0.30);
```

```html
<div class="shadow-z1">Level 1</div>
<div class="drop-shadow-z3">Drop shadow</div>
<div class="inset-shadow">Inset effect</div>
```

## Surface Components

Component utilities with background + text color and proper contrast:

```html
<div class="surface-primary">Primary Surface</div>
<div class="surface-secondary">Secondary Surface</div>
<div class="surface-secondary-container">Secondary Container</div>

<div class="surface-container-lowest">Lowest</div>
<div class="surface-container-low">Low</div>
<div class="surface-container">Standard</div>
<div class="surface-container-high">High</div>
<div class="surface-container-highest">Highest</div>

<!-- Fixed color combinations -->
<div class="surface-primary-fixed">Fixed background with on-fixed text</div>
<div class="surface-primary-fixed-variant">
  Fixed background with variant text
</div>
<div class="surface-primary-fixed-dim">
  Dim fixed background with on-fixed text
</div>
<div class="surface-primary-fixed-dim-variant">
  Dim fixed with variant text
</div>
```

### Interactive Surface Components

Interactive surface utilities combine surface styling with Material Design 3
state layer support. They automatically include hover, focus, and pressed
states with proper transition timing:

```html
<!-- Interactive surfaces with built-in state layers -->
<button class="interactive-surface-primary">Primary Interactive</button>
<button class="interactive-surface-secondary">Secondary Interactive</button>
<button class="interactive-surface-tertiary">Tertiary Interactive</button>

<!-- Container variants with interaction states -->
<div class="interactive-surface-container-lowest">Interactive Lowest</div>
<div class="interactive-surface-container">Interactive Standard</div>
<div class="interactive-surface-container-highest">Interactive Highest</div>

<!-- Special interactive surfaces -->
<button class="interactive-surface-inverse-primary">Inverse Primary</button>
<button class="interactive-surface-error">Error Interactive</button>

<!-- Fixed color interactive surfaces -->
<button class="interactive-surface-primary-fixed">Fixed Interactive</button>
```

Interactive surfaces include:
- **Automatic state layers**: hover, focus, and pressed states
- **Smooth transitions**: Uses `--md-state-transition-duration` CSS variable
- **Proper contrast**: Maintains accessible text/background combinations
- **All surface variants**: Available for every standard surface utility

## Animation Utilities

Material Design animation effects:

### Ripple Effect

The `.ripple-effect` utility class provides Material Design ripple animations:

```html
<button class="relative overflow-hidden">
  Click me
  <span class="ripple-effect"></span>
</button>
```

Features:
- **Circular animation**: Expands from center with 50% border-radius
- **Configurable duration**: Use `--md-ripple-duration` (default: 600ms)
- **Configurable opacity**: Use `--md-ripple-opacity` (default: 0.12)
- **Color matching**: Uses `currentColor` to match parent text color
- **Performance**: Optimized with `will-change: transform, opacity`

```css
/* Customize ripple properties */
.custom-ripple {
  --md-ripple-duration: 800ms;
  --md-ripple-opacity: 0.2;
}
```

## Dark Mode

Automatic dark mode variants using `.dark` class (default):

```html
<html class="dark"><!-- Dark mode active --></html>
```

Customize dark mode strategy:

```typescript
themePlugin({
  darkMode: 'class',        // Default: .dark class
  // darkMode: 'media',     // Use @media (prefers-color-scheme)
  // darkSuffix: '-dark',   // Custom dark selector
})
```

## Configuration Options

**themePlugin()** - structured options:
```typescript
{
  themePrefix: 'md-',
  surfacePrefix: 'surface-',
  omitTheme: false,
  darkSuffix: '',
  shades: [50,100,200,300,400,500,600,700,800,900],
  colors: { primary: { value: '#6750A4' } }
}
```

**flatPlugin()** - flat color properties:
```typescript
{
  themePrefix: 'md-',
  surfacePrefix: 'surface-',
  primary: '#6750A4',              // Direct color definition
  secondary: ['#958DA5', false],   // [color, harmonize]
  neutral: [50, 100, 200, 500]     // Custom shades
}
```

## API Reference

```typescript
// Main exports
import flatPlugin, {
  themePlugin,
  makeThemeFromPartialOptions,
  formatTheme,
  colorFormatter
} from '@poupe/tailwindcss'

// Color system
import { defaultColors, withKnownColor } from
  '@poupe/tailwindcss/theme'

// Theme utilities
import { makeTheme, makeShadows, makeShades } from
  '@poupe/tailwindcss/theme'

// Color formatters: 'rgb' | 'hsl' | 'hex' | 'numbers'
const formatter = colorFormatter('rgb')
```

## Ecosystem

- [@poupe/theme-builder](../@poupe-theme-builder) - MD3 token generation
- [@poupe/vue](../@poupe-vue) - Vue components
- [@poupe/nuxt](../@poupe-nuxt) - Nuxt integration

## Requirements

- Node.js >=20, TailwindCSS ^4.1

## License

MIT