Icon buttons
Icon buttons help people take minor actions with one tap
Usage
Use icon buttons to display actions in a compact layout. Icon buttons can represent opening actions such as opening an overflow menu or search, or represent binary actions that can be toggled on and off, such as favorite or bookmark.
Icon buttons can be grouped together or they can stand alone.
Instalation
Run the following command if is not already installed:
npm i @radix-ui/react-slot
Copy and paste the following code into your project.
import * as React from 'react'
import { Slot, Slottable } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const iconButtonVariants = cva(
'shrink-0 relative group/button h-10 w-10 overflow-hidden grid place-items-center rounded-xl transition outline-none disabled:pointer-events-none disabled:text-onSurface/38 active:scale-[0.98]',
{
variants: {
variant: {
filled: 'bg-primary text-onPrimary disabled:bg-onSurface/12',
tonal:
'bg-secondaryContainer text-onSecondaryContainer disabled:bg-onSurface/12',
outlined:
'border border-outline text-onSurfaceVariant disabled:border-onSurface/12',
standard: 'text-onSurfaceVariant',
},
},
defaultVariants: {
variant: 'filled',
},
}
)
const stateLayerVariants = cva(
'transition-opacity absolute inset-0 z-0 opacity-0 group-hover/button:opacity-8 group-focus/button:opacity-12 group-active/button:opacity-12',
{
variants: {
variant: {
filled: 'bg-onPrimary',
tonal: 'bg-onSecondaryContainer',
outlined: 'bg-onSurfaceVariant',
standard: 'bg-onSurfaceVariant',
},
},
defaultVariants: {
variant: 'filled',
},
}
)
export interface IconButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof iconButtonVariants> {
asChild?: boolean
disableStateLayer?: boolean
}
const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
(
{ className, variant, asChild, disableStateLayer, children, ...props },
ref
) => {
const Comp = asChild ? Slot : 'button'
return (
<Comp
ref={ref}
className={cn(iconButtonVariants({ variant, className }))}
{...props}
>
<Slottable>{children}</Slottable>
{!disableStateLayer && (
<span className={cn(stateLayerVariants({ variant }))} />
)}
</Comp>
)
}
)
IconButton.displayName = 'IconButton'
export { IconButton, iconButtonVariants, stateLayerVariants }
Update the import paths to match your project setup.
Examples
Filled icon button
Filled icon buttons have higher visual impact and are best for high emphasis actions.
import { Icon } from '@/components/ui/icon'
import { IconButton } from '@/components/ui/icon-button'
export const FilledIconButton = () => {
return (
<IconButton>
<Icon symbol="settings" />
</IconButton>
)
}
Filled tonal icon button
Filled tonal icon buttons are a middle ground between filled and outlined icon buttons. They’re useful in contexts where the button requires slightly more emphasis than an outline would give, such as a secondary action paired with a high emphasis action.
import { Icon } from '@/components/ui/icon'
import { IconButton } from '@/components/ui/icon-button'
export const FilledTonalIconButton = () => {
return (
<IconButton variant="tonal">
<Icon symbol="settings" />
</IconButton>
)
}
Outlined icon button
Outlined icon buttons are medium-emphasis buttons. They’re useful when an icon button needs more emphasis than a standard icon button but less than a filled or filled tonal icon button.
import { Icon } from '@/components/ui/icon'
import { IconButton } from '@/components/ui/icon-button'
export const OutlinedIconButton = () => {
return (
<IconButton variant="outlined">
<Icon symbol="settings" />
</IconButton>
)
}
Standard icon button
Standard icon buttons are small-emphasis buttons. They’re useful when an icon button needs less emphasis than a contained button.
import { Icon } from '@/components/ui/icon'
import { IconButton } from '@/components/ui/icon-button'
export const StandardIconButton = () => {
return (
<IconButton variant="standard">
<Icon symbol="settings" />
</IconButton>
)
}