IconButton
Icon that acts as a button, with hover and pressed colours and an optional tooltip. It is the control for a row action or a toolbar, where a label would not fit.
Use this when / not when
- Use for an action that a recognisable icon explains on its own: close, copy, more, refresh.
- Not for an action with a label —
Buttonis a real button element, focusable and named, and it takes an icon too. - Not for an icon that opens a menu of actions: that is
ContextMenuButton. - Not for a decorative icon. This one keeps its hover colours whether or not anything
happens, and shows a pointer cursor as soon as it has an
onClickorisClickable.
Import
import { IconButton } from "@onlyoffice/apps-ui-kit/components/icon-button";
Also exported from the root barrel @onlyoffice/apps-ui-kit.
Needs ThemeProvider from @onlyoffice/apps-ui-kit/providers/theme above it in the tree for
the icon's default colour and for color="accent".
Stories
Default
With Hover State
Hover over the buttons to see the alternate icon and colour, a cue that the button reacts before it is clicked (iconHoverName, hoverColor).
With Click State
Press and hold the button to see the alternate icon and colour that confirm the press (iconClickName, clickColor); they stay until the pointer leaves the button.
Sizes
Icon buttons at 16, 20, 25, 32 and 40px, so a size can be picked to match the surrounding text or row height (size).
Disabled
Disabled icon buttons ignore clicks and hover and keep their default icon and colour (isDisabled). They look the same as enabled ones apart from the arrow cursor, so pair them with a visible reason when the difference matters.
With Stroke
Stroke mode colours the outlines of the icon's shapes and leaves their own fill as drawn, which suits outline icons (isStroke). The two filled icons here show that: each keeps its fill and gains a grey outline.
With Custom Node
A square of initials in place of an SVG icon: any React node can be the icon, rendered inline with no network request (iconNode).
With Tooltip
Hover over the button to read what it does: an icon alone rarely says so, and the button renders this tooltip itself, next to the pointer (tooltipId, tooltipContent).
Css Customization
The variables are listed under CSS variables on this page; here all three are set through the style prop, because a value set on a wrapper never arrives. Hover the button to see the hover colour.
Minimal example
Pass the icon as a node. It needs no network request and your bundler types it.
import { IconButton } from "@onlyoffice/apps-ui-kit/components/icon-button";
export function CloseButton({ onClose }: { onClose: () => void }) {
return (
<IconButton
size={16}
title="Close"
onClick={onClose}
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") onClose();
}}
iconNode={
<svg viewBox="0 0 16 16" aria-hidden="true">
<path
d="M4 4l8 8M12 4l-8 8"
stroke="currentColor"
strokeWidth="1.5"
/>
</svg>
}
/>
);
}
Props
Recipes
Disabled
import { IconButton } from "@onlyoffice/apps-ui-kit/components/icon-button";
export function RefreshButton({ busy }: { busy: boolean }) {
return (
<IconButton
size={16}
isDisabled={busy}
title="Refresh"
onClick={() => {}}
iconNode={
<svg viewBox="0 0 16 16" aria-hidden="true">
<circle
cx="8"
cy="8"
r="6"
fill="none"
stroke="currentColor"
strokeWidth="1.5"
/>
</svg>
}
/>
);
}
An icon loaded from a URL
iconName is a URL that the browser fetches, so it has to be one your bundler produced or one
under your public directory.
import { IconButton } from "@onlyoffice/apps-ui-kit/components/icon-button";
import trashUrl from "./trash.svg?url";
export function DeleteButton({ onDelete }: { onDelete: () => void }) {
return (
<IconButton
size={16}
iconName={trashUrl}
color="--accent-main"
title="Delete"
onClick={onDelete}
/>
);
}
Behaviour the types don't state
iconNameis a URL. It goes toreact-svgassrc, which fetches it and inlines the markup, so an asset name, an import of the SVG as a component, or a build-time alias of the DocSpace client will not work.iconNodeavoids the request entirely.- It renders a
<div>, not a<button>. There is no implicit role, no tab stop and no Enter or Space activation. A button anyone can use from the keyboard needstabIndex,onKeyDownand a role of your own — the minimal example shows the minimum. onMouseUpfires only for the middle and right buttons. The component switches onevent.nativeEvent.buttonand handles1and2, having labelled1as the left button; the left button is0and falls through. UseonClick.- The hover and pressed icon swaps are suppressed on a touch device, which the component
detects by
ontouchstart. isDisabledblocks every handler including the colour swaps, and setsaria-disabled; the element stays in the tab order if you gave it one. The stylesheet changes nothing but the cursor, which becomes the arrow, so a disabled button keeps its default icon and colour and otherwise looks the same as an enabled one.- The cursor is the pointer only when the button has an
onClickorisClickable; otherwise it is the arrow. - With
tooltipIdandtooltipContentthe button renders its ownTooltipbelow itself, which follows the pointer on a desktop and stays put elsewhere. titlenever reaches the DOM — the component's tooltip container consumes it.
CSS variables
The component declares these on its own element and writes them into its inline style from the
size and color props, so a value set on a wrapper never arrives. The props are the way to
change them; the style prop also works, because it is applied after them. color accepts
the name of a custom property (color="--accent-main"), which it wraps in var().
Accessibility
- The element is a
<div>with no role and no accessible name. A screen reader announces nothing unless you addrole="button"and a name, which the component does not do for you. aria-disabledis always set:truewhileisDisabled,falseotherwise.aria-labelis passed through to the element and is the way to give it a name.- The tooltip from
titleis not an accessible name either — it is rendered by the kit's tooltip, not by the platform. - For an icon-only action that has to be usable by everyone,
Buttonwitharia-labelis the safer component.
Test ids
| Element | data-testid |
|---|---|
| The button | icon-button, overridable with dataTestId |
The fetched SVG, with iconName | icon-button-svg |
Related
Button— a real button, with a label and an icon.ContextMenuButton— an icon that opens a menu.Tooltip— the tooltiptitleandtooltipContentfeed.