IconButton
A button that is an icon and no word. It is a square, and the one place the icon inside it gets its size. Its label is the accessible name and the tooltip at once, so the two never drift apart.
import { IconButton } from '@basmilius/react-ui';import { useState } from 'react';
import { Bold, ChevronRight, Italic, RefreshCw, Settings, Trash } from 'lucide-react';
import { ButtonGroup, IconButton, Separator, shortcut } from '@basmilius/react-ui';
const REFRESH = shortcut('Mod+R');
export default function IconButtonDemo() {
const [bold, setBold] = useState(true);
const [italic, setItalic] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [open, setOpen] = useState(false);
const refresh = (): void => {
setRefreshing(true);
window.setTimeout(() => setRefreshing(false), 1200);
};
return (
<div className="flex items-center gap-2">
<ButtonGroup>
<IconButton icon={Bold} label="Bold" aria-pressed={bold} onClick={() => setBold(!bold)} />
<IconButton icon={Italic} label="Italic" aria-pressed={italic} onClick={() => setItalic(!italic)} />
</ButtonGroup>
<Separator />
<IconButton icon={RefreshCw} label="Refresh" kbd={REFRESH} spin={refreshing} onClick={refresh} />
<IconButton
icon={ChevronRight}
label={open ? 'Collapse' : 'Expand'}
aria-expanded={open}
iconClassName={open ? 'rotate-90 transition-transform' : 'transition-transform'}
onClick={() => setOpen(!open)}
/>
<IconButton icon={Settings} label="Settings" tooltipSide="bottom" />
<IconButton icon={Trash} label="Delete" tooltip="Nothing is selected" aria-disabled />
</div>
);
}Sizes
The size decides the square, the radius and the icon inside: 16 in the default 32, 14 in 28 (sm), and 12 in 24 (xs) and 20 (2xs). Never set a height, a width or a radius on it. w-auto is the one way to widen it, for a word beside the icon handed in as children.
import { Plus } from 'lucide-react';
import { IconButton } from '@basmilius/react-ui';
export default function IconButtonSizes() {
return (
<div className="flex items-center gap-3">
<IconButton icon={Plus} label="Add (32, icon 16)" />
<IconButton icon={Plus} label="Add (28, icon 14)" size="sm" />
<IconButton icon={Plus} label="Add (24, icon 12)" size="xs" />
<IconButton icon={Plus} label="Add (20, icon 12)" size="2xs" />
<IconButton icon={Plus} label="Add a file" className="w-auto gap-1.5 px-2 text-xs">
Add
</IconButton>
</div>
);
}Toggles and state
active draws the button as a pressed key, for a toggle that is on. Where the button is a real toggle, use aria-pressed instead, as the bold and italic buttons above do. The theme draws both the same. spin turns the icon for a step that is running.
iconClassName goes to the icon rather than the button, for a chevron that turns when its section opens, a status icon in its own tone or a filled glyph (fill-current). The icon keeps the size of the button; one that needs another size is handed in as children without icon.
A disabled icon button with disabled loses its tooltip, because a disabled button takes no pointer events. With aria-disabled it keeps its focus and its tooltip, which can say why nothing happens.
As another element
render makes another element the button, such as a menu trigger. The trigger's behavior and the button's look merge into one element:
<Menu.Root>
<IconButton icon={Ellipsis} label="More" render={<Menu.Trigger />} />
<Menu.Popup>...</Menu.Popup>
</Menu.Root>Props
IconButton takes every prop of a <button> except children, plus:
| Prop | Type | Default | |
|---|---|---|---|
label | string | Required. The accessible name, and the tooltip unless tooltip says otherwise. | |
icon | LucideIcon | Left out for a button that draws something else, handed in as children. | |
tooltip | ReactNode | false | label | A tooltip that says more than the name, or false for none. |
kbd | Shortcut | string | The shortcut printed in the tooltip, and under the button while the modifier is held. | |
tooltipSide | TooltipSide | 'top' | |
size | IconButtonSize | 'md' | 'md' | 'sm' | 'xs' | '2xs' |
active | boolean | false | Draws a pressed key. |
spin | boolean | false | Turns the icon. |
iconClassName | string | Classes for the icon: a tone, a turn, a fill. | |
children | ReactNode | Drawn after the icon: a count, or a word with w-auto. | |
render | RenderProp | <button type="button" /> | Another element to be the button. |
IconButtonProps and IconButtonSize are exported types.