Admin Demo Showcase GitHub
Developer Documentation

Lume CSS Documentation

Lume is a minimal CSS library for thoughtful interfaces. This documentation is organized by foundation, component, and utility layers, with copy-ready HTML snippets for each pattern.

CDN-ready CSS variables Dark mode Accessibility-aware Low JavaScript footprint
Production startup checklist: preload theme before CSS, use data-ui-init="pending" with html[data-ui-init="pending"] body { visibility: hidden; }, defer icon script, and reveal after window.load + bounded fonts wait. See No Flicker Setup.

Installation

Use Lume from the local file, your npm package build, or a CDN. Start with one stylesheet import, then apply No Flicker Setup for stable first paint.

CDN
<!-- latest (fastest updates) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.min.css" />

<!-- pinned (recommended for production stability) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css@1.0.0/dist/lume.min.css" />
npm / local build
npm install @iamtherealtim/lume-css

/* app.css */
@import "@iamtherealtim/lume-css/dist/lume.css";
For production, prefer pinned CDN versions and review CHANGELOG before upgrading.

Starter Templates

Choose a setup path: full bundle for fastest integration, or partial module imports when you want tighter payload control.

Full bundle (fastest)
<!-- HTML app shell -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.js"></script>
Partial modules (selective)
/* app.css */
@import "@iamtherealtim/lume-css/core.css";
@import "@iamtherealtim/lume-css/components.css";
@import "@iamtherealtim/lume-css/utilities.css";

/* optional */
@import "@iamtherealtim/lume-css/a11y.css";
@import "@iamtherealtim/lume-css/responsive.css";
Interactive starter (modal toggle)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.js"></script>

<button
  class="lume-btn lume-btn-primary"
  data-lume-toggle="modal"
  data-lume-target="#starter-modal">
  Open modal
</button>

<div class="lume-modal-overlay" id="starter-modal">
  <div class="lume-modal" role="dialog" aria-modal="true" aria-labelledby="starter-modal-title">
    <div class="lume-modal-header">
      <h3 class="lume-h4" id="starter-modal-title">Starter modal</h3>
      <button class="lume-modal-close" data-lume-close data-lume-target="#starter-modal" aria-label="Close">&times;</button>
    </div>
    <div class="lume-modal-body">
      <p class="lume-body">This modal opens and closes using Lume's data attributes.</p>
    </div>
    <div class="lume-modal-footer">
      <button class="lume-btn lume-btn-outline" data-lume-close data-lume-target="#starter-modal">Close</button>
    </div>
  </div>
</div>
Interactive starter (dropdown toggle)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.min.css" />
<script defer src="https://cdn.jsdelivr.net/npm/@iamtherealtim/lume-css/dist/lume.js"></script>

<div class="lume-dropdown" id="starter-dropdown">
  <button
    class="lume-btn lume-btn-outline"
    data-lume-toggle="dropdown"
    data-lume-target="#starter-dropdown">
    Open menu
  </button>

  <div class="lume-dropdown-menu" role="menu">
    <button class="lume-dropdown-item" role="menuitem">Profile</button>
    <button class="lume-dropdown-item" role="menuitem">Billing</button>
    <button class="lume-dropdown-item lume-dropdown-item-danger" role="menuitem">Sign out</button>
  </div>
</div>
Utilities are namespaced as lume-* to avoid collisions with existing app styles.

Migration & Integration

Adding Lume to an existing app usually takes three safe steps: import once, scope updates gradually, and swap custom utilities incrementally.

Incremental rollout checklist
  • Start with one route or feature area.
  • Use existing classes + add lume-* utilities gradually.
  • Adopt token overrides in app-level :root once layout is stable.
Stylesheet order
<link rel="stylesheet" href="/legacy.css" />
<link rel="stylesheet" href="/lume.css" />
<link rel="stylesheet" href="/app-overrides.css" />

No Flicker Setup

Use this startup pattern to prevent first-paint theme flashes and layout shifts while fonts and icons initialize. It sets theme early, keeps the page hidden during hydration, and reveals it once the UI is ready.

