QUI React

Icon Button

An icon button performs an action when clicked (like a button), and it visually represents the action it will perform (like an icon).

import {QIconButton} from "@qui/react"

Overview

The icon button is best used as a screen's primary, or most common, action.

The Icon Button is very similar to the Button component. Use it when you want to render a clear and minimal action.

Accessibility

Icon buttons often rely on visual cues to communicate their purpose. However, for users who rely on assistive technologies like screen readers, these visual cues are not accessible. This is where aria-label comes in.

The aria-label attribute provides a text description to these assistive technologies, effectively conveying the purpose of the icon button.

Guidelines

  • Always provide either an aria-label or aria-labelledby attribute.

Examples

Style

Fill
Outline
Ghost
import {ReactNode} from "react"
import {ExternalLink} from "lucide-react"
import {QIconButton} from "@qui/react"
export default function Style(): ReactNode {
return (
<div className="grid grid-cols-3 grid-rows-2 justify-items-center gap-x-8 gap-y-1">
<div className="q-font-heading-xs">Fill</div>
<div className="q-font-heading-xs">Outline</div>
<div className="q-font-heading-xs">Ghost</div>
<QIconButton
aria-label="Navigate"
color="primary"
icon={ExternalLink}
variant="fill"
/>
<QIconButton
aria-label="Navigate"
color="primary"
icon={ExternalLink}
variant="outline"
/>
<QIconButton
aria-label="Navigate"
color="primary"
icon={ExternalLink}
variant="ghost"
/>
</div>
)
}

Sizes

Customize size using the size property.

import {ReactNode} from "react"
import {ExternalLink} from "lucide-react"
import {QIconButton} from "@qui/react"
export default function Size(): ReactNode {
return (
<div className="flex flex-1 items-end justify-center gap-8">
<QIconButton
aria-label="Navigate"
icon={ExternalLink}
size="xs"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
icon={ExternalLink}
size="s"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
icon={ExternalLink}
size="m"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
icon={ExternalLink}
size="l"
variant="fill"
/>
</div>
)
}

Dense Property

The dense property can be used to reduce the button's padding.

import {ReactNode} from "react"
import {ExternalLink} from "lucide-react"
import {QIconButton} from "@qui/react"
export default function Dense(): ReactNode {
return (
<div className="grid justify-center">
<div className="flex flex-1 items-end gap-8">
<QIconButton
aria-label="Navigate"
dense
icon={ExternalLink}
size="xs"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
dense
icon={ExternalLink}
size="s"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
dense
icon={ExternalLink}
size="m"
variant="fill"
/>
<QIconButton
aria-label="Navigate"
dense
icon={ExternalLink}
size="l"
variant="fill"
/>
</div>
</div>
)
}

Shapes

The round shape is also available.

Colors

Customize the color of the Icon Button using the color input.

Fill
Outline
Ghost
import {Fragment, ReactNode} from "react"
import {ExternalLink} from "lucide-react"
import {QButtonColor} from "@qui/base"
import {QIconButton} from "@qui/react"
const buttonColors: QButtonColor[] = [
"neutral",
"primary",
"positive",
"warning",
"negative",
]
export default function AllColors(): ReactNode {
return (
<div className="grid grid-cols-3 grid-rows-7 justify-items-center gap-x-8 gap-y-5">
<div className="q-font-heading-xs">Fill</div>
<div className="q-font-heading-xs">Outline</div>
<div className="q-font-heading-xs">Ghost</div>
{buttonColors.map((color) => {
return (
<Fragment key={color}>
<QIconButton
aria-label="Navigate"
color={color}
icon={ExternalLink}
variant="fill"
/>
<QIconButton
aria-label="Navigate"
color={color}
icon={ExternalLink}
variant="outline"
/>
<QIconButton
aria-label="Navigate"
color={color}
icon={ExternalLink}
variant="ghost"
/>
</Fragment>
)
})}
<QIconButton
aria-label="Navigate"
disabled
icon={ExternalLink}
variant="fill"
/>
<QIconButton
aria-label="Navigate"
disabled
icon={ExternalLink}
variant="outline"
/>
<QIconButton
aria-label="Navigate"
disabled
icon={ExternalLink}
variant="ghost"
/>
</div>
)
}

Contrast

The contrast color can be used to provide optimal contrast on alternate background colors.

Fill
Outline
Ghost
import {ReactNode} from "react"
import {ExternalLink} from "lucide-react"
import {clsx} from "@qui/base"
import {QIconButton} from "@qui/react"
export default function Contrast(): ReactNode {
return (
<div className="grid justify-center">
<div
className={clsx(
"bg-contrast-4",
"grid grid-cols-3 grid-rows-2",
"justify-items-center gap-x-8 gap-y-1 rounded p-4",
)}
>
<div className="text-contrast-primary q-font-heading-xs">Fill</div>
<div className="text-contrast-primary q-font-heading-xs">Outline</div>
<div className="text-contrast-primary q-font-heading-xs">Ghost</div>
<QIconButton
aria-label="Navigate"
color="contrast"
icon={ExternalLink}
variant="fill"
/>
<QIconButton
aria-label="Navigate"
color="contrast"
icon={ExternalLink}
variant="outline"
/>
<QIconButton
aria-label="Navigate"
color="contrast"
icon={ExternalLink}
variant="ghost"
/>
</div>
</div>
)
}

Loading

The icon prop accepts either a LucideIcon or ReactNode, which is useful for composing advanced patterns. The following example features an interactive loading button.

import {ReactNode, useRef, useState} from "react"
import {DownloadCloudIcon} from "lucide-react"
import {QIconButton, QProgressCircle} from "@qui/react"
Loading.displayName = "Loading"
export default function Loading(): ReactNode {
const [loading, setLoading] = useState(false)
const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined)
const onToggle = () => {
clearTimeout(timeoutRef.current)
setLoading(true)
// simulate an async action
timeoutRef.current = setTimeout(() => {
setLoading(false)
}, 2000)
}
return (
<QIconButton
icon={
loading ? (
<QProgressCircle color="inherit" size="xxs" />
) : (
DownloadCloudIcon
)
}
onClick={onToggle}
shape="round"
variant="outline"
/>
)
}

API

Props

Name & DescriptionOption(s)Default
The component used for the root node. It can be a React component or element.
| ElementType
| ComponentType
'button'
React children prop.
ReactNode
The className property of the Element interface gets and sets the value of the class attribute of the specified element.
string
Overrides the classes of the internal elements.
{
icon?: ClassValue
root?: ClassValue
}
The color variant of the button.
| 'inherit'
| 'neutral'
| 'primary'
| 'positive'
| 'warning'
| 'negative'
| 'contrast'
'neutral'
If true, the component will render with reduced padding.
boolean
false
If true, the component will not be interactive and will appear dimmed.
boolean
false
If true, all CSS transitions are disabled.
boolean
false
| LucideIcon
| ReactNode
If true, the button renders in the selected style. Note that this property takes precedence over the color and variant properties.
boolean
false
The shape of the button.
| 'square'
| 'round'
'square'
The size of the component and its icons.
| 'xs'
| 's'
| 'm'
| 'l'
'm'
The style global attribute contains CSS styling declarations to be applied to the element.
CSSProperties
The style variant of the button.
| 'fill'
| 'outline'
| 'ghost'
'ghost'
Type
| ElementType
| ComponentType
Default
'button'
Description
The component used for the root node. It can be a React component or element.
Description
React children prop.
Type
string
Description
The className property of the Element interface gets and sets the value of the class attribute of the specified element.
Type
{
icon?: ClassValue
root?: ClassValue
}
Description
Overrides the classes of the internal elements.
Type
| 'inherit'
| 'neutral'
| 'primary'
| 'positive'
| 'warning'
| 'negative'
| 'contrast'
Default
'neutral'
Description
The color variant of the button.
Type
boolean
Default
false
Description
If true, the component will render with reduced padding.
Type
boolean
Default
false
Description
If true, the component will not be interactive and will appear dimmed.
Type
boolean
Default
false
Description
If true, all CSS transitions are disabled.
Type
| LucideIcon
| ReactNode
Description
Type
boolean
Default
false
Description
If true, the button renders in the selected style. Note that this property takes precedence over the color and variant properties.
Type
| 'square'
| 'round'
Default
'square'
Description
The shape of the button.
Type
| 'xs'
| 's'
| 'm'
| 'l'
Default
'm'
Description
The size of the component and its icons.
Description
The style global attribute contains CSS styling declarations to be applied to the element.
Type
| 'fill'
| 'outline'
| 'ghost'
Default
'ghost'
Description
The style variant of the button.