MD3
Expressive
MATERIAL DESIGN 3 EXPRESSIVE

Icon Buttons

Icon buttons let people take action with a single icon.

Icon buttons let people take action with a single icon. They are compact, high-density components used for the most frequent actions — like liking, bookmarking, or sharing. They morph in shape and color to communicate context and state.

Introduction

The MD3 Expressive Icon Button is a refined version of the standard button, optimized for density and clarity. It supports four primary color styles (Standard, Filled, Tonal, and Outlined) and can function as a simple action or a stateful toggle. In the Expressive update, icon buttons feature smooth shape-morphing transitions that provide tactile confirmation of interaction.

Anatomy

  • Container: The surface of the button. Supports multiple shapes (round, square) and variants.
  • Icon: The visual indicator of the action. Should be universally understood.
  • State Layer: Handles hover and pressed states with a ripple effect and morphing.
  • Selection Indicator (Toggle): In toggle mode, the container color or icon fill changes to indicate the active state.

Variants

Color Styles

  • Filled: High emphasis. Best for the primary action in a section.
  • Tonal: Medium-high emphasis. A softer alternative to Filled.
  • Outlined: Medium emphasis. Uses a border for visual separation.
  • Standard: Low emphasis. Ideal for toolbars and overflow menus.
Loading demo...

Toggle Mode

Icon buttons can toggle between two states. When selected, the button can morph its shape (e.g., from round to rounded-square) and its color to provide clear feedback.

Loading demo...

Selected Icon

Instead of conditional rendering in children, use the selectedIcon prop to render an active icon variant (such as filled) automatically when selected={true}.

Loading demo...

Features

Shapes

Choose between Round (classic) and Square (modern/expressive) base shapes. Both support morphing on interaction.

Loading demo...

Sizing

Supports five sizes (XS to XL), allowing you to match the density of your interface.

Loading demo...

Width Variants

In MD3 Expressive, icon buttons support three container width variants (default 1:1, narrow, wide) to fit different interface layouts and spatial contexts.

Loading demo...

Loading State

Displays a loading indicator while a process is in progress, automatically disabling interaction and updating ARIA states.

Loading demo...

Usage

Basic Action

import { IconButton, Icon } from "@bug-on/m3-expressive";

<IconButton 
  icon={<Icon name="share" />} 
  aria-label="Share content" 
  onClick={() => handleShare()} 
/>

Toggle Button

const [liked, setLiked] = useState(false);

<IconButton
  variant="toggle"
  selected={liked}
  onClick={() => setLiked(!liked)}
  icon={<Icon name="favorite" />}
  selectedIcon={<Icon name="favorite" fill={1} />}
  aria-label="Like"
  colorStyle="tonal"
/>

Width Variants

<IconButton
  icon={<Icon name="tune" />}
  aria-label="Filters"
  width="wide"
/>

Next.js Integration (asChild)

Use the asChild prop to render a different element (like a Next.js Link) while maintaining IconButton styling and ripple effects.

import Link from "next/link";
import { IconButton, Icon } from "@bug-on/m3-expressive";

<IconButton asChild aria-label="Settings">
  <Link href="/settings">
    <Icon name="settings" />
  </Link>
</IconButton>

Best Practices

Do

  • Always provide a descriptive aria-label since the button has no text.
  • Use tooltips to explain the action if the icon is not universally known.
  • Use the Standard variant for low-priority actions in a toolbar.
  • Ensure the icon is centered perfectly within the container.

Don't

  • Don't use more than one Filled icon button in a single area.
  • Avoid using very small sizes (XS) for primary actions on touch devices.
  • Don't use complex or ambiguous icons; stick to well-known symbols.

Accessibility

  • Required Label: aria-label must be provided for every icon button.
  • Toggle State: Uses aria-pressed for toggle variants.
  • Touch Target: Even smaller visual sizes maintain a minimum 48x48dp touch target.
  • Motion: Morphing animations respect prefers-reduced-motion.

API Reference

IconButton

PropTypeDefaultDescription
colorStyle"standard" | "filled" | "tonal" | "outlined""standard"Visual variant.
variant"action" | "toggle""action"Behavior mode.
selectedbooleanfalseRequired for toggle variant.
selectedIconReactNodeActive icon to display when variant="toggle" and selected={true}.
iconReactNodeThe icon to display.
size"xs" | "sm" | "md" | "lg" | "xl""md"Physical container dimensions (height/diameter).
width"narrow" | "default" | "wide""default"Container slot width ratio per MD3 Expressive specification (MD3SlotWidth).
shape"round" | "square""round"Base container shape.
loadingbooleanfalseShows loading indicator.
asChildbooleanfalseRenders as the child element while keeping styles.
classNamestringCustom classes.