Drop-in startup snippet
<!-- 1) Prepaint init: place this before your CSS links -->
<script>
  document.documentElement.setAttribute('data-ui-init', 'pending');
  try {
    const savedTheme = localStorage.getItem('lume-theme');
    if (savedTheme) document.documentElement.setAttribute('data-theme', savedTheme);
  } catch (_) {}
</script>

<!-- 2) Lume CSS -->
<link rel="stylesheet" href="lume.css" />

<!-- 3) Optional icons: defer so layout CSS is available first -->
<script defer src="https://unpkg.com/lucide@latest"></script>

<!-- 4) Ready gate: run near end of body -->
<script>
  (function () {
    function initIcons() {
      if (window.lucide && typeof window.lucide.createIcons === 'function') {
        window.lucide.createIcons();
      }
    }

    function revealUi() {
      document.documentElement.removeAttribute('data-ui-init');
    }

    function waitForFontsOrTimeout(timeoutMs) {
      if (!document.fonts || !document.fonts.ready) {
        return Promise.resolve();
      }
      return Promise.race([
        document.fonts.ready,
        new Promise((resolve) => setTimeout(resolve, timeoutMs))
      ]);
    }

    window.addEventListener('load', function () {
      waitForFontsOrTimeout(1200).then(function () {
        initIcons();
        revealUi();
      });
    });
  })();
</script>
Required CSS guard in your app stylesheet: html[data-ui-init="pending"] body { visibility: hidden; }

Theming & Dark Mode

Override CSS custom properties to match your brand. Toggle dark mode by setting data-theme="dark" on <html>.

Theme override example
:root {
  --lume-accent: #7C3AED;
  --lume-accent-light: #EDE9FE;
  --lume-accent-dark: #5B21B6;
}

/* manual dark mode */
html[data-theme="dark"] {
  --lume-bg: #141412;
  --lume-text: #F0EFE9;
}
Tip: persist user theme preference with localStorage and apply it before CSS loads. See No Flicker Setup for the full startup pattern.

Browser Support

Lume targets modern evergreen browsers. Some visual enhancements (for example color-mix()) may gracefully degrade in older environments.

Browser Supported Notes
Chrome / Edge (current) Yes Full feature set
Firefox (current) Yes Full feature set
Safari 16.4+ Yes Recommended baseline for modern CSS parity
Legacy browsers Partial Core layout works; modern visual effects may degrade

Design Tokens

Lume exposes colors, spacing, typography, radius, and shadows through CSS custom properties. Build custom themes by overriding these tokens in your app stylesheet.

Core color tokens
--lume-text
--lume-accent
--lume-surface
--lume-success
:root {
  --lume-bg: #FAFAF8;
  --lume-surface: #F4F3EF;
  --lume-text: #1C1C1A;

  --lume-accent: #5B5BD6;
  --lume-accent-light: #EEEEF9;
  --lume-accent-dark: #3E3E9E;

  --lume-danger: #C0392B;
  --lume-warning: #B7791F;
  --lume-info: #1A5C8A;
  --lume-success: #30A46C;
}
Type, spacing, radius tokens
:root {
  --lume-font-sans: 'Instrument Sans', system-ui, sans-serif;
  --lume-font-serif: 'Lora', Georgia, serif;

  --lume-text-sm: 0.875rem;
  --lume-text-base: 1rem;
  --lume-text-lg: 1.125rem;

  --lume-space-2: 0.5rem;
  --lume-space-4: 1rem;
  --lume-space-6: 1.5rem;

  --lume-radius: 6px;
  --lume-radius-lg: 12px;

  --lume-shadow-sm: 0 1px 4px rgba(0,0,0,0.07);
}
Token Group Examples Used In
Color --lume-accent, --lume-border All components
Typography --lume-font-sans, --lume-text-lg Headings, body, controls
Spacing --lume-space-4, --lume-space-8 Padding, gaps, stacks
Radius / Shadow --lume-radius-md, --lume-shadow Cards, modals, dropdowns

Typography

Use semantic tags where possible and add Lume classes when you want the design-system styling applied. Lume includes display, heading, body, lead, small text, code, and blockquote patterns.

Typography scale
Display Heading
Heading One
Heading Two

