Lattice reference

System

Density scaling, layout primitives, and surface tones layered on top of the style foundation, wired together by a single SystemProvider.

@lattice-ui/system Stable direction depends on core , style

System sits one level above @lattice-ui/style. Where Style owns the raw theme and host-prop helpers, System adds the app-facing layer: a density system that scales spacing, radius, and type globally; layout primitives (Stack, Row, Grid) that drive Roblox layout instances from theme spacing tokens; and surface tones for consistent backgrounds and borders. SystemProvider ties the theme and density together and feeds a density-resolved Theme down through ThemeProvider.

Import

import { SystemProvider, useSystemTheme } from "@lattice-ui/system";
import { DensityProvider, useDensity, applyDensity, density } from "@lattice-ui/system";
import { Stack, Row, Grid } from "@lattice-ui/system";
import { Surface, surface } from "@lattice-ui/system";

API reference

SystemProvider

The top-level provider. It owns the raw (base) theme, wraps a DensityProvider, and exposes both through a system context. Density transforms are applied internally and the resolved theme is passed down via @lattice-ui/style’s ThemeProvider, so any useTheme consumer below sees the density-scaled theme automatically.

function SystemProvider(props: SystemProviderProps): React.Element;
<SystemProvider defaultTheme={defaultDarkTheme} defaultDensity="comfortable">
{app}
</SystemProvider>

Theme and density are each independently controllable (theme/defaultTheme, density/defaultDensity). Writes always target the base theme; the resolved theme is derived from base theme plus current density.

Prop Type Description
theme Theme Controlled base theme. When set, SystemProvider does not own theme state.
defaultTheme Theme Initial base theme for uncontrolled usage. Defaults to defaultLightTheme.
onThemeChange (nextTheme: Theme) => void Called when the base theme changes.
density DensityToken Controlled density. "compact", "comfortable", or "spacious".
defaultDensity DensityToken Initial density for uncontrolled usage. Defaults to "comfortable".
onDensityChange (next: DensityToken) => void Called when density changes.
children React.ReactNode The subtree governed by this system.

useSystemTheme

function useSystemTheme(): SystemThemeContextValue;
const { theme, baseTheme, density, setBaseTheme, setDensity } = useSystemTheme();

Returns the system context: the density-resolved theme for reading, the baseTheme before density transforms, the current density, and setters. Writes go through setBaseTheme (raw theme) and setDensity. Must be called under a SystemProvider.

DensityProvider

The density layer used internally by SystemProvider, also usable on its own. It reads the base theme from the surrounding system base-theme context, resolves a density-scaled theme, and republishes it through ThemeProvider. Density is controllable via density/defaultDensity.

function DensityProvider(props: DensityProviderProps): React.Element;
<DensityProvider density="compact">{children}</DensityProvider>
Prop Type Description
density DensityToken Controlled density value.
defaultDensity DensityToken Initial density for uncontrolled usage. Defaults to "comfortable".
onDensityChange (next: DensityToken) => void Called when density changes.
children React.ReactNode The subtree receiving the density-resolved theme.

useDensity

function useDensity(): DensityContextValue;
const { density, setDensity } = useDensity();

Returns the current density token and a setDensity setter. Must be called under a DensityProvider (or SystemProvider).

applyDensity

function applyDensity(theme: Theme, token: DensityToken): Theme;
const compact = applyDensity(defaultLightTheme, "compact");

Pure theme transformer. Returns a new Theme with space, radius, and typography scaled by the token’s factors and colors carried through unchanged. Spacing and radius are rounded and clamped to a non-negative minimum; text sizes clamp to a minimum of 10. Density does not create layout or child instances — it only reshapes token values.

density

function density(token: DensityToken): (theme: Theme) => Theme;
const compact = density("compact");
const scaled = compact(theme);

A curried form of applyDensity — returns a theme transformer bound to a token, convenient where a (theme) => Theme function is expected.

Stack

Vertical-by-default flex layout primitive. Renders a transparent frame with a uilistlayout, mapping align/justify to Roblox alignment enums and resolving gap and padding through theme spacing tokens.

function Stack(props: StackProps): React.Element;
<Stack gap={8} align="center" padding={16}>
{children}
</Stack>

align controls the cross axis and justify the main axis (their effect swaps with direction). gap and every padding field accept a SpaceToken (resolved through the theme) or a raw pixel number. autoSize maps to AutomaticSize; sx and any direct host props are merged on top of the transparent base. asChild is not supported and throws if passed.

