Lattice UI is a set of headless primitives for rbxts/react. Each primitive ships as its own @lattice-ui/react-<name> package, owns the tricky interaction work — open state, focus, layering, motion — and leaves the visuals to you. You install only the packages a screen actually uses.
This page gets one primitive into your project. The rest of getting started uses Dialog as the worked example, so installing @lattice-ui/react-dialog here is a good place to start.
Since 0.6.1 every package is namespaced by framework layer: @lattice-ui/<name> became @lattice-ui/react-<name>, and the old @lattice-ui/core is now @lattice-ui/react-runtime. This is a rename only — no exports or APIs changed. If you are upgrading from 0.6.0 or earlier, add the prefix to every import, and run npx lattice-ui init to rewrite the old names in your package.json — leaving both names listed makes the old and new copies resolve side by side, which npm rejects.
Prerequisites
Lattice UI runs on top of rbxts/react, so your project should already have the React runtime available.
import React from "@rbxts/react";import ReactRoblox from "@rbxts/react-roblox";@rbxts/react and @rbxts/react-roblox are peer dependencies of every primitive (^17.3.7-ts.1). Install them yourself if they are not already in your project — the primitive packages do not bundle them.
Install a package
pnpm add @lattice-ui/react-dialognpm install @lattice-ui/react-dialogyarn add @lattice-ui/react-dialogbun add @lattice-ui/react-dialogInstall one primitive at a time. Each package pulls in the shared foundations it needs — every primitive depends on @lattice-ui/react-runtime, and Dialog additionally brings @lattice-ui/react-focus, @lattice-ui/react-layer, and @lattice-ui/react-motion — so you do not add those by hand.
import { Dialog } from "@lattice-ui/react-dialog";Use the lattice CLI
If you would rather not manage packages by hand, the lattice CLI installs primitives for you, adds the @rbxts/react peers alongside them, and resolves your package manager automatically from the project lockfile. It needs Node 20+ and runs straight from npm — no install required.
npx lattice-ui add dialogNote the argument is the registry name (dialog), not the npm package name — the CLI maps it to @lattice-ui/react-dialog for you. You can add several primitives at once — space- or comma-separated — or pull in a curated preset. overlay bundles popover, tooltip, dialog, and toast, while form bundles checkbox, radio-group, switch, text-field, and textarea. The full command and preset reference lives in the CLI reference.
npx lattice-ui add dialog toast --preset overlayRun add with no names and no --preset and it prompts you to pick presets and components interactively. Add --dry-run to print the exact install command without touching anything.
The CLI also scaffolds and maintains projects: lattice create starts a new rbxts project, lattice init wires the toolchain into an existing one, and lattice remove / lattice upgrade keep your installed primitives in sync. Run lattice doctor if you want it to check your setup.
The manual install works with any package manager. The CLI supports pnpm, npm, and yarn — pass --pm <pnpm|npm|yarn> to any command to override the manager it detects from your lockfile.
Verify it works
Render the minimum useful surface to confirm the import resolves and the primitive mounts:
import React from "@rbxts/react";import { Dialog } from "@lattice-ui/react-dialog";
export function SmokeTest() { return ( <Dialog.Root defaultOpen> <Dialog.Portal> <Dialog.Content> <textlabel BackgroundTransparency={1} Size={UDim2.fromOffset(220, 40)} Text="Lattice UI is installed" /> </Dialog.Content> </Dialog.Portal> </Dialog.Root> );}Next step
Build a real, controlled surface in Your first dialog.