Latticehome

Lattice UI

Headless Roblox UI primitives for rbxts/react.

@lattice-ui · v0.8.1 · pre-1.0
Avatar · Switch · Slider · Dialog · Toast — one live scene. Toggle, drag, and send an invite.

Lattice UI provides behavior primitives for Roblox interfaces built with rbxts/react.

Use it for dialogs, popovers, menus, selects, and tabs where focus, layering, state, and dismissal need to stay predictable.

Behavior in, visuals yours.
<Dialog.Root>
<Dialog.Trigger asChild>
<textbutton Text="Invite player" />
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content trapFocus restoreFocus>
{/* your visuals */}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
Headless primitives
Keep rendering and styling in the app while Lattice owns the interaction contract.
Focus and layers
Restore focus, manage stacked overlays, and keep dismissal behavior predictable.
App-owned visuals
Build dialogs, selects, menus, and guided surfaces without moving visual ownership into the primitive layer.

Components

20 primitives, one contract.

Every primitive shares the same composition model: compound parts, controlled or uncontrolled state, and asChild composition.

Form

Checkbox
A checked-state primitive with indeterminate support, controlled or uncontrolled state, and an optional presence-animated indicator.
Radio Group
Single-selection primitive that owns the chosen value, registers items in order, and moves selection across them with gamepad and arrow-key navigation.
Switch
Boolean toggle primitive that owns checked state and animates the thumb between the ends of the track, while your component owns every part of how it looks.
Toggle Group
Selection primitive that coordinates a set of toggle items in single- or multiple-select mode, owning pressed state and motion while you own the item visuals.
Slider
Single-thumb slider primitive that owns clamped, stepped value state and pointer-drag plus keyboard adjustment while you own the track, range, and thumb visuals.
Select
Single-value selection primitive that owns open and value state, registers items in order, and anchors popper-positioned content in a portal while you own the visuals.
Combobox
Single-value selection primitive that owns value state, input filtering, item registration, and popper positioning while you own the visuals.
Text Field
Single-line text input primitive that owns the value, separates live changes from commit, exposes disabled/readOnly/invalid state, and wires label, description, and message parts together.
Textarea
Multi-line text input primitive that owns the value, separates change from commit, auto-resizes to its content within row bounds, and wires label, description, and message parts together.

Guides

Learn the model once.

Focus management
How lattice-ui keeps GuiObject selection predictable across overlays — focus scopes, focus nodes, restore snapshots, and ordered selection.
Gamepad and input
How lattice-ui serves pointer, touch, keyboard, and gamepad players with one input model — ordered selection, engine-driven gamepad navigation, and per-item key handling.
Controlled and uncontrolled state
Understand the controlled/uncontrolled pattern that every stateful Lattice primitive shares, and when to own the state yourself versus letting the primitive own it.
Portals and layers
Render overlays into the right ScreenGui, order them predictably with DisplayOrder, and coordinate outside-press dismissal — without hard-coding layout math.
asChild composition
Merge primitive behavior onto your own host element with asChild and the Slot component, when forwarding props onto the part's own element is not enough.
Presence and motion
How lattice-ui animates GuiObjects — presence reveal/exit, response settling, feedback effects, and the target contracts that keep motion from fighting layout.
Motion recipes
A practical catalog of lattice-ui's ready-made motion configs and how to override the transition prop on any animatable component part.
Theming
How Lattice UI themes work — plain token objects of Color3s and numbers that your components read explicitly through ThemeProvider, useTheme, and useThemeValue.
Styling with recipes
Style Lattice surfaces with the sx value for one-off theming and createRecipe for reusable variant systems, then attach either to headless primitives.
Styling with Vela
Style headless Lattice primitives with Tailwind-shaped class names using vela-rbxts, the compile-time className transform Lattice's asChild was built to accept.
Density and layout
Wire up SystemProvider, scale spacing with density tokens, tone panels with surfaces, and lay out HUDs with Stack, Row, and Grid — all from the same theme scale.
Positioning with Popper
Anchor floating surfaces to a trigger with a shared placement model, collision-aware flipping, and offset props instead of hand-written screen math.
Roblox UI constraints
The Roblox-specific realities — GuiObject selection, BasePlayerGui portals, ScreenGui ordering and inset, default selection limits — that shape every lattice-ui primitive.

Pre-1.0, moving deliberately.

Packages version in lockstep. Most primitives are stable in direction; Select and Slider are feature-limited, and Popper is experimental. Read the stability tiers before depending on an API.

Package stability →