React Clean UI
Form

Button

A clickable button with icons, intents, scaling, and grouped children.

Button is a themed, clickable surface built on Roblox's native ImageButton. It automatically applies the current Clean UI theme, including background, border, corner radius, and hover styling based on intent.

Import

import { Button } from "@rbxts/react-clean-ui";

Basic usage

Loom Preview

The text prop renders a label, and icon renders a leading icon. Either can be used on its own.

<Button text="Save" />
<Button icon="save" />

Responding to clicks

Button renders an ImageButton, so click handling is done through the native Event prop.

<Button
    text="Submit"
    intent="primary"
    Event={{
        Activated: () => {
            print("Submitted");
        },
    }}
/>

Intents

Set intent to control the button's background, border, and text/icon colors.

<Button text="Primary" intent="primary" />
<Button text="Secondary" intent="secondary" />
<Button text="Success" intent="success" />
<Button text="Info" intent="info" />
<Button text="Warning" intent="warning" />
<Button text="Danger" intent="danger" />

Hovering a button switches its colors to the intent's hover state.

secondary is a lower-emphasis alternative to primary, such as a neutral grey button in the default theme. Every shipped theme styles it. A custom theme that doesn't define secondary still works: the button falls back to the primary colors.

Custom content

For layouts beyond an icon and a label, pass children instead of icon/text. Button.Icon and Button.Text are exposed so custom content can still pick up the button's intent and scale.

<Button intent="info">
    <HStack valign="Center" spacing="sm">
        <Button.Icon icon="download" intent="info" />
        <Button.Text text="Download report" intent="info" />
    </HStack>
</Button>

When both icon/text and children are provided, the automatic icon/label row renders first, followed by children.

Scaling

Button supports the shared scale prop, which resolves the button's typography and icon size from the active theme.

<Button text="Small" scale="sm" />
<Button text="Large" scale="lg" />

Available scales are xs, sm, md, lg, and xl.

Spacing

The shared spacing prop controls the gap between the icon and text, as well as the button's internal padding.

<Button icon="star" text="Spacious" spacing="lg" />

Padding

Set padding to override the button's internal padding with a CSS-like value. Like CSS, it accepts one value for all sides, two values (vertical, horizontal), three values (top, horizontal, bottom), or four values (top, right, bottom, left), with or without px. A single number is also accepted.

<Button text="Even" padding={8} />
<Button text="Wide" padding="4 12" />
<Button text="Custom" padding="4px 12px 4px 12px" />

padding overrides the padding derived from spacing side by side, including when spacing="None". The gap between the icon and text still follows spacing.

Disabled state

Set disabled to prevent interaction. The button switches to the intent's disabled colors (when defined in the theme) and ignores hover and click events.

<Button text="Disabled" intent="primary" disabled />

Grouped buttons

Set group on a Button and wrap the group in a Group to make every grouped button match the width of the widest one. This keeps a stack of buttons with icons or labels of differing lengths visually aligned.

import { Button, Group, VStack } from "@rbxts/react-clean-ui";

<Group>
    <VStack>
        <Button group text="Save" intent="primary" />
        <Button group text="Save and continue" intent="primary" />
        <Button group icon="times" text="Cancel" />
    </VStack>
</Group>

Props

Button-specific props

PropTypeDefaultDescription
textstringundefinedRenders a label using the button's typography and intent color.
iconIconNameundefinedRenders a leading icon using the button's intent color.
fontWeightEnum.FontWeightundefinedOverrides the font weight used by the label.
childrenReact.ReactNodeundefinedCustom content rendered after the automatic icon/label row.
groupbooleanfalseMatches this button's width to the widest button in its Group.
disabledbooleanfalseDisables hover/click interaction and switches to disabled colors.
LayoutOrdernumberundefinedNative Roblox layout order.
paddingCssPaddingundefinedOverrides the spacing-derived internal padding, per side (for example 8, "4 12", or "4px 12px 4px 12px").
styleOverrideButtonStyleOverrideundefinedOverrides theme values (colors, corners, border, etc.) for this instance only.
EventReact.InstanceEvent<ImageButton>undefinedNative Roblox event handlers, including Activated.

Shared props

The button also supports props inherited from the following interfaces.

InterfacePurpose
IntentElementPropsConfigures the button's base intent.
IconElementPropsConfigures the icon prop's accepted values.
BackgroundElementPropsConfigures background colour and transparency.
SpacedElementPropsConfigures theme-based internal spacing.
ScalableElementPropsConfigures the label and icon scale.
ShadowElementPropsConfigures a box shadow.
ZIndexElementPropsConfigures the button's ZIndex.

Behaviour

  • The button automatically grows to fit its content (AutomaticSize.XY).
  • Hovering the button switches its background, border, and text/icon colours to the intent's hover state.
  • Setting disabled sets Active={false}, ignores hover and Activated events, and switches colours to the intent's disabled state (when defined in the theme).
  • When group is set and a Group ancestor is present, the button's width is fixed to the widest button reporting into that Group; its height still grows automatically.
  • Without text, icon, or children, the button renders with no content.
  • Internal padding comes from spacing (against theme.spacing, with "None" meaning 0). When padding is set, its parsed per-side values replace the spacing-derived ones. The resolved padding is also reported to Group, so a grouped button's width includes it.
  • Background transparency resolves as BackgroundTransparency prop, then styleOverride.backgroundTransparency, then the current intent's own backgroundTransparency (non-primary intents only), then theme.components.button.backgroundTransparency.
  • Border thickness resolves as the intent state's borderThickness, then styleOverride.borderThickness, then theme.components.button.borderThickness.

Theme values

The button uses values from theme.components.button for:

  • Corner radius
  • Border thickness
  • Background transparency
  • Typography
  • Box shadow
  • Per-intent background, border, and text/icon colours for the default, hover, and disabled states, plus optional backgroundImage and backgroundGradient

Each intent state in theme.components.button.intents can also set:

  • borderThickness — overrides the button's border thickness for that intent and state.
  • backgroundTransparency — for any intent other than primary, overrides theme.components.button.backgroundTransparency. It is read from that intent's current state, then that intent's default entry, and is never inherited from primary. For primary, the component-level backgroundTransparency always applies.

These values can be changed by providing a custom Clean UI theme.

GitHub Repository

On this page