⌘K
(opens in new tab)
Liquidify
Documentation
Getting started
Concepts
Liquid GlassProvidersThemingCompositionControlled stateFormsAccessibilityBrowser supportFidelity notesSSR and React Server Components
Guides
Packages
Design tokens
Examples
AI resourcesDocumentation versions
Community

Theming

Drive appearance through the --lq-* design-token cascade and the token override provider.

Every visual value in Liquidify — colour, radius, glass tuning, motion — resolves from a --lq-* design-token custom property emitted by @liquidify/tokens. The library's own CSS never hard-codes a raw value; it reads tokens. That single rule is what makes theming a cascade concern rather than a per-component prop drill.

There are two layers to theming:

  1. Named environment providers — Theme, Material, and Backdrop — select a coherent bundle of token values (colour scheme, default material, backdrop volatility) for a subtree.
  2. LiquidTokenProvider — the one seam where a consumer writes explicit --lq-* values to override individual tokens for a subtree.

Environment providers

Theme is re-exported from @liquidify/react so the common single-package setup needs no second install. Material and Backdrop live in @liquidify/glass.

import { Theme } from "@liquidify/react"
import { Backdrop, Material } from "@liquidify/glass"

export function AppShell({ children }: { children: React.ReactNode }) {
  return (
    <Theme type="system">
      <Material default="regular">
        <Backdrop type="low">{children}</Backdrop>
      </Material>
    </Theme>
  )
}
ProviderSettingValuesDefault
Themetypelight, dark, systemlight
Materialdefaultfrosted, regular, clearregular
Backdroptypestatic, low, highlow

Providers are nestable and the nearest one wins for its setting. See Providers for the full contract.

Overriding tokens

LiquidTokenProvider accepts a tokens map of --lq-* custom properties and writes them onto its own display: contents root, so every descendant inherits them through the CSS cascade. A key that does not start with --lq- is dropped — a development no-op, never a silent leak.

import { LiquidTokenProvider } from "@liquidify/glass"
import { Button } from "@liquidify/react"

export function BrandedRegion() {
  return (
    <LiquidTokenProvider tokens={{ "--lq-color-accent": "rebeccapurple" }}>
      <Button variant="borderedProminent">Continue</Button>
    </LiquidTokenProvider>
  )
}

Because the override lands as a plain CSS custom-property value that the existing rules already consume, it wins with no specificity fight and needs no component-level style or per-instance prop. This is the architecture the library deliberately chose over prop drilling.

Nesting merges

An inner provider merges with the nearest ancestor: inner keys win, parent keys are inherited. Only a provider's own keys are written to its root; the cascade carries the rest for free.

import { LiquidTokenProvider } from "@liquidify/glass"
import { Slider } from "@liquidify/react"

export function NestedTokens() {
  return (
    <LiquidTokenProvider tokens={{ "--lq-color-accent": "teal" }}>
      <LiquidTokenProvider tokens={{ "--lq-radius-control": "0.25rem" }}>
        {/* accent: teal (inherited), radius: 0.25rem (own) */}
        <Slider aria-label="Amount" defaultValue={0.4} />
      </LiquidTokenProvider>
    </LiquidTokenProvider>
  )
}
ProvidersComposition