@lattice-ui/text-field Part of the stable direction toward v1.0.
What It Is For
Use TextField for single-line text entry with label, description, validation message, and commit hooks that stay in one compound tree.
It is the right default when you want field semantics without adopting a pre-skinned input component.
import { TextField } from "@lattice-ui/text-field";
import React from "@rbxts/react";
export function TextFieldExample() {
const [value, setValue] = React.useState("player-one");
const invalid = value.size() < 3;
return (
<frame BackgroundTransparency={1} Size={UDim2.fromOffset(460, 220)}>
<TextField.Root invalid={invalid} onValueChange={setValue} value={value}>
<frame BackgroundTransparency={1} Size={UDim2.fromOffset(420, 180)}>
<uilistlayout
FillDirection={Enum.FillDirection.Vertical}
Padding={new UDim(0, 6)}
/>
<TextField.Label asChild>
<textbutton
AutoButtonColor={false}
BackgroundTransparency={1}
BorderSizePixel={0}
Size={UDim2.fromOffset(420, 22)}
Text="Display name"
TextColor3={Color3.fromRGB(236, 240, 248)}
TextSize={14}
TextXAlignment={Enum.TextXAlignment.Left}
/>
</TextField.Label>
<TextField.Input asChild>
<textbox
BackgroundColor3={Color3.fromRGB(34, 41, 54)}
BorderSizePixel={0}
Size={UDim2.fromOffset(420, 38)}
TextColor3={Color3.fromRGB(236, 240, 248)}
TextSize={14}
TextXAlignment={Enum.TextXAlignment.Left}
>
<uicorner CornerRadius={new UDim(0, 8)} />
<uipadding
PaddingLeft={new UDim(0, 10)}
PaddingRight={new UDim(0, 10)}
/>
</textbox>
</TextField.Input>
<TextField.Description asChild>
<textlabel
BackgroundTransparency={1}
Size={UDim2.fromOffset(420, 18)}
Text="Use onValueCommit when saves should happen on commit rather than every keystroke."
TextColor3={Color3.fromRGB(172, 181, 196)}
TextSize={13}
TextXAlignment={Enum.TextXAlignment.Left}
/>
</TextField.Description>
<TextField.Message asChild>
<textlabel
BackgroundTransparency={1}
Size={UDim2.fromOffset(420, 18)}
Text={
invalid ? "Must be at least 3 characters." : "Ready to save."
}
TextColor3={
invalid
? Color3.fromRGB(210, 102, 102)
: Color3.fromRGB(172, 181, 196)
}
TextSize={13}
TextXAlignment={Enum.TextXAlignment.Left}
/>
</TextField.Message>
</frame>
</TextField.Root>
</frame>
);
} Live demo is experimental and may contain bugs.
Install
Global CLI command: lattice add text-field
Monorepo local script
Use your package manager wrapper when running the local lattice command.
pnpm lattice add text-fieldPublic Exports
-
TextField -
TextField.Root -
TextField.Input -
TextField.Label -
TextField.Description -
TextField.Message
State Model
TextField.Rootmanages the current string value plusdisabled,readOnly,required, andinvalidflags.- The package supports controlled and uncontrolled value ownership through
valueordefaultValue. onValueChangefires on text edits, whileonValueCommitfires on commit moments such as focus loss or enter-like confirmation.
Key API
TextField.Root
Use value, defaultValue, onValueChange, onValueCommit, disabled, readOnly, required, and invalid to connect the field to app state.
TextField.Input
Use asChild when the host should be your own TextBox; root-level disabled and read-only rules still flow through.
TextField.Label / Description / Message
Use the companion parts to keep accessibility and field messaging close to the same shared state source.
Composition Patterns
Labeled validated fields
Keep label, input, helper text, and validation message inside one TextField.Root so invalid and read-only state stay coordinated.
Commit-aware settings
Use onValueCommit when the app should treat typing and committed saves differently.
Cautions / Limits
- Commit callbacks are separate from live change callbacks; do not expect
onValueCommitto fire on every keystroke. - Use
Textareainstead when multi-line input or automatic height growth is part of the field contract.