IconButton is a compact button that displays only an icon. Use it for actions where the icon alone clearly communicates the purpose.
Basics
The only required props are name (which determines the icon) and accessibilityLabel (for screen readers).
<HStack gap={2} flexWrap="wrap">
<IconButton name="gear" accessibilityLabel="Open settings" onClick={console.log} />
<IconButton name="close" accessibilityLabel="Close modal" onClick={console.log} />
<IconButton name="refresh" accessibilityLabel="Refresh data" onClick={console.log} />
</HStack>
Variants
Use variants to denote intent and importance. The active prop fills the icon when enabled.
<HStack gap={2} flexWrap="wrap">
<IconButton
active
name="orderHistory"
accessibilityLabel="View transaction history"
variant="primary"
onClick={console.log}
/>
<IconButton
active
name="gear"
accessibilityLabel="View settings"
variant="secondary"
onClick={console.log}
/>
<IconButton
name="phone"
accessibilityLabel="Call support"
variant="tertiary"
onClick={console.log}
/>
<IconButton
name="checkmark"
accessibilityLabel="Approve transaction"
variant="foregroundMuted"
onClick={console.log}
/>
</HStack>
Transparent
Use the transparent prop to remove the background until the user interacts with the button.
<HStack gap={2} flexWrap="wrap">
<IconButton
active
name="orderHistory"
accessibilityLabel="View past order history"
variant="primary"
transparent
onClick={console.log}
/>
<IconButton
active
name="gear"
accessibilityLabel="Update settings"
variant="secondary"
transparent
onClick={console.log}
/>
<IconButton
name="phone"
accessibilityLabel="Call support"
variant="tertiary"
transparent
onClick={console.log}
/>
<IconButton
name="checkmark"
accessibilityLabel="Verify your identity"
variant="foregroundMuted"
transparent
onClick={console.log}
/>
</HStack>
States
Loading
Use the loading prop to show a spinner when an action is in progress. The button becomes non-interactive and displays a loading spinner instead of the icon.
function LoadingExample() {
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = () => {
setIsLoading(true);
setTimeout(() => setIsLoading(false), 2000);
};
return (
<HStack gap={2} flexWrap="wrap">
<IconButton
name="checkmark"
accessibilityLabel={isLoading ? 'Processing submission' : 'Submit form'}
variant="primary"
loading={isLoading}
onClick={handleSubmit}
/>
<IconButton
name="refresh"
accessibilityLabel={isLoading ? 'Refreshing data' : 'Refresh data'}
variant="secondary"
loading={isLoading}
onClick={handleSubmit}
/>
</HStack>
);
}
Disabled
Use the disabled prop to prevent interaction and show a disabled visual state.
<HStack gap={2} flexWrap="wrap">
<IconButton
active
name="orderHistory"
accessibilityLabel="View transaction history"
variant="primary"
disabled
onClick={console.log}
/>
<IconButton
active
name="gear"
accessibilityLabel="View settings"
variant="secondary"
disabled
onClick={console.log}
/>
<IconButton
name="checkmark"
accessibilityLabel="Approve transaction"
variant="foregroundMuted"
disabled
onClick={console.log}
/>
</HStack>
Sizing
IconButtons are compact by default. Use compact={false} for larger touch targets.
<HStack gap={2} flexWrap="wrap" alignItems="center">
<IconButton
active
name="gear"
accessibilityLabel="Settings - compact"
variant="primary"
compact
onClick={console.log}
/>
<IconButton
active
name="gear"
accessibilityLabel="Settings - regular"
variant="primary"
compact={false}
onClick={console.log}
/>
</HStack>
Accessibility
Since icon buttons have no visible text, an accessibilityLabel is required to describe the button's purpose for screen readers.
<IconButton name="close" accessibilityLabel="Close trade modal" />
When composing a button with a visible label, use accessibilityLabelledBy to reference the label's id instead. See the Claim Drop example below.
Composed Examples
Claim Drop
A toggleable icon button with an adjacent label. Uses accessibilityLabelledBy to associate the button with its visible label.
function ClaimDropExample() {
const [active, setActive] = useState(false);
const variant = useMemo(() => (active ? 'primary' : 'foregroundMuted'), [active]);
const label = useMemo(() => (active ? 'Reject drop' : 'Claim drop'), [active]);
return (
<HStack gap={2} alignItems="center">
<IconButton
name="drops"
active={active}
variant={variant}
onClick={() => setActive((active) => !active)}
id="claim-drop-button"
accessibilityLabelledBy="claim-drop-label"
/>
<Text font="label1" as="label" htmlFor="claim-drop-button" id="claim-drop-label">
{label}
</Text>
</HStack>
);
}
Notification Bell
An icon button with a badge showing the notification count. Uses DotCount to display the number of unread notifications.
<DotCount count={3} overlap="circular" pin="top-end">
<IconButton
name="bell"
accessibilityLabel="Notifications, 3 unread"
variant="secondary"
onClick={console.log}
/>
</DotCount>