Lead paragraph text for intros and section summaries.

Body text for long-form content and interface copy.

Small text for metadata and helper copy.

Good design is as little design as possible.
<div class="lume-display">Display Heading</div>
<div class="lume-h1">Heading One</div>
<div class="lume-h2">Heading Two</div>

<p class="lume-lead">Lead paragraph text...</p>
<p class="lume-body">Body text...</p>
<p class="lume-small">Small text...</p>

<blockquote class="lume-blockquote">
  Good design is as little design as possible.
</blockquote>
Prose and code

Writing with lume-prose

Use .lume-prose for article-like content where headings, paragraphs, lists, and blockquotes need consistent spacing.

  • Good defaults for body content
  • Readable line-height and max width
  • Works well in docs and blogs
<article class="lume-prose">
  <h2>Article title</h2>
  <p>Body paragraph...</p>
  <ul>
    <li>List item</li>
    <li>List item</li>
  </ul>
</article>
Class Purpose Typical Usage
.lume-display Largest serif heading Hero headers
.lume-h1 ... .lume-h6 Heading scale Section and card titles
.lume-lead Emphasized paragraph Intro copy
.lume-prose Long-form content wrapper Docs / blog article

Layout

Layout classes cover container sizing, grid columns, and flex helpers. Combine them with spacing utilities for fast page scaffolding.

Grid columns
Column 1
Column 2
Column 3
<div class="lume-grid lume-grid-3">
  <div>Column 1</div>
  <div>Column 2</div>
  <div>Column 3</div>
</div>
Flex + stack helpers
Left item Right item
Stack item A
Stack item B
Stack item C
<div class="lume-flex lume-justify-between lume-items-center">
  <span>Left item</span>
  <span>Right item</span>
</div>

<div class="lume-stack-2">
  <div>Stack item A</div>
  <div>Stack item B</div>
</div>
Class Description Notes
.lume-container Responsive page container Use -sm/-md/-lg/-xl variants
.lume-grid-2/3/4 Fixed equal grid columns Collapse at small breakpoints
.lume-grid-5/6 Extended fixed equal grid columns Useful for denser dashboards and data tiles
.lume-grid-auto-fill/auto-fit Auto-responsive grid tracks Adapts column count based on available width
.lume-grid-gap-1..8 Grid-specific gap spacing scale Use when you want gap control independent of flex gaps
.lume-grid-collapse-sm/md/lg Explicit breakpoint collapse modifiers Force single-column stack at selected breakpoints
.lume-flex + helpers Flex row/column alignment Pair with .lume-gap-*
.lume-stack-* Vertical spacing between children Includes .lume-stack-4

Buttons

Buttons include solid, outline, ghost, danger, size, pill, block, icon-ready, and gradient/special variants.

Button variants
<button class="lume-btn lume-btn-primary">Primary</button>
<button class="lume-btn lume-btn-outline">Outline</button>
<button class="lume-btn lume-btn-ghost">Ghost</button>

<button class="lume-btn lume-btn-primary lume-btn-sm">Small</button>
<button class="lume-btn lume-btn-primary lume-btn-pill">Pill</button>
<button class="lume-btn lume-btn-dark lume-btn-block">Full width</button>
Buttons with icons
<button class="lume-btn lume-btn-primary lume-with-icon">
  <i data-lucide="rocket" class="lume-icon"></i>
  Launch
</button>

<button class="lume-btn lume-btn-outline-primary lume-with-icon">
  <i data-lucide="sparkles" class="lume-icon"></i>
  Upgrade
</button>

<button class="lume-btn lume-btn-dark lume-with-icon">
  Share
  <i data-lucide="arrow-right" class="lume-icon"></i>
</button>

<button class="lume-btn lume-btn-primary lume-btn-pill lume-with-icon">
  <i data-lucide="check" class="lume-icon"></i>
  Confirm
</button>

<button class="lume-btn lume-btn-dark lume-btn-icon" aria-label="Favorite">
  <i data-lucide="heart" class="lume-icon"></i>
