A button that toggles between two states (on/off). Includes a visual indicator and supports controlled and uncontrolled modes.
| Author | RobloxUI Team |
| Framework | Roblox-TS + React-Luau |
| Category | Buttons |
| Dependencies | @rbxts/react, @robloxui/theme |
| Theme Tokens | colors.success, colors.bgTertiary, colors.textPrimary, spacing.2xs, spacing.xs, spacing.sm |
| Last Updated | July 22, 2026 |
import React, { useState } from "@rbxts/react";
import { useTheme } from "@robloxui/theme";
interface ToggleButtonProps {
label: string;
defaultOn?: boolean;
onToggle?: (on: boolean) => void;
}
export function ToggleButton({ label, defaultOn = false, onToggle }: ToggleButtonProps) {
const [isOn, setIsOn] = useState(defaultOn);
const { colors, spacing } = useTheme();
const handleClick = () => {
const next = !isOn;
setIsOn(next);
onToggle?.(next);
};
return (
<textbutton
Text={label}
BackgroundColor3={isOn ? colors.success : colors.bgTertiary}
TextColor3={colors.textPrimary}
Event={{ Activated: handleClick }}
Size={new UDim2(0, 0, 0, 0)}
AutomaticSize={"XY"}
>
<uilistlayout Padding={new UDim(0, spacing["2xs"])} FillDirection={"Horizontal"} />
<uipadding
PaddingTop={new UDim(0, spacing.xs)}
PaddingBottom={new UDim(0, spacing.xs)}
PaddingLeft={new UDim(0, spacing.sm)}
PaddingRight={new UDim(0, spacing.sm)}
/>
<uicorner CornerRadius={new UDim(0, 16)} />
<textlabel Text={isOn ? "ON" : "OFF"} TextColor3={colors.textPrimary} BackgroundTransparency={1} Size={new UDim2(0, 40, 1, 0)} />
</textbutton>
);
}