Skip to content

Button

Versatile action element supporting links, loading states, and icon-only mode.

<Button label="Button" variant="primary" />
<Button label="Button" variant="secondary" />
<Button label="Button" variant="ghost" />
<Button label="Button" variant="destructive" />
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button label="Small" size="sm" />
<Button label="Medium" size="md" />
<Button label="Large" size="lg" />
</div>
function SizeAlignmentStory() {
const [value, setValue] = useState('day');
const [name, setName] = useState('');
return (
<div style={{display: 'grid', gap: '1.5rem'}}>
{(['sm', 'md', 'lg'] as const).map(size => (
<div
key={size}
style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button label={size} size={size} variant="primary" />
<TextInput
isLabelHidden
label={`Name (${size})`}
onChange={setName}
placeholder="Name"
size={size}
value={name}
/>
<SegmentedControl
label={`View (${size})`}
onChange={setValue}
size={size}
value={value}>
<SegmentedControlItem label="Day" value="day" />
<SegmentedControlItem label="Week" value="week" />
</SegmentedControl>
</div>
))}
</div>
);
}
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button icon={Plus} label="Add" />
<Button
endContent={<Icon icon={Inbox} />}
label="Inbox"
variant="secondary"
/>
<Button icon={Settings} isIconOnly label="Settings" />
</div>
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button icon={Plus} label="Small" size="sm" />
<Button icon={Plus} label="Medium" size="md" />
<Button icon={Plus} label="Large" size="lg" />
</div>
<Button
label="Disabled"
isDisabled
tooltip="This action is currently unavailable."
/>
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button isLoading label="Small" size="sm" variant="primary" />
<Button isLoading label="Medium" size="md" variant="primary" />
<Button isLoading label="Large" size="lg" variant="primary" />
</div>
<Button
endContent={<Icon icon={Inbox} />}
isLoading
label="Sync inbox"
variant="primary"
/>
<Button label="Open docs" href="/docs" variant="primary" />
<Button label="Hover me" tooltip="Helpful context for this action." />
<Button
label="Unavailable"
isDisabled
tooltip="This action is not available for your current role."
/>
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button
label="Status"
startContent={
<span
className={css({
w: '2',
h: '2',
borderRadius: 'full',
bg: 'green',
})}
/>
}
/>
<Button
label="Inbox"
startContent={<Icon icon={Inbox} />}
variant="primary"
/>
<Button
endContent={<Icon icon={Settings} />}
label="Configure"
startContent={
<span
className={css({
w: '2',
h: '2',
borderRadius: 'full',
bg: 'orange',
})}
/>
}
variant="secondary"
/>
</div>
<div
className={css({bg: 'primary', borderRadius: 'lg', p: '4'})}
style={{
display: 'flex',
gap: '0.5rem',
alignItems: 'center',
color: 'white',
}}>
<Button icon={Settings} isIconOnly label="Settings" variant="onSolid" />
<Button label="Action" variant="onSolid" />
<Button icon={Plus} label="Add item" variant="onSolid" />
</div>
<div style={{display: 'flex', gap: '1rem', alignItems: 'center'}}>
<Button icon={RefreshCw} isIconOnly isLoading label="Refresh" size="sm" />
<Button
icon={RefreshCw}
isIconOnly
isLoading
label="Refresh"
size="md"
variant="primary"
/>
<Button
icon={RefreshCw}
isIconOnly
isLoading
label="Refresh"
size="lg"
variant="ghost"
/>
</div>

When isIconOnly: true

