Skip to content

Button

Button separates an action’s semantic type from its visual hierarchy. The same API renders with Brutal or Elegant material without changing behavior. ButtonGroup joins related actions and can provide a shared size without changing each button’s semantic type.

Demos

Each behavior lives in its own TSX demo and rendered preview. Open a section’s source without wading through an unrelated all-in-one workbench.

Type and hierarchy

Compare all eight semantic types across the solid, secondary, tertiary, and quaternary hierarchy levels.

Size and shape

Tiny, small, medium, and large use the exact 22 / 28 / 34 / 40px height contract. Round and circle are independent shape controls.

Appearance

Ghost, dashed, text, borderless, strong, and block treatments share the same semantic type API. When independent hierarchy flags overlap, a fixed precedence decides which one applies.

Icon

Use a React node, a render callback, either placement, or an icon-only circle.

Send action

type="accent" is the action color, rUI’s pink, for the one action a surface exists for, such as sending a message. Press Enter in the composer to send.

Loading and disabled

Loading composes Raft UI’s Spinner, preserves the label and focus, and blocks mouse and keyboard activation without setting the native disabled attribute. The counter makes that input gate directly observable.

Custom color

Override the semantic fill and text colors for one-off product needs.

Tag, focus, and keyboard

Render native anchors or custom controls, control tab participation and keyboard activation, bridge Safari click focus, and keep native form types explicit.

ButtonGroup

Groups join adjacent actions, provide a shared size, and support horizontal or vertical layout without taking ownership of semantic type.

Props

Button

NameTypeDefaultDescriptionVersion
typedefault | tertiary | primary | accent | info | success | warning | errordefaultSets semantic intent and the matching color family. tertiary here is the neutral semantic type, not the hierarchy prop.Unreleased
secondarybooleanfalseUses the semantic family’s soft surface.Unreleased
tertiarybooleanfalseUses a quiet neutral surface with semantic text.Unreleased
quaternarybooleanfalseRemoves the resting container while retaining hover and focus feedback.Unreleased
ghostbooleanfalseUses a transparent surface with a semantic border.Unreleased
dashedbooleanfalseUses the ghost treatment with a dashed border.Unreleased
textbooleanfalseRemoves the control box and keeps only the label.Unreleased
borderedbooleantrueControls whether the current appearance renders its border. A borderless button is flat, with no shadow.Unreleased
colorstringundefinedOverrides the semantic color and derives hover, pressed, soft, and wave colors. A light hex or rgb() color gets dark text on its solid fill, so the label keeps AA contrast.Unreleased
textColorstringundefinedOverrides the text and icon color for every state.Unreleased
sizetiny | small | medium | largemediumSets height, padding, type size, icon size, and radius. Heights are 22 / 28 / 34 / 40px.Unreleased
loadingbooleanfalseKeeps the control focusable and its label visible, swaps the icon position to a spinner, marks the control busy, and blocks mouse and keyboard activation.Unreleased
loadingLabelstringLocale’s “Loading”The spinner’s accessible label. Defaults to the string from the current ConfigProvider locale.Unreleased
spinPropsOmit<SpinnerProps, "aria-label" | "role">undefinedForwards Raft UI Spinner options such as size, variant, and native span props while Button retains ownership of the accessible loading status and label.Unreleased
disabledbooleanfalseDisables focus and activation. Alternate tags use equivalent ARIA and event behavior.Unreleased
focusablebooleantrueControls whether the control participates in focus navigation.Unreleased
keyboardbooleantrueControls Enter and Space activation while leaving pointer activation available.Unreleased
nativeFocusBehaviorbooleanBrowser-dependentUses native click focus when available and otherwise applies Safari-compatible focus without scrolling.Unreleased
tagReact.ElementTypebuttonRenders another element such as an anchor while preserving matching native props and refs.Unreleased
blockbooleanfalseMakes the button fill the available inline width.Unreleased
iconReactNodeundefinedRenders a decorative icon. Add aria-label to an icon-only button.Unreleased
renderIcon() => ReactNodeundefinedRender callback. When both are supplied, it takes priority over icon; loading owns the icon slot without executing it.Unreleased
iconPlacementleft | rightleftPlaces the icon before or after the label.Unreleased
roundbooleanfalseUses a pill shape.Unreleased
circlebooleanfalseUses a square footprint with a circular shape, intended for icon-only actions.Unreleased
strongbooleanfalseSelects the theme’s strong weight: Brutal 700 and Elegant 500, from defaults of 500 and 400.Unreleased
attrTypebutton | submit | resetbuttonSets the native button type attribute.Unreleased

secondary, tertiary, quaternary, ghost, dashed, and text are independent booleans. If flags overlap, resolution follows this order: text → dashed → ghost → secondary → tertiary → quaternary → solid. Native attributes, events, and refs are inferred from tag; native form behavior uses attrType. All exported Button and ButtonGroup contracts live in the component’s public-types.ts. Loading composes the public Raft UI Spinner: Brutal uses the hard border ring and Elegant uses the two-circle SVG arc, while Button keeps the label in place and blocks activation. The click wave is an Elegant-family material behavior and is deliberately absent from Brutal; the quiet secondary, tertiary, and quaternary treatments keep their ripple transparent.

ButtonGroup

NameTypeDefaultDescriptionVersion
sizetiny | small | medium | largeundefinedProvides a shared size that overrides child button sizes.Unreleased
verticalbooleanfalseStacks buttons vertically instead of horizontally.Unreleased

ButtonGroup supports native div attributes and refs. Give each group an accessible name with aria-label or aria-labelledby.