Prop Type Description
direction LayoutDirection "vertical" (default) or "horizontal".
gap SpaceValue Spacing between children: a space token or pixel number. Defaults to 0.
align StackAlign Cross-axis alignment: "start", "center", or "end". Defaults to "start".
justify StackJustify Main-axis alignment: "start", "center", or "end". Defaults to "start".
autoSize StackAutoSize boolean | "x" | "y" | "xy". Maps to AutomaticSize; true picks the main axis.
padding... SpaceValue padding, paddingX/Y, and paddingTop/Right/Bottom/Left, resolved via theme spacing.
sx Sx<StyleProps> Extra host props, merged over the transparent base.
children React.ReactNode Laid-out children.

Row

function Row(props: RowProps): React.Element;
<Row gap={6}>{children}</Row>

A Stack with direction fixed to "horizontal". Accepts every StackProps field except direction (RowProps = Omit<StackProps, "direction">).

Grid

Responsive grid primitive backed by a uigridlayout. It measures its own AbsoluteSize and resolves the column count and cell width on layout changes — either honoring a fixed columns or fitting as many minColumnWidth cells as the container allows.

function Grid(props: GridProps): React.Element;
<Grid minColumnWidth={120} gap={8} cellHeight={48}>
{children}
</Grid>

gap sets both axes; rowGap/columnGap override per axis. All spacing accepts tokens or pixels. cellHeight defaults to 32. Like Stack, asChild is not supported and throws.

Prop Type Description
columns number Fixed column count. When omitted, columns are derived from minColumnWidth and container width.
minColumnWidth SpaceValue Minimum cell width used to compute responsive column count.
cellHeight SpaceValue Height of each cell. Defaults to 32.
gap SpaceValue Spacing for both axes. Defaults to 0.
rowGap SpaceValue Vertical spacing override. Defaults to gap.
columnGap SpaceValue Horizontal spacing override. Defaults to gap.
autoSize StackAutoSize Maps to AutomaticSize; true resolves to the Y axis. Defaults to false.
padding... SpaceValue Same padding fields as Stack, resolved via theme spacing.
sx Sx<StyleProps> Extra host props, merged over the transparent base.
children React.ReactNode Grid cells.

Surface

Decorated surface host primitive. Renders a frame styled with the chosen tone and, for non-overlay tones, adds a uicorner and uistroke for rounded corners and a themed border.

function Surface(props: SurfaceProps): React.Element;
<Surface tone="elevated" Size={UDim2.fromOffset(240, 120)}>
{children}
</Surface>

For decorated tones the host BorderSizePixel is forced to 0 since the border is drawn by uistroke; the overlay tone renders a translucent fill with no decoration. sx and direct host props merge on top. asChild is not supported and throws.

Prop Type Description
tone SurfaceToken "surface" (default), "elevated", "sunken", or "overlay".
sx Sx<StyleProps> Extra host props, merged over the tone.
children React.ReactNode Surface contents.

surface

function surface<Props>(token: SurfaceToken): Sx<Props>;
const elevatedSx = surface("elevated");

Props-only counterpart to the Surface primitive. Returns an Sx value that resolves to background, border color, and border-size host props for the given tone — no child instances (no uicorner/uistroke). Use it when you only want the tone’s host props on an existing element. The overlay tone resolves to a translucent overlay fill with no border.

Types

Prop Type Description
DensityToken "compact" | "comfortable" | "spacious" The three density levels.
DensityContextValue { density; setDensity } Value returned by useDensity.
DensityProviderProps object Props for DensityProvider.
SystemProviderProps object Props for SystemProvider.
SystemThemeContextValue object theme, baseTheme, density, setBaseTheme, setDensity from useSystemTheme.
LayoutDirection "vertical" | "horizontal" Stack fill direction.
StackAlign "start" | "center" | "end" Cross-axis alignment.
StackJustify "start" | "center" | "end" Main-axis alignment.
StackAutoSize boolean | "x" | "y" | "xy" AutomaticSize selector.
StackPadding object The padding/paddingX/paddingTop... field group.
SpaceToken keyof Theme["space"] A key of the theme spacing scale.
SpaceValue SpaceToken | number A space token or a raw pixel value.
StackProps object Props for Stack.
RowProps Omit<StackProps, "direction"> Props for Row.
GridProps object Props for Grid.
SurfaceToken "surface" | "elevated" | "sunken" | "overlay" The four surface tones.
SurfaceProps object Props for the Surface primitive.