</button>
Gradient / special buttons
<button class="lume-btn lume-btn-gradient-aurora">Aurora Shift</button>
<button class="lume-btn lume-btn-gradient-sunset">Sunset Glow</button>
<button class="lume-btn lume-btn-gradient-ocean">Ocean Lift</button>
<button class="lume-btn lume-btn-gradient-violet">Violet Pulse</button>
<button class="lume-btn lume-btn-gradient-forest">Forest Rise</button>
<button class="lume-btn lume-btn-gradient-aurora lume-btn-pill">Aurora Pill</button>

<!-- Optional effect controls -->
<button class="lume-btn lume-btn-gradient-sunset lume-btn-no-glow">No Glow</button>
<button class="lume-btn lume-btn-gradient-ocean lume-btn-no-lift">No Lift</button>
<button class="lume-btn lume-btn-gradient-sunset lume-btn-no-filter">No Filter</button>
<button class="lume-btn lume-btn-gradient-aurora lume-btn-no-shift">No Shift</button>
<button class="lume-btn lume-btn-gradient-violet lume-btn-fx-off">FX Off</button>
Loading button pattern
<button class="lume-btn lume-btn-primary lume-btn-loading" aria-busy="true">
  Saving changes
</button>

<button class="lume-btn lume-btn-outline lume-btn-loading" disabled>
  Processing
</button>

Forms

Form controls include labeled inputs, selects, textarea, search fields, check/radio groups, errors, and input groups.

Common form patterns
As it appears on legal documents.
Please enter a valid email address.
https://
Drop files here or click to browse
PNG, JPG, PDF up to 10MB
<div class="lume-form-group">
  <label class="lume-label lume-label-required">Full name</label>
  <input class="lume-input" type="text" placeholder="Jane Smith" />
  <span class="lume-hint">As it appears on legal documents.</span>
</div>

<div class="lume-select-wrapper">
  <select class="lume-select">
    <option>United States</option>
    <option>Canada</option>
  </select>
</div>

<div class="lume-input-group">
  <span class="lume-input-addon">https://</span>
  <input class="lume-input" type="text" placeholder="yourdomain.com" />
</div>

<input class="lume-input lume-input-error" type="email" value="not-an-email" />
<span class="lume-error-message">Please enter a valid email address.</span>

<label class="lume-check-group">
  <input type="checkbox" checked />
  <span class="lume-check-label">Enable notifications</span>
</label>
<label class="lume-check-group">
  <input type="radio" name="plan" checked />
  <span class="lume-check-label">Starter plan</span>
</label>
<label class="lume-check-group">
  <input type="radio" name="plan" />
  <span class="lume-check-label">Pro plan</span>
</label>
<textarea class="lume-textarea" rows="3" placeholder="Tell us about yourself..."></textarea>
<input class="lume-range" type="range" min="0" max="100" value="60" />

<label class="lume-switch">
  <input type="checkbox" checked />
  <span class="lume-switch-track" aria-hidden="true"></span>
  <span class="lume-switch-label">Enable two-factor authentication</span>
</label>

<div class="lume-file">
  <input class="lume-file-input" type="file" />
  <div class="lume-file-dropzone">
    <div class="lume-file-title">Drop files here or click to browse</div>
    <div class="lume-file-meta">PNG, JPG, PDF up to 10MB</div>
  </div>
</div>
</div>

Cards

Cards support default, lifted, and filled surfaces, plus optional header/footer regions.

Card variants

Default card

Bordered surface for general content.

Lifted card

Primary content block with shadow.

Filled card

Muted surface for secondary content.

<div class="lume-card">
  <div class="lume-card-body">...</div>
</div>

<div class="lume-card lume-card-lifted">...</div>
<div class="lume-card lume-card-filled">...</div>
Card with header/footer
Project status Healthy

Daily backups succeeded. No incidents in the last 24 hours.

Interactive card links
<a class="lume-card lume-card-link lume-card-interactive" href="/reports/revenue">
  <div class="lume-card-body">
    <h3 class="lume-card-title">Revenue report</h3>
    <p class="lume-card-text">Open the weekly performance summary.</p>
  </div>
</a>

Badges & Tags

Use badges for status labels and tags for lightweight categorical chips.

Status indicators
Primary Active Pending Error Internal
Design Open Source Roadmap
<span class="lume-badge lume-badge-success lume-badge-dot lume-badge-pill">Active</span>
<span class="lume-badge lume-badge-danger">Error</span>

<span class="lume-tag">Design</span>
<span class="lume-tag">
  Roadmap
  <button class="lume-tag-close" aria-label="Remove">×</button>
</span>

Alerts

Alerts communicate inline feedback. Choose severity variant by context and include short action text.

Alert variants
<div class="lume-alert lume-alert-info" role="alert">
  <div class="lume-alert-content">
    <div class="lume-alert-title">Heads up</div>
    <div class="lume-alert-body">This is informational context.</div>
  </div>
</div>

<div class="lume-alert lume-alert-success" role="alert">
  <div class="lume-alert-content">
    <div class="lume-alert-title">Saved</div>
    <div class="lume-alert-body">Your changes were saved successfully.</div>
  </div>
</div>

<div class="lume-alert lume-alert-warning" role="alert">
  <div class="lume-alert-content">
    <div class="lume-alert-title">Usage limit</div>
    <div class="lume-alert-body">You are at 90% of your quota.</div>
  </div>
</div>

<div class="lume-alert lume-alert-danger" role="alert">
  <div class="lume-alert-content">
    <div class="lume-alert-title">Request failed</div>
    <div class="lume-alert-body">Please retry in a few seconds.</div>
  </div>
</div>

Tables

Tables support hover rows, compact density, striped rows, and right-aligned action columns.

Data table
Name Status Role Actions
Alice Chen Active Admin
Marcus Webb Pending Editor
<div class="lume-table-wrapper">
  <table class="lume-table lume-table-hover">
    <thead>
      <tr><th>Name</th><th>Status</th><th>Role</th><th class="lume-text-right">Actions</th></tr>
    </thead>
    <tbody>
      <tr>
        <td>Alice Chen</td>
        <td><span class="lume-badge lume-badge-success lume-badge-dot lume-badge-pill">Active</span></td>
        <td>Admin</td>
        <td class="text-right"><button class="lume-btn lume-btn-ghost lume-btn-sm">Edit</button></td>
      </tr>
    </tbody>
  </table>
</div>

Tooltip

Tooltips are attribute-driven and work on any inline or block element.

Note: CSS-only tooltips may clip inside overflow: hidden parents and complex scroll containers. For advanced positioning, use a JS-positioned popover/tooltip layer.

Directional tooltips
<button data-tooltip="Default tooltip">Hover</button>
<button data-tooltip="Bottom" data-tooltip-pos="bottom">Hover</button>
<button data-tooltip="Left" data-tooltip-pos="left">Hover</button>
<button data-tooltip="Right" data-tooltip-pos="right">Hover</button>

Tabs

Tabs are class-toggled components. Activate the selected tab and matching panel by id.

Underline tabs

Lume tabs are lightweight and framework-agnostic.

Toggle .is-active on both tab and panel.

Prefer keyboard navigation with focus-visible styles enabled.

<div class="lume-tabs">
  <button class="lume-tab is-active">Overview</button>
  <button class="lume-tab">API</button>
</div>
<div class="lume-tab-panels">
  <div class="lume-tab-panel is-active">...</div>
  <div class="lume-tab-panel">...</div>
</div>

Accordion

Accordions use native <details> and <summary>, so they work without JavaScript and are accessible by default.

Because it uses native <details>, open/close height animation is intentionally minimal. Use an enhanced JS variant if you need animated panels.

Details accordion
How do I install Lume?
Use CDN or npm and import one stylesheet into your app.
How do I customize colors?
Override CSS variables like --lume-accent.
<div class="lume-accordion">
  <details class="lume-accordion-item" open>
    <summary class="lume-accordion-trigger">Question</summary>
    <div class="lume-accordion-body">Answer</div>
  </details>
</div>

Progress & Spinner

Use progress bars for known completion states and spinners for indeterminate loading states.

Loading indicators
<div class="lume-progress">
  <div
    class="lume-progress-bar"
    role="progressbar"
    aria-label="Upload progress"
    aria-valuemin="0"
    aria-valuemax="100"
    aria-valuenow="72"
    style="width: 72%;">
  </div>
</div>

<div class="lume-progress">
  <div class="lume-progress-bar lume-progress-bar-striped" style="width: 45%;"></div>
</div>

<div class="lume-spinner lume-spinner-sm"></div>
<div class="lume-spinner"></div>
<div class="lume-spinner lume-spinner-lg"></div>

Avatar

Avatars support initials or image content, size modifiers, status dots, and overlapping groups.

Avatar patterns
SM
AC
MW
PN
AC
MW
JD
KR
TM
+2
<div class="lume-avatar">AC</div>
<div class="lume-avatar lume-avatar-lg">MW</div>

<div class="lume-avatar-wrapper">
  <div class="lume-avatar lume-avatar-lg">AC</div>
  <div class="lume-avatar-status"></div>
</div>

<div class="lume-avatar-group">
  <div class="lume-avatar">A</div>
  <div class="lume-avatar">B</div>
</div>

Toast

Toasts are temporary notifications. Use semantic variants for success, info, warning, and error feedback.

Toast variants
Saved
Your changes have been saved.
Upload failed
File exceeds size limit.
<div class="lume-toast lume-toast-success">
  <div class="lume-toast-content">
    <div class="lume-toast-title">Saved</div>
    <div class="lume-toast-body">Your changes have been saved.</div>
  </div>
</div>

<div class="lume-toast lume-toast-danger">
  <div class="lume-toast-content">
    <div class="lume-toast-title">Upload failed</div>
    <div class="lume-toast-body">File exceeds size limit.</div>
  </div>
</div>

Pagination

Pagination items support active and disabled state classes. Pair with server-side or client-side paging logic.

Page controls
<nav class="lume-pagination" aria-label="Pagination">
  <a class="lume-page-item is-disabled" aria-disabled="true" tabindex="-1">← Prev</a>
  <a class="lume-page-item is-active" aria-current="page">1</a>
  <a class="lume-page-item">2</a>
</nav>

Skeleton

Skeleton loaders preserve layout during async fetches and reduce perceived latency.

Skeleton card
<div class="lume-skeleton-card" role="status" aria-label="Loading content">
  <div class="lume-skeleton lume-skeleton-card-img"></div>
  <div class="lume-skeleton-card-body">
    <div class="lume-skeleton lume-skeleton-heading"></div>
    <div class="lume-skeleton lume-skeleton-text"></div>
  </div>
</div>

Callout

Callouts are persistent emphasis blocks for guidance, warnings, and important contextual information.

Callout variants
Default callout
Use callouts for persistent notes that should remain visible.
Info
This endpoint is rate limited to 100 requests per minute.
Warning
Migrating now may restart active sessions.
<div class="lume-callout">
  <div class="lume-callout-title">Default callout</div>
  Use callouts for persistent notes.
</div>

<div class="lume-callout lume-callout-info">
  <div class="lume-callout-title">Info</div>
  This endpoint is rate limited.
</div>

<div class="lume-callout lume-callout-warning">
  <div class="lume-callout-title">Warning</div>
  Migrating now may restart active sessions.
</div>

List Group

List groups are bordered vertical collections for settings menus, action lists, and simple data groups.

Settings list
Account
Profile Preferences Notifications
<div class="lume-list">
  <div class="lume-list-header">Account</div>
  <a class="lume-list-item lume-list-item-action">Profile</a>
  <a class="lume-list-item lume-list-item-action lume-list-item-active">Preferences</a>
  <button class="lume-list-item lume-list-item-action lume-list-item-danger">Delete account</button>
</div>

Stat / KPI

Stat cards present key metrics with trend context in dashboards and analytics screens.

KPI cards
Revenue
$84.2k
12.5% MoM
Churn
2.4%
0.3% MoM
Uptime
99.9%
No change
<div class="lume-stat">
  <div class="lume-stat-label">Revenue</div>
  <div class="lume-stat-value">$84.2k</div>
  <div class="lume-stat-trend lume-stat-trend-up">12.5% MoM</div>
</div>

<div class="lume-stat">
  <div class="lume-stat-label">Churn</div>
  <div class="lume-stat-value">2.4%</div>
  <div class="lume-stat-trend lume-stat-trend-down">0.3% MoM</div>
</div>

Empty State

Empty states guide users when no data exists yet. Include a clear action to unblock progress.

No data placeholder
📂
No files yet
Upload your first file to begin collaborating with your team.
<div class="lume-empty">
  <div class="lume-empty-icon">📂</div>
  <div class="lume-empty-title">No files yet</div>
  <div class="lume-empty-body">Upload your first file...</div>
  <div class="lume-empty-actions">...</div>
</div>

Stepper

Steppers communicate progress in multi-step flows. Use completed, active, and optional error state classes.

Horizontal + vertical stepper
Account
Profile
Billing
Review
Order placed
Shipped
Delivery failed
<div class="lume-steps">
  <div class="lume-step lume-step-completed">...</div>
  <div class="lume-step lume-step-active">...</div>
  <div class="lume-step lume-step-error">...</div>
</div>

<div class="lume-steps lume-steps-vertical">
  <div class="lume-step lume-step-completed">...</div>
  <div class="lume-step lume-step-active">...</div>
  <div class="lume-step lume-step-error">...</div>
</div>

Drawer

Drawers slide in from screen edges and work well for secondary workflows or contextual editing.

Right drawer
Edit profile
<div class="lume-drawer-overlay is-open"></div>
<div class="lume-drawer lume-drawer-right is-open">
  <div class="lume-drawer-header">...</div>
  <div class="lume-drawer-body">...</div>
</div>

Keyboard / Kbd

Use semantic <kbd> for shortcuts in docs and app help UI.

Shortcut tokens

Open command palette with K.

CtrlShiftPEscEnterTab
<p>Open command palette with <kbd>⌘</kbd> <kbd>K</kbd>.</p>

Utilities

Use utilities for small one-off adjustments. Keep usage intentional to preserve readability.

Category Utilities Example
Spacing lume-mt-*, lume-mb-*, lume-p-*, lume-px-*, lume-py-* class="lume-mt-4 lume-p-4"
Display / Flex lume-d-flex, lume-d-grid, lume-flex-1, lume-gap-* class="lume-d-flex lume-gap-4"
Responsive visibility lume-sm-hidden, lume-sm-block, lume-md-hidden, lume-lg-hidden class="lume-sm-hidden lume-md-block"
Text behavior lume-text-truncate, lume-text-wrap, lume-text-nowrap, lume-uppercase, lume-tracking-wide class="lume-text-truncate lume-uppercase"
Grid layout helpers lume-grid-gap-*, lume-grid-collapse-sm/md/lg class="lume-grid lume-grid-4 lume-grid-gap-6 lume-grid-collapse-md"
Overflow / Position lume-overflow-auto, lume-pos-relative, lume-pos-sticky class="lume-pos-sticky lume-inset-0"
Z-index lume-z-dropdown, lume-z-modal, lume-z-toast Layer orchestration
Opacity / Cursor lume-opacity-50, lume-cursor-not-allowed Disabled states
Transition / Aspect lume-transition-fast, lume-aspect-video Smooth state + media boxes
Utility composition example
Utility-first card shell

Composed from utility classes only.

<div class="lume-rounded-lg lume-overflow-hidden">
  <div class="lume-aspect-video"></div>
  <div class="lume-p-4">...</div>
</div>

<button class="lume-btn lume-btn-outline w-full transition-fast">
  Action
</button>

Icon Set & Mapping

Lume includes icon helper classes so icons can be dropped into buttons, pills, badges, tags, tabs, dropdown items, list rows, and breadcrumb links with consistent alignment and sizing.

The docs and admin demo use Lucide via data-lucide attributes. Lume itself is icon-library agnostic; these classes work with inline SVGs from any icon set.

UI Meaning Mapped Icon (data-lucide)
Dashboardlayout-dashboard
Analyticsbar-chart-3
Usersusers
Ordersshopping-cart
Billingcredit-card
Audit Logshistory
Support Ticketslife-buoy
Integrationsplug-zap
Settingssettings
Library Docsbook-open
Showcasesparkles
Menu togglemenu
Search fieldsearch
Class Purpose
.lume-icon Base icon size helper for inline icons
.lume-icon-sm / .lume-icon-lg Optional icon size modifiers
.lume-with-icon Align text + icon with consistent gap
.lume-icon-leading / .lume-icon-trailing Optional directional spacing nudges
Buttons, pills, badges, tags
<button class="lume-btn lume-btn-primary lume-with-icon">
  <i data-lucide="rocket" class="lume-icon"></i>
  Launch
</button>

<button class="lume-btn lume-btn-outline-primary lume-btn-pill lume-with-icon">
  <i data-lucide="sparkles" class="lume-icon"></i>
  Pro Pill
</button>

<span class="lume-badge lume-badge-info lume-badge-pill lume-with-icon">
  <i data-lucide="shield-check" class="lume-icon"></i>
  Verified
</span>

<span class="lume-tag lume-with-icon">
  <i data-lucide="tag" class="lume-icon"></i>
  Release
</span>
Tabs, dropdowns, list items, breadcrumb
<button class="lume-tab is-active">
  <i data-lucide="layout-dashboard" class="lume-icon"></i>
  Overview
</button>

<button class="lume-dropdown-item">
  <i data-lucide="user-cog" class="lume-icon"></i>
  Account settings
</button>

<a href="#" class="lume-list-item lume-list-item-action">
  <i data-lucide="folder-open" class="lume-icon"></i>
  Projects
</a>

<span class="lume-breadcrumb-item">
  <a href="#" class="lume-with-icon">
    <i data-lucide="home" class="lume-icon lume-icon-sm"></i>
    Home
  </a>
</span>

<!-- Run once after DOM is ready -->
<script>window.lucide?.createIcons();</script>

JavaScript Patterns

Most Lume components are CSS-only. Interactive components need tiny JS helpers that toggle classes and manage focus/escape behavior.

Tabs helper
function switchTab(tab, panelId) {
  const tabBar = tab.parentElement;
  const panels = tabBar.nextElementSibling;
  tabBar.querySelectorAll('.lume-tab').forEach(t => t.classList.remove('is-active'));
  panels.querySelectorAll('.lume-tab-panel').forEach(p => p.classList.remove('is-active'));
  tab.classList.add('is-active');
  document.getElementById(panelId).classList.add('is-active');
}
Dropdown outside-click
document.addEventListener('click', (event) => {
  document.querySelectorAll('.lume-dropdown.is-open').forEach((menu) => {
    if (!menu.contains(event.target)) {
      menu.classList.remove('is-open');
    }
  });
});
Data-attribute behaviors
<!-- Auto-dismiss after 5s (default) -->
<div class="lume-toast" data-lume-autodismiss="5000">
  Saved successfully
</div>

<!-- Opt out from auto-dismiss -->
<div class="lume-toast" data-lume-autodismiss="false">
  Persistent message
</div>

<!-- Remove parent row/chip/card from a button -->
<button data-lume-remove=".lume-tag">Remove</button>
Escape key close pattern
document.addEventListener('keydown', (event) => {
  if (event.key !== 'Escape') return;

  document.querySelectorAll('.lume-modal-overlay.is-open')
    .forEach((modal) => modal.classList.remove('is-open'));

  document.querySelectorAll('.lume-drawer.is-open')
    .forEach((drawer) => drawer.classList.remove('is-open'));
});

Accessibility

Lume includes visible focus styles and reduced motion support. Use this checklist during implementation.

Area What to implement Lume support
Keyboard navigation All interactive controls reachable with Tab :focus-visible styles included
Modal semantics role="dialog", aria-modal="true", focus trap Structure + styles provided
Alerts Use role="alert" for critical live updates Alert variants available
Motion Respect reduced motion preference @media (prefers-reduced-motion: reduce) support included
Contrast Verify custom theme contrast at WCAG AA Default palette is tuned for readability
Recommended QA: navigate docs with keyboard only, run Lighthouse accessibility audit, and test with reduced motion enabled at the OS level.