Reference: UI Components¶
The @rbx/ui package provides reusable UI components with theming support for Roblox games.
Installation¶
pnpm add @rbx/ui
Quick Start¶
import { createFrame, createLabel, createButton, setTheme, DarkTheme } from "@rbx/ui";
// Set the theme
setTheme(DarkTheme);
// Create a simple panel
const panel = createFrame({
size: { x: 300, y: 200 },
position: { x: 0.5, y: 0.5 },
anchor: { x: 0.5, y: 0.5 },
backgroundColor: "surface",
cornerRadius: 8,
});
// Add a title
const title = createLabel({
text: "Welcome!",
textColor: "textPrimary",
textSize: 24,
font: "GothamBold",
parent: panel,
});
// Add a button
const button = createButton({
text: "Continue",
size: { x: 120, y: 40 },
onClick: () => print("Clicked!"),
parent: panel,
});
Theme System¶
Built-in Themes¶
import { setTheme, getTheme, DarkTheme, LightTheme } from "@rbx/ui";
// Use dark theme (default)
setTheme(DarkTheme);
// Use light theme
setTheme(LightTheme);
// Get current theme
const theme = getTheme();
Theme Colors¶
// Semantic colors available in themes:
{
background: Color3, // Main background
surface: Color3, // Cards, panels
surfaceAlt: Color3, // Alternate surface
primary: Color3, // Primary actions
primaryHover: Color3, // Primary hover state
secondary: Color3, // Secondary actions
accent: Color3, // Accents, highlights
textPrimary: Color3, // Main text
textSecondary: Color3, // Secondary text
textMuted: Color3, // Muted/disabled text
border: Color3, // Borders
error: Color3, // Error states
warning: Color3, // Warning states
success: Color3, // Success states
info: Color3, // Info states
}
Custom Themes¶
import { setTheme, rgb, hex } from "@rbx/ui";
const CustomTheme = {
background: rgb(15, 15, 25),
surface: rgb(25, 25, 40),
surfaceAlt: rgb(35, 35, 55),
primary: hex("#6366f1"),
primaryHover: hex("#818cf8"),
secondary: rgb(100, 100, 120),
accent: hex("#f59e0b"),
textPrimary: rgb(255, 255, 255),
textSecondary: rgb(180, 180, 200),
textMuted: rgb(120, 120, 140),
border: rgb(60, 60, 80),
error: hex("#ef4444"),
warning: hex("#f59e0b"),
success: hex("#22c55e"),
info: hex("#3b82f6"),
};
setTheme(CustomTheme);
Color Utilities¶
import { rgb, hex, toColor3, darken, lighten } from "@rbx/ui";
// Create colors
const red = rgb(255, 0, 0);
const blue = hex("#3b82f6");
// Convert to Color3
const color3 = toColor3("primary"); // Uses theme
const color3b = toColor3(rgb(100, 150, 200));
// Modify colors
const darker = darken(blue, 0.2); // 20% darker
const lighter = lighten(blue, 0.2); // 20% lighter
Creation Utilities¶
Frames¶
import { createFrame } from "@rbx/ui";
const frame = createFrame({
size: { x: 300, y: 200 }, // Pixels or scale (0-1)
position: { x: 0.5, y: 0.5 }, // Position
anchor: { x: 0.5, y: 0.5 }, // Anchor point
backgroundColor: "surface", // Theme color or Color3
backgroundTransparency: 0, // 0 = opaque, 1 = transparent
cornerRadius: 8, // Corner rounding
borderColor: "border", // Border color
borderWidth: 1, // Border thickness
zIndex: 1, // Layer order
visible: true, // Visibility
parent: screenGui, // Parent instance
name: "MyFrame", // Instance name
});
Labels¶
import { createLabel } from "@rbx/ui";
const label = createLabel({
text: "Hello World",
textColor: "textPrimary",
textSize: 18,
font: "Gotham", // Enum.Font name
textXAlignment: "Center", // Left, Center, Right
textYAlignment: "Center", // Top, Center, Bottom
textWrapped: true,
richText: true, // Enable rich text
size: { x: 200, y: 50 },
position: { x: 0, y: 0 },
backgroundColor: "transparent", // "transparent" for no background
parent: frame,
});
Buttons¶
import { createButton } from "@rbx/ui";
const button = createButton({
text: "Click Me",
size: { x: 120, y: 40 },
position: { x: 0.5, y: 0.8 },
anchor: { x: 0.5, y: 0.5 },
backgroundColor: "primary",
hoverColor: "primaryHover",
textColor: "textPrimary",
textSize: 16,
cornerRadius: 6,
onClick: () => {
print("Button clicked!");
},
parent: frame,
});
Scroll Frames¶
import { createScrollFrame } from "@rbx/ui";
const scrollFrame = createScrollFrame({
size: { x: 300, y: 400 },
canvasSize: { x: 0, y: 800 }, // Scrollable area
scrollDirection: "vertical", // "vertical", "horizontal", "both"
scrollBarThickness: 6,
scrollBarColor: "border",
backgroundColor: "surface",
parent: screenGui,
});
Layout Utilities¶
Corner Radius¶
import { addCorner } from "@rbx/ui";
// Add rounded corners
addCorner(frame, 8); // 8 pixel radius
addCorner(frame, { scale: 0.1 }); // 10% of size
Padding¶
import { addPadding } from "@rbx/ui";
// Uniform padding
addPadding(frame, 16);
// Different padding per side
addPadding(frame, {
top: 20,
bottom: 20,
left: 16,
right: 16,
});
List Layout¶
import { addListLayout } from "@rbx/ui";
// Vertical list
addListLayout(frame, {
direction: "vertical", // "vertical" or "horizontal"
padding: 8, // Gap between items
horizontalAlignment: "Center", // Left, Center, Right
verticalAlignment: "Top", // Top, Center, Bottom
sortOrder: "LayoutOrder", // Name or LayoutOrder
});
Grid Layout¶
import { addGridLayout } from "@rbx/ui";
addGridLayout(frame, {
cellSize: { x: 100, y: 100 },
cellPadding: { x: 8, y: 8 },
fillDirection: "horizontal", // "horizontal" or "vertical"
horizontalAlignment: "Center",
verticalAlignment: "Top",
sortOrder: "LayoutOrder",
});
Stroke¶
import { addStroke } from "@rbx/ui";
addStroke(frame, {
color: "border",
thickness: 2,
transparency: 0,
lineJoinMode: "Round", // Round, Bevel, Miter
});
Size Utilities¶
import { px, scale, centerAnchor, centerPosition } from "@rbx/ui";
// Pixel sizes
const size1 = px(300, 200); // UDim2.fromOffset(300, 200)
// Scale sizes (relative to parent)
const size2 = scale(0.5, 0.5); // UDim2.fromScale(0.5, 0.5)
// Mixed sizes
const size3 = new UDim2(0.5, 10, 0, 100); // 50% + 10px, 100px
// Center helpers
frame.AnchorPoint = centerAnchor(); // Vector2(0.5, 0.5)
frame.Position = centerPosition(); // UDim2(0.5, 0, 0.5, 0)
Components¶
Dialog¶
Modal dialog with title, content, and buttons.
import { createDialog } from "@rbx/ui";
const cleanup = createDialog({
title: "Confirm Action",
message: "Are you sure you want to proceed?",
buttons: [
{
text: "Cancel",
style: "secondary",
onClick: () => cleanup(),
},
{
text: "Confirm",
style: "primary",
onClick: () => {
doAction();
cleanup();
},
},
],
parent: screenGui,
});
Toast¶
Temporary notification message.
import { showToast } from "@rbx/ui";
// Simple toast
showToast({
message: "Settings saved!",
duration: 3, // Seconds
parent: screenGui,
});
// Toast with type
showToast({
message: "Connection lost",
type: "error", // "info", "success", "warning", "error"
duration: 5,
parent: screenGui,
});
ListView¶
Scrollable list of items.
import { createListView } from "@rbx/ui";
const listView = createListView({
items: [
{ id: "1", label: "Item 1" },
{ id: "2", label: "Item 2" },
{ id: "3", label: "Item 3" },
],
renderItem: (item, index) => {
const row = createFrame({ ... });
createLabel({ text: item.label, parent: row });
return row;
},
onItemClick: (item, index) => {
print(`Clicked ${item.label}`);
},
size: { x: 300, y: 400 },
itemHeight: 50,
parent: screenGui,
});
// Update items
listView.setItems(newItems);
ProgressBar¶
Progress indicator.
import { createProgressBar } from "@rbx/ui";
const progressBar = createProgressBar({
progress: 0.5, // 0-1
size: { x: 200, y: 20 },
backgroundColor: "surface",
fillColor: "primary",
cornerRadius: 4,
showLabel: true, // Show percentage text
parent: frame,
});
// Update progress
progressBar.setProgress(0.75);
Spinner¶
Loading indicator.
import { createSpinner } from "@rbx/ui";
const spinner = createSpinner({
size: 32, // Diameter in pixels
color: "primary",
thickness: 3,
parent: frame,
});
// Start/stop animation
spinner.start();
spinner.stop();
// Cleanup
spinner.destroy();
Best Practices¶
1. Use Theme Colors¶
// Good - uses theme colors
createFrame({ backgroundColor: "surface" });
createLabel({ textColor: "textPrimary" });
// Avoid - hardcoded colors (won't adapt to theme changes)
createFrame({ backgroundColor: rgb(30, 30, 30) });
2. Clean Up Resources¶
// Components return cleanup functions
const cleanup = createDialog({ ... });
// Call cleanup when done
cleanup();
// Or use the destroy method on components
progressBar.destroy();
spinner.destroy();
3. Use Layouts Over Manual Positioning¶
// Good - uses layout
const container = createFrame({ ... });
addListLayout(container, { direction: "vertical", padding: 8 });
items.forEach((item, i) => {
createFrame({ layoutOrder: i, parent: container });
});
// Avoid - manual positioning
items.forEach((item, i) => {
createFrame({ position: { x: 0, y: i * 50 }, parent: container });
});
4. Responsive Sizing¶
// Use scale for responsive layouts
createFrame({
size: { x: 0.8, y: 0.6 }, // 80% width, 60% height
position: { x: 0.5, y: 0.5 },
anchor: { x: 0.5, y: 0.5 },
});
// Or mix scale and pixels
createFrame({
size: new UDim2(1, -32, 0, 50), // Full width - 32px margin, 50px tall
});
Integration Example¶
import {
createFrame,
createLabel,
createButton,
createListView,
showToast,
addCorner,
addPadding,
addListLayout,
setTheme,
DarkTheme,
} from "@rbx/ui";
// Set theme
setTheme(DarkTheme);
// Create main menu
function createMainMenu(screenGui: ScreenGui) {
// Background panel
const panel = createFrame({
size: { x: 400, y: 500 },
position: { x: 0.5, y: 0.5 },
anchor: { x: 0.5, y: 0.5 },
backgroundColor: "surface",
parent: screenGui,
});
addCorner(panel, 12);
addPadding(panel, 24);
// Content container
const content = createFrame({
size: { x: 1, y: 1 },
backgroundColor: "transparent",
parent: panel,
});
addListLayout(content, { direction: "vertical", padding: 16 });
// Title
createLabel({
text: "Main Menu",
textColor: "textPrimary",
textSize: 28,
font: "GothamBold",
size: { x: 1, y: 0 },
autoSize: "Y",
layoutOrder: 1,
parent: content,
});
// Menu buttons
const menuItems = ["Play", "Settings", "Shop", "Quit"];
menuItems.forEach((item, i) => {
createButton({
text: item,
size: { x: 1, y: 0 },
autoSize: "Y",
backgroundColor: "primary",
textSize: 18,
cornerRadius: 8,
layoutOrder: i + 2,
onClick: () => handleMenuClick(item),
parent: content,
});
});
return panel;
}
function handleMenuClick(item: string) {
showToast({
message: `Selected: ${item}`,
type: "info",
duration: 2,
});
}