Utility button components

FREE

Free and open-source React utility button components built for modern applications and websites. These utility buttons are built using React Aria and styled with Tailwind CSS.

Installation

You can add this utility button component using our CLI or manually:

npx untitledui@latest add button-utility

Utility button examples

Below are examples and variations of this utility button component:

API reference

ButtonUtility

Import ButtonUtility from @/components/base/buttons/button-utility.

ButtonUtility props
PropTypeDefaultDescription
isDisabledboolean—Disables the button and shows a disabled state.
size
"xs""sm"
"sm"The size variant of the button.
color
"secondary""tertiary"
"secondary"The color variant of the button.
iconReactNode | FC<{ className?: string; }>—The icon to display in the button.
tooltipstring—The tooltip to display when hovering over the button.
tooltipPlacement
"bottom""end""left""right""start""top""bottom left""bottom right""bottom start""bottom end""top left""top right""top start""top end"
+8 more
"left top""left bottom""start top""start bottom""right top""right bottom""end top""end bottom"
"top"The placement of the tooltip.
classNamestring—The class name applied to the button.
Props from React Aria (23)
ButtonUtility inherited props
PropTypeDefaultDescription
onClick((e: MouseEvent<FocusableElement>) => void)—Not recommended – use onPress instead. onClick is an alias for onPress provided for compatibility with other libraries. onPress provides additional event details for non-mouse interactions.
onPress((e: PressEvent) => void)—Handler that is called when the press is released over the target.
onPressChange((isPressed: boolean) => void)—Handler that is called when the press state changes.
onPressEnd((e: PressEvent) => void)—Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target.
onPressStart((e: PressEvent) => void)—Handler that is called when a press interaction starts.
onPressUp((e: PressEvent) => void)—Handler that is called when a press is released over the target, regardless of whether it started on the target or not.
onHoverChange((isHovering: boolean) => void)—Handler that is called when the hover state changes.
onHoverEnd((e: HoverEvent) => void)—Handler that is called when a hover interaction ends.
onHoverStart((e: HoverEvent) => void)—Handler that is called when a hover interaction starts.
onBlur((e: FocusEvent<Element, Element>) => void)—Handler that is called when the element loses focus.
onFocus((e: FocusEvent<Element, Element>) => void)—Handler that is called when the element receives focus.
onFocusChange((isFocused: boolean) => void)—Handler that is called when the element's focus status changes.
autoFocusboolean—Whether the element should receive focus on render.
onKeyDown((e: KeyboardEvent) => void)—Handler that is called when a key is pressed.
onKeyUp((e: KeyboardEvent) => void)—Handler that is called when a key is released.
idstring—The element's unique identifier.
styleStyleOrFunction<T>—The inline style for the element. A function may be provided to compute the style based on component state.
slotstring | null—A slot name for the component. Slots allow the component to receive props from a parent component. An explicit null value indicates that the local props completely override all props received from a parent.
render(props: DetailedHTMLProps<LinkWithRequiredHref, HTMLAnchorElement> | JSX.IntrinsicElements[Fallback], renderProps: T) => ReactElement—Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components.Note: You can check if 'href' in props in order to tell whether to render an <a> element.Requirements:
  • You must render the expected element type (e.g. if <a> is expected, you cannot render a <button>).
  • Only a single root DOM element can be rendered (no fragments).
  • You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.
aria-describedbystring—Identifies the element (or elements) that describes the object.
aria-detailsstring—Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-labelstring—Defines a string value that labels the current element.
aria-labelledbystring—Identifies the element (or elements) that labels the current element.

Also accepts the global HTML attributes (dir, lang, hidden, inert, translate), all standard React DOM event handlers.

CloseButton

Import CloseButton from @/components/base/buttons/close-button. Renders React Aria’s Button — all of its props are supported.

CloseButton props
PropTypeDefaultDescription
theme
"light""dark"
"light"Whether the icon is styled for a light background (light) or a dark one (dark).
size
"xs""sm""md""lg"
"sm"Controls the dimensions of the button and its icon.
labelstring—The accessible name of the button, applied as aria-label. Defaults to "Close".
slotstring | null"close"The React Aria slot the button fills. Defaults to "close" so it automatically closes a parent Dialog/Modal without an explicit handler. Pass null to opt out (e.g. when used as a SearchField clear button it is picked up regardless of slot).
Props from React Aria (43)
CloseButton inherited props
PropTypeDefaultDescription
onClick((e: MouseEvent<FocusableElement>) => void)—Not recommended – use onPress instead. onClick is an alias for onPress provided for compatibility with other libraries. onPress provides additional event details for non-mouse interactions.
onPress((e: PressEvent) => void)—Handler that is called when the press is released over the target.
onPressChange((isPressed: boolean) => void)—Handler that is called when the press state changes.
onPressEnd((e: PressEvent) => void)—Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target.
onPressStart((e: PressEvent) => void)—Handler that is called when a press interaction starts.
onPressUp((e: PressEvent) => void)—Handler that is called when a press is released over the target, regardless of whether it started on the target or not.
onHoverChange((isHovering: boolean) => void)—Handler that is called when the hover state changes.
onHoverEnd((e: HoverEvent) => void)—Handler that is called when a hover interaction ends.
onHoverStart((e: HoverEvent) => void)—Handler that is called when a hover interaction starts.
onBlur((e: FocusEvent<Element, Element>) => void)—Handler that is called when the element loses focus.
onFocus((e: FocusEvent<Element, Element>) => void)—Handler that is called when the element receives focus.
onFocusChange((isFocused: boolean) => void)—Handler that is called when the element's focus status changes.
autoFocusboolean—Whether the element should receive focus on render.
excludeFromTabOrderboolean—Whether to exclude the element from the sequential tab order. If true, the element will not be focusable via the keyboard by tabbing. This should be avoided except in rare scenarios where an alternative means of accessing the element or its functionality via the keyboard is available.
onKeyDown((e: KeyboardEvent) => void)—Handler that is called when a key is pressed.
onKeyUp((e: KeyboardEvent) => void)—Handler that is called when a key is released.
formstring—The <form> element to associate the button with. The value of this attribute must be the id of a <form> in the same document.
formActionstring | ((formData: FormData) => void | Promise<void>)—The URL that processes the information submitted by the button. Overrides the action attribute of the button's form owner.
formEncTypestring—Indicates how to encode the form data that is submitted.
formMethodstring—Indicates the HTTP method used to submit the form.
formNoValidateboolean—Indicates that the form is not to be validated when it is submitted.
formTargetstring—Overrides the target attribute of the button's form owner.
idstring—The element's unique identifier.
isDisabledboolean—Whether the button is disabled.
isPendingboolean—Whether the button is in a pending state. This disables press and hover events while retaining focusability, and announces the pending state to screen readers.
namestring—Submitted as a pair with the button's value as part of the form data.
preventFocusOnPressboolean—Whether to prevent focus from moving to the button when pressing it.Caution, this can make the button inaccessible and should only be used when alternative keyboard interaction is provided, such as ComboBox's MenuTrigger or a NumberField's increment/decrement control.
type
"button""submit""reset"
"button"The behavior of the button when used in an HTML form.
valuestring—The value associated with the button's name when it's submitted with the form data.
styleStyleOrFunction<ButtonRenderProps>—The inline style for the element. A function may be provided to compute the style based on component state.
childrenChildrenOrFunction<ButtonRenderProps>—The children of the component. A function may be provided to alter the children based on component state.
classNameClassNameOrFunction<ButtonRenderProps>—The CSS className for the element. A function may be provided to compute the class based on component state.
renderDOMRenderFunction<"button", ButtonRenderProps>—Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components.Requirements:
  • You must render the expected element type (e.g. if <button> is expected, you cannot render an <a>).
  • Only a single root DOM element can be rendered (no fragments).
  • You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.
aria-describedbystring—Identifies the element (or elements) that describes the object.
aria-detailsstring—Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-labelstring—Defines a string value that labels the current element.
aria-labelledbystring—Identifies the element (or elements) that labels the current element.
aria-controlsstring—Identifies the element (or elements) whose contents or presence are controlled by the current element.
aria-current
falsetrue"step""true""false""page""location""date""time"
—Indicates whether this element represents the current item within a container or set of related elements.
aria-disabled
falsetrue"true""false"
—Indicates whether the element is disabled to users of assistive technology.
aria-expanded
falsetrue"true""false"
—Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-haspopup
falsetrue"true""false""menu""listbox""tree""grid""dialog"
—Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-pressed
falsetrue"true""false""mixed"
—Indicates the current "pressed" state of toggle buttons.

Also accepts the global HTML attributes (dir, lang, hidden, inert, translate), all standard React DOM event handlers.

FAQs

Please refer to our frequently asked questions page for more.

Utility buttons support "secondary" and "tertiary" through the color prop. The default "secondary" has a background, border and shadow, while "tertiary" only shows a background on hover.

Utility buttons come in "xs" and "sm". The default is "sm", which renders a 20px icon; "xs" renders a 16px icon.

Pass a string to the tooltip prop. The button is wrapped in a Tooltip and the same text is used as the button's aria-label. Use tooltipPlacement to change the position, which defaults to "top". The tooltip doesn't open while the button is disabled.

Use the icon prop with a component reference, like icon={Copy01}, or with an element. When passing an element, add the data-icon attribute so it picks up the button's icon size and color styles.

Pass an aria-label that describes the action, for example aria-label="Copy". Utility buttons only contain an icon, so without tooltip or aria-label the button has no accessible name.

Yes, pass href and it renders a React Aria Link with the same styles. When isDisabled is true, the href is removed so the link can't be followed.

Use the CloseButton component from @/components/base/buttons/close-button, shown in the Close X examples. It supports theme "light" (default) or "dark", sizes "xs", "sm" (default), "md" and "lg", and uses "Close" as its aria-label unless you pass label. It fills React Aria's "close" slot, so it closes a parent dialog or modal without an extra handler.