PropTypeDefaultDescription
aria-controlsstringIdentifies the element(s) whose contents are controlled by the button.
aria-current'page' | 'step' | 'location' | 'date' | 'time'Indicates the current item in a set.
aria-describedbystringIdentifies the element(s) that describe the button.
aria-detailsstringIdentifies the element that provides a detailed description.
aria-expandedbooleanIndicates whether a controlled element is expanded or collapsed.
aria-haspopupboolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog'Indicates the button opens an interactive popup element.
aria-hiddenbooleanIndicates whether the element is exposed to the accessibility API.
aria-keyshortcutsstringKeyboard shortcuts that activate or focus the button.
aria-labelstringAccessible label that overrides the visible label for assistive technologies. Use when the visible text is too terse (e.g. a page number) and a longer description is needed.
aria-labelledbystringIdentifies the element(s) that label the button.
aria-ownsstringIdentifies element(s) owned by the button that are not DOM children.
aria-pressedboolean | 'mixed'Indicates the current pressed state of a toggle button.
aria-roledescriptionstringHuman-readable description of the role of the button.
asLinkComponentCustom link component to render when href is set. Falls back to the component provided by LinkProvider, or a plain <a> tag.
classNamestringAdditional CSS class names applied to the root element.
data-testidstringTest ID applied to the root element.
endContentReactNodeContent rendered after the label, such as a badge or count. Hidden in icon-only mode.
formstringHTML form attribute associating the button with a <form> by ID.
hrefstringURL to navigate to. When set and the button is not isDisabled, the component renders as a link element.
isDisabledbooleanWhether the button is disabled. Prevents interaction and applies disabled styling.
isLoadingbooleanWhether the button is in a loading state. Shows a spinner overlay, disables interaction, and announces "Loading" to assistive technologies.
label*stringText label for the button. Always required for accessibility even when isIconOnly is true.
namestringHTML name attribute for form submission.
onClickMouseEventHandler<HTMLElement>Click event handler.
onKeyDown(event: KeyboardEvent<HTMLElement>) => voidKeyboard event handler for the root element.
refRef<HTMLElement>Ref forwarded to the root element.
relstringLink rel attribute (e.g., "noopener"). Only applies when rendering as a link.
size"sm" | "md" | "lg"Visual size of the button.
startContentReactNodeArbitrary content rendered before the label (after the icon, if present). Hidden in icon-only mode.
styleCSSPropertiesInline styles applied to the root element.
targetstringLink target attribute (e.g., "_blank"). Only applies when rendering as a link.
tooltipstringTooltip text shown on hover. Defaults to label when isIconOnly is true (since the label is otherwise not visible); pass an explicit value to override, or undefined to keep the default. When set on a disabled button, aria-disabled is used instead of the disabled attribute so the tooltip remains accessible.
type'button' | 'submit' | 'reset'HTML button type attribute.
valuestringHTML value attribute for form submission.
variant"destructive" | "primary" | "ghost" | "onSolid" | "secondary"Visual style variant.
icon*IconComponentIcon element rendered before the label. Required in icon-only mode.
isIconOnly*trueVisually hides the label, showing only the icon. The label prop is still required and used as aria-label.

When isIconOnly: false

PropTypeDefaultDescription
aria-controlsstringIdentifies the element(s) whose contents are controlled by the button.
aria-current'page' | 'step' | 'location' | 'date' | 'time'Indicates the current item in a set.
aria-describedbystringIdentifies the element(s) that describe the button.
aria-detailsstringIdentifies the element that provides a detailed description.
aria-expandedbooleanIndicates whether a controlled element is expanded or collapsed.
aria-haspopupboolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog'Indicates the button opens an interactive popup element.
aria-hiddenbooleanIndicates whether the element is exposed to the accessibility API.
aria-keyshortcutsstringKeyboard shortcuts that activate or focus the button.
aria-labelstringAccessible label that overrides the visible label for assistive technologies. Use when the visible text is too terse (e.g. a page number) and a longer description is needed.
aria-labelledbystringIdentifies the element(s) that label the button.
aria-ownsstringIdentifies element(s) owned by the button that are not DOM children.
aria-pressedboolean | 'mixed'Indicates the current pressed state of a toggle button.
aria-roledescriptionstringHuman-readable description of the role of the button.
asLinkComponentCustom link component to render when href is set. Falls back to the component provided by LinkProvider, or a plain <a> tag.
classNamestringAdditional CSS class names applied to the root element.
data-testidstringTest ID applied to the root element.
endContentReactNodeContent rendered after the label, such as a badge or count. Hidden in icon-only mode.
formstringHTML form attribute associating the button with a <form> by ID.
hrefstringURL to navigate to. When set and the button is not isDisabled, the component renders as a link element.
isDisabledbooleanWhether the button is disabled. Prevents interaction and applies disabled styling.
isLoadingbooleanWhether the button is in a loading state. Shows a spinner overlay, disables interaction, and announces "Loading" to assistive technologies.
label*stringText label for the button. Always required for accessibility even when isIconOnly is true.
namestringHTML name attribute for form submission.
onClickMouseEventHandler<HTMLElement>Click event handler.
onKeyDown(event: KeyboardEvent<HTMLElement>) => voidKeyboard event handler for the root element.
refRef<HTMLElement>Ref forwarded to the root element.
relstringLink rel attribute (e.g., "noopener"). Only applies when rendering as a link.
size"sm" | "md" | "lg"Visual size of the button.
startContentReactNodeArbitrary content rendered before the label (after the icon, if present). Hidden in icon-only mode.
styleCSSPropertiesInline styles applied to the root element.
targetstringLink target attribute (e.g., "_blank"). Only applies when rendering as a link.
tooltipstringTooltip text shown on hover. Defaults to label when isIconOnly is true (since the label is otherwise not visible); pass an explicit value to override, or undefined to keep the default. When set on a disabled button, aria-disabled is used instead of the disabled attribute so the tooltip remains accessible.
type'button' | 'submit' | 'reset'HTML button type attribute.
valuestringHTML value attribute for form submission.
variant"destructive" | "primary" | "ghost" | "onSolid" | "secondary"Visual style variant.
iconIconComponentIcon element rendered before the label.
isIconOnlyfalseVisually hides the label, showing only the icon. The label prop is still required and used as aria-label.