Theming
Lattice renders with a small set of semantic design tokens — CSS custom properties prefixed
with --lt-. Every token resolves through a host variable with a built-in fallback, so you can
theme Lattice by defining the host variables (the same names shadcn/ui uses) on :root and
.dark. For example, set --primary and Lattice’s --lt-primary follows.
Tokens are global and shared across components. The Style tab on each component example lists the tokens that example uses in its initial rendered state. Tokens that only appear in interactive or overlay content — a dropdown panel, a dialog, a popover that opens on demand — are not captured there; this page is the complete reference.
Dark mode
Section titled “Dark mode”Every token ships a light and a dark value (the Light and Dark columns below). Dark mode is
driven by a dark class on the <html> element: when it is present, the .dark host variables
take over and Lattice’s tokens follow. You theme dark mode the same way as light — by defining the
host variables under .dark.
Lattice manages the class for you through its appearance helpers, exported from the package:
initializeTheme()— call once before your app mounts (e.g. in your entry file). It reads the stored preference (localStoragekeyappearance, defaultsystem), applies thedarkclass andcolor-scheme, and keeps them in sync when the OS preference changes.useAppearance()— a hook returning{ appearance, resolvedAppearance, updateAppearance }.appearanceis the chosen mode ("light" | "dark" | "system"),resolvedAppearanceis the effective"light" | "dark"after resolvingsystem, andupdateAppearance(mode)persists the choice (tolocalStorageand a cookie) and applies it immediately. Build your own theme switcher on top of it.
import { initializeTheme, useAppearance } from "@lattice-php/lattice";
initializeTheme();
function AppearanceToggle() { const { appearance, updateAppearance } = useAppearance();
return ( <button onClick={() => updateAppearance(appearance === "dark" ? "light" : "dark")}> Toggle theme </button> );}Token reference
Section titled “Token reference”Colors
| Token | Host variable | Light | Dark |
|---|---|---|---|
--lt-bg | --background | oklch(0.97 0 0) | oklch(0.145 0 0) |
--lt-fg | --foreground | oklch(0.145 0 0) | oklch(0.985 0 0) |
--lt-surface | --card | oklch(1 0 0) | oklch(0.145 0 0) |
--lt-surface-fg | --card-foreground | oklch(0.145 0 0) | oklch(0.985 0 0) |
--lt-popover | --popover | oklch(1 0 0) | oklch(0.145 0 0) |
--lt-popover-fg | --popover-foreground | oklch(0.145 0 0) | oklch(0.985 0 0) |
--lt-primary | --primary | oklch(0.48 0.092 182) | oklch(0.74 0.105 182) |
--lt-primary-fg | --primary-foreground | oklch(0.985 0 0) | oklch(0.2 0.025 182) |
--lt-secondary | --secondary | oklch(0.97 0 0) | oklch(0.269 0 0) |
--lt-secondary-fg | --secondary-foreground | oklch(0.205 0 0) | oklch(0.985 0 0) |
--lt-muted | --muted | oklch(0.97 0 0) | oklch(0.269 0 0) |
--lt-muted-fg | --muted-foreground | oklch(0.556 0 0) | oklch(0.708 0 0) |
--lt-accent | --accent | oklch(0.965 0.013 182) | oklch(0.278 0.018 182) |
--lt-accent-fg | --accent-foreground | oklch(0.4 0.07 182) | oklch(0.985 0 0) |
--lt-danger | --destructive | oklch(0.585 0.21 27.3) | oklch(0.42 0.13 26) |
--lt-danger-fg | --destructive-foreground | oklch(0.985 0 0) | oklch(0.985 0 0) |
--lt-border | --border | oklch(0.922 0 0) | oklch(0.269 0 0) |
--lt-input | --input | oklch(0.922 0 0) | oklch(0.269 0 0) |
--lt-ring | --ring | oklch(0.72 0.075 182) | oklch(0.55 0.08 182) |
--lt-overlay | --overlay | oklch(0 0 0 / 0.5) | oklch(0 0 0 / 0.6) |
--lt-warning | --warning | oklch(0.84 0.14 88) | oklch(0.7 0.13 78) |
--lt-success | --success | oklch(0.62 0.125 160) | oklch(0.7 0.15 162) |
--lt-success-fg | --success-foreground | oklch(0.985 0 0) | oklch(0.205 0 0) |
--lt-info | --info | oklch(0.62 0.14 240) | oklch(0.7 0.14 240) |
--lt-info-fg | --info-foreground | oklch(0.985 0 0) | oklch(0.205 0 0) |
--lt-primary-hover | --primary-hover | oklch(0.43 0.092 182) | oklch(0.79 0.105 182) |
--lt-primary-active | --primary-active | oklch(0.39 0.092 182) | oklch(0.84 0.105 182) |
--lt-danger-hover | --destructive-hover | oklch(0.53 0.21 27.3) | oklch(0.47 0.13 26) |
--lt-danger-active | --destructive-active | oklch(0.48 0.21 27.3) | oklch(0.52 0.13 26) |
--lt-success-hover | --success-hover | oklch(0.57 0.125 160) | oklch(0.75 0.15 162) |
--lt-success-active | --success-active | oklch(0.52 0.125 160) | oklch(0.8 0.15 162) |
--lt-info-hover | --info-hover | oklch(0.57 0.14 240) | oklch(0.75 0.14 240) |
--lt-info-active | --info-active | oklch(0.52 0.14 240) | oklch(0.8 0.14 240) |
--lt-secondary-hover | --secondary-hover | oklch(0.93 0 0) | oklch(0.32 0 0) |
--lt-secondary-active | --secondary-active | oklch(0.9 0 0) | oklch(0.36 0 0) |
--lt-disabled | --disabled | oklch(0.95 0 0) | oklch(0.32 0 0) |
--lt-disabled-fg | --disabled-foreground | oklch(0.7 0 0) | oklch(0.55 0 0) |
--lt-icon-xs | — | 0.75rem | 0.75rem |
--lt-icon-sm | — | 0.875rem | 0.875rem |
--lt-icon-md | — | 1rem | 1rem |
--lt-icon-lg | — | 1.25rem | 1.25rem |
--lt-icon-xl | — | 1.5rem | 1.5rem |
--lt-icon-2xl | — | 2rem | 2rem |
--lt-icon-3xl | — | 2.5rem | 2.5rem |
--lt-icon-4xl | — | 3rem | 3rem |
--lt-icon-stroke | — | 1.5 | 1.5 |
--lt-control-h-sm | — | 2rem | 2rem |
--lt-control-h-md | — | 2.25rem | 2.25rem |
--lt-control-h-lg | — | 2.5rem | 2.5rem |
--lt-table-cell-x | — | calc(var(--spacing) * 4) | calc(var(--spacing) * 4) |
--lt-table-cell-y | — | calc(var(--spacing) * 4) | calc(var(--spacing) * 4) |
--lt-font-weight-normal | — | 400 | 400 |
--lt-font-weight-medium | — | 500 | 500 |
--lt-font-weight-semibold | — | 600 | 600 |
--lt-font-weight-bold | — | 700 | 700 |
--lt-shadow-xs | — | 0 1px 1px 0 oklch(0 0 0 / 0.04) | 0 1px 1px 0 oklch(0 0 0 / 0.04) |
--lt-shadow-sm | — | 0 1px 2px 0 oklch(0 0 0 / 0.05) | 0 1px 2px 0 oklch(0 0 0 / 0.05) |
--lt-shadow-md | — | 0 2px 4px -1px oklch(0 0 0 / 0.08), 0 1px 2px -1px oklch(0 0 0 / 0.06) | 0 2px 4px -1px oklch(0 0 0 / 0.08), 0 1px 2px -1px oklch(0 0 0 / 0.06) |
--lt-shadow-lg | — | 0 8px 16px -4px oklch(0 0 0 / 0.12), 0 2px 4px -2px oklch(0 0 0 / 0.08) | 0 8px 16px -4px oklch(0 0 0 / 0.12), 0 2px 4px -2px oklch(0 0 0 / 0.08) |
--lt-z-dropdown | — | 1000 | 1000 |
--lt-z-sticky | — | 1100 | 1100 |
--lt-z-overlay | — | 1200 | 1200 |
--lt-z-modal | — | 1300 | 1300 |
--lt-z-popover | — | 1400 | 1400 |
--lt-z-toast | — | 1500 | 1500 |
--lt-duration-fast | — | 120ms | 120ms |
--lt-duration-base | — | 160ms | 160ms |
--lt-sidebar-w | — | 16rem | 16rem |
--lt-sidebar-w-collapsed | — | 4rem | 4rem |
--lt-container-max | — | 80rem | 80rem |
--lt-gutter | — | calc(var(--spacing) * 6) | calc(var(--spacing) * 6) |
Radius
| Token | Host variable | Light | Dark |
|---|---|---|---|
--lt-radius | --radius | 0.5rem | 0.5rem |
--lt-radius-sm | — | calc(var(--lt-radius) - 0.125rem) | calc(var(--lt-radius) - 0.125rem) |
--lt-radius-xs | — | calc(var(--lt-radius) - 0.25rem) | calc(var(--lt-radius) - 0.25rem) |