@lattice-ui/tabs Part of the stable direction toward v1.0.
What It Is For
Use Tabs when the screen should switch between sibling panels without leaving the current route or layout.
It is a good fit for profile pages, settings surfaces, and inspector UIs where the current section should stay explicit.
import { Tabs } from "@lattice-ui/tabs";
import React from "@rbxts/react";
export function TabsExample() {
const [value, setValue] = React.useState("overview");
return (
<frame BackgroundTransparency={1} Size={UDim2.fromOffset(520, 240)}>
<Tabs.Root onValueChange={setValue} value={value}>
<Tabs.List asChild>
<frame BackgroundTransparency={1} Size={UDim2.fromOffset(360, 40)}>
<uilistlayout
FillDirection={Enum.FillDirection.Horizontal}
Padding={new UDim(0, 8)}
/>
{(["overview", "activity", "settings"] as const).map((tab) => (
<Tabs.Trigger asChild key={tab} value={tab}>
<textbutton
AutoButtonColor={false}
BackgroundColor3={
value === tab
? Color3.fromRGB(53, 104, 196)
: Color3.fromRGB(34, 41, 54)
}
BorderSizePixel={0}
Size={UDim2.fromOffset(112, 36)}
Text={tab}
TextColor3={Color3.fromRGB(236, 240, 248)}
TextSize={14}
>
<uicorner CornerRadius={new UDim(0, 8)} />
</textbutton>
</Tabs.Trigger>
))}
</frame>
</Tabs.List>
{(["overview", "activity", "settings"] as const).map((tab) => (
<Tabs.Content
asChild
forceMount={tab === "overview"}
key={tab}
value={tab}
>
<frame
BackgroundColor3={Color3.fromRGB(34, 41, 54)}
BorderSizePixel={0}
Position={UDim2.fromOffset(0, 56)}
Size={UDim2.fromOffset(360, 110)}
>
<uicorner CornerRadius={new UDim(0, 10)} />
<textlabel
BackgroundTransparency={1}
Position={UDim2.fromOffset(14, 14)}
Size={UDim2.fromOffset(320, 32)}
Text={`${tab} content`}
TextColor3={Color3.fromRGB(236, 240, 248)}
TextSize={14}
TextXAlignment={Enum.TextXAlignment.Left}
/>
</frame>
</Tabs.Content>
))}
</Tabs.Root>
</frame>
);
} Live demo is experimental and may contain bugs.
Install
Global CLI command: lattice add tabs
Monorepo local script
Use your package manager wrapper when running the local lattice command.
pnpm lattice add tabsPublic Exports
-
Tabs -
Tabs.Root -
Tabs.List -
Tabs.Trigger -
Tabs.Content
State Model
Tabs.Rootmanages a single selectedvaluewith controlled or uncontrolled ownership.- Triggers register with orientation-aware ordering so selection movement can advance through enabled items.
Tabs.Contentcan stay mounted withforceMounteven when its tab is not the active value.
Key API
Tabs.Root
Use value, defaultValue, onValueChange, and orientation to define the navigation model.
Tabs.Trigger
Each trigger needs a stable value; disabled removes it from activation and directional movement.
Tabs.Content
Use forceMount when inactive content still needs measurement, retained state, or custom animation handling.
Composition Patterns
Screen subsections
Use tabs when the user needs to move between a few related panels while keeping the container layout constant.
Inspector sidebars
Use orientation="vertical" when the trigger list should behave more like a navigation rail than a top bar.
Cautions / Limits
- Current behavior activates tabs immediately when selection moves; there is no separate manual activation mode.
- Tabs solve disclosure and selection, not overlaying or lazy positioning; reach for
AccordionorDialogwhen the UI contract is different.