Keep meaning and hierarchy consistent across light, dark, and system appearance scopes.
A theme changes the appearance of an interface while preserving the meaning of its content and controls. Use semantic colors and supported component treatments so the same task remains recognizable in light and dark contexts.
Liquidify exports Theme from @liquidify/react and @liquidify/glass. Its type accepts light, dark, or system. An omitted type defaults to light; use system deliberately when the interface should follow the browser's preferred color scheme.
import type { ReactNode } from "react"
import { Theme } from "@liquidify/react"
import "@liquidify/react/styles.css"
export function ProductTheme({ children }: { children: ReactNode }) {
return <Theme type="system">{children}</Theme>
}Theme renders a wrapper with display: contents and the declared CSS color scheme. It does not provide a visible panel, background, padding, or a saved user preference. The application owns any appearance control and persistence.
Nested Theme scopes can set a different appearance for their descendants. Use them for a concrete need, such as a preview of another theme. Check overlays in their actual rendered location; a React context and the DOM location of portaled content can have different inheritance boundaries.
| Decision | Relevant mechanism |
|---|---|
| Light, dark, or system appearance | Theme's type |
| Meaning of foreground and surface colors | Semantic --lq-color-* tokens |
| A control's emphasis | Its supported variant, role, or tint |
| Forced increased contrast on participating surfaces | IncreaseContrast from @liquidify/glass |
| Custom artwork or literal colors | Application-owned assets and CSS |
Shipped token pairs use light-dark() to resolve against the active color scheme. Theme does not recolor a literal hexadecimal value or a raster image. Use Color to choose roles and evaluate translucent surfaces; dark appearance is not a blanket color inversion.
Figure in preparation
One task across appearance scopes
The same content retains meaning in light and dark themes.
IncreaseContrast is a context provider, not a styled DOM wrapper. With level="on", participating glass surfaces receive a forced-contrast attribute and select the associated semantic colors. Arbitrary HTML children do not acquire a contrast scope merely by being nested in the provider. The shipped CSS also responds to prefers-contrast: more.
Consequently, a theme comparison should include application-owned surfaces and plain text as well as glass controls. Inspect the final foreground and background together. Neither a dark theme nor the presence of an increased-contrast token proves that the complete composition meets the application's accessibility requirements.
Check the same content, labels, selected values, focus, disabled states, and busy states in both themes. If artwork loses essential detail, adjust the artwork or provide a deliberate theme variant. Keep the composition and meaning consistent between variants.
Test a system preference change while the page is open. Include nested scopes and temporary content, not only the initial screen. Do not assume that Theme also selects platform metrics, native window behavior, or a different component API.