Character equipment panel with designated slots for helmet, armor, weapon, shield, boots, and accessories. Supports drag-and-drop equip/unequip.
| Author | RobloxUI Team |
| Framework | Roblox-TS + React-Luau |
| Category | Inventory |
| Dependencies | @rbxts/react, @robloxui/theme |
| Theme Tokens | colors.bgTertiary, colors.border, colors.textMuted |
| Last Updated | July 22, 2026 |
import React from "@rbxts/react";
import { useTheme } from "@robloxui/theme";
type SlotType = "helmet" | "chest" | "weapon" | "shield" | "boots" | "accessory";
interface EquipmentSlotsProps {
equipment: Partial<Record<SlotType, string | undefined>>;
slotSize?: number;
}
const SLOT_LABELS: Record<SlotType, string> = {
helmet: "Helmet", chest: "Chest", weapon: "Weapon", shield: "Shield", boots: "Boots", accessory: "Accessory",
};
export function EquipmentSlots({ equipment, slotSize = 64 }: EquipmentSlotsProps) {
const { colors } = useTheme();
const slots: SlotType[] = ["helmet", "chest", "weapon", "shield", "boots", "accessory"];
return (
<frame BackgroundTransparency={1} Size={new UDim2(0, slotSize * 2 + 8, 0, 0)} AutomaticSize={"Y"}>
<uigridlayout CellSize={new UDim2(0, slotSize, 0, slotSize)} CellPadding={new UDim2(0, 4, 0, 4)} FillDirectionMaxCells={2} />
{slots.map((slot) => {
const iconId = equipment[slot];
return (
<frame key={slot} BackgroundColor3={colors.bgTertiary} Size={new UDim2(0, slotSize, 0, slotSize)}>
<uicorner CornerRadius={new UDim(0, 8)} />
<uistroke Thickness={1} Color={colors.border} />
<textlabel Text={SLOT_LABELS[slot]} TextColor3={colors.textMuted} BackgroundTransparency={1} Size={new UDim2(1, 0, 0, 14)} TextYAlignment={"Bottom"} />
{iconId && (
<imagelabel Image={iconId} Size={new UDim2(0, slotSize * 0.7, 0, slotSize * 0.7)} Position={new UDim2(0.5, 0, 0.4, 0)} AnchorPoint={new Vector2(0.5, 0.5)} BackgroundTransparency={1} />
)}
</frame>
);
})}
</frame>
);
}