@poupe/tailwindcss
Version:
TailwindCSS v4 plugin for Poupe UI framework with theme customization support
562 lines (438 loc) • 16.1 kB
Markdown
# @poupe/tailwindcss
[](https://www.jsdocs.io/package/@poupe/tailwindcss)
[](https://www.npmjs.com/package/@poupe/tailwindcss)
[](../../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