MD3
Expressive
MATERIAL DESIGN 3 EXPRESSIVE

Toolbars

Toolbars provide a surface for frequently used actions, typically floating or docked at the screen edge.

Toolbars are a versatile alternative to traditional App Bars in Material Design 3 Expressive. They can be docked to the bottom of the screen or float above content, providing context-aware actions in a compact, modern format.

Loading demo...

Introduction

MD3 Expressive Toolbars are designed for high-density action surfaces. Unlike standard App Bars, which are usually pinned to the top, Toolbars are often placed at the bottom or sides of the screen to optimize thumb reachability on mobile and provide a more focused workspace on desktop. They support dynamic expansion states, toggleable action building blocks, and spatial XR elevations.

Anatomy

  • Container: The background surface, available in pill (standard), large rounded, or spatial glassmorphic shapes.
  • Leading Content: Actions shown only when the toolbar is expanded.
  • Main Content: Primary actions that remain visible in both collapsed and expanded states.
  • Trailing Content: Secondary actions or settings shown when expanded.
  • FAB integration: Floating toolbars can be paired with a Floating Action Button (FAB).

Variants

Bottom Docked Toolbar

A full-width toolbar fixed at the bottom of the screen. It is the modern replacement for the traditional Bottom App Bar, supporting leading, centered, and trailing content slots.

Loading demo...
<BottomDockedToolbar 
  startContent={<IconButton aria-label="Menu"><Icon name="menu" /></IconButton>}
  endContent={<IconButton aria-label="More"><Icon name="more_vert" /></IconButton>}
>
  <div className="flex gap-2">
    <IconButton aria-label="Search"><Icon name="search" /></IconButton>
    <IconButton aria-label="Edit"><Icon name="edit" /></IconButton>
  </div>
</BottomDockedToolbar>

Floating Toolbar (Horizontal & Vertical)

Floating toolbars are independent surfaces that hover over content. They are highly expressive, supporting a collapsed "pill" state and an expanded state that reveals more actions.

Loading demo...
Loading demo...
<HorizontalFloatingToolbar expanded={expanded}>
  <IconButton aria-label="Action"><Icon name="bolt" /></IconButton>
</HorizontalFloatingToolbar>

Floating Toolbar with FAB

A specialized variant that docks a Floating Action Button next to a floating toolbar. This creates a cohesive "action hub" that manages both the primary page action and secondary utility actions.

Loading demo...
Loading demo...
<HorizontalFloatingToolbarWithFab
  expanded={expanded}
  floatingActionButton={<FAB icon={<Icon name="add" />} aria-label="Add" />}
>
  <IconButton aria-label="Share"><Icon name="share" /></IconButton>
</HorizontalFloatingToolbarWithFab>

Spatial & XR Elevations (Glassmorphism)

Toolbars support 6 elevation and color variants, including spatial XR translucent surfaces with backdrop blur (backdrop-blur-md):

  • standard: Low-emphasis surface container.
  • vibrant: High-emphasis primary container.
  • surface-high: Elevated surface container high.
  • surface-highest: Elevated surface container highest.
  • tertiary: Tertiary container colors.
  • xr: Semi-transparent glassmorphic surface with backdrop blur for spatial/XR experiences.
Loading demo...
<HorizontalFloatingToolbar variant="xr" expanded={true}>
  <ToolbarToggleButton selected icon={<Icon name="view_in_ar" />}>
    Spatial View
  </ToolbarToggleButton>
  <ToolbarIconButton aria-label="Rotate"><Icon name="3d_rotation" /></ToolbarIconButton>
</HorizontalFloatingToolbar>

Flexibility & Slots

When configuring a toolbar, think of it as a container with slots. Slots can be populated by icon buttons, toggle buttons, images, text fields, or any custom component.

Toggle Actions & Buttons

Toolbars provide dedicated building blocks for toggleable actions (ToolbarToggleButton & ToolbarIconButton with selected state) and slot delegation (asChild):

Loading demo...
import {
  ToolbarIconButton,
  ToolbarToggleButton,
  ToolbarDivider,
  HorizontalFloatingToolbar,
} from "@bug-on/m3-expressive";

<HorizontalFloatingToolbar expanded={true}>
  {/* Toggle Icon Button */}
  <ToolbarIconButton 
    aria-label="Format Bold" 
    selected={isBold} 
    onClick={() => setIsBold(!isBold)}
  >
    <Icon name="format_bold" />
  </ToolbarIconButton>
  
  <ToolbarDivider />
  
  {/* Toggle Button with Text & Icon */}
  <ToolbarToggleButton 
    selected={activeTab === 'edit'} 
    onClick={() => setActiveTab('edit')}
    icon={<Icon name="edit" />}
    emphasis="tonal"
  >
    Edit
  </ToolbarToggleButton>
  
  {/* Slot Delegation via asChild */}
  <ToolbarIconButton aria-label="Home" asChild>
    <a href="#home"><Icon name="home" /></a>
  </ToolbarIconButton>
</HorizontalFloatingToolbar>

Emphasis Hierarchy & Dividers

Loading demo...

Use ToolbarIconButton to add emphasis hierarchy and ToolbarDivider to group related actions:

import {
  ToolbarIconButton,
  ToolbarDivider,
  HorizontalFloatingToolbar,
} from "@bug-on/m3-expressive";

// Single filled (high-emphasis) action alongside standard siblings
<HorizontalFloatingToolbar expanded={true}>
  <ToolbarIconButton aria-label="Bold"><BoldIcon /></ToolbarIconButton>
  <ToolbarIconButton aria-label="Italic"><ItalicIcon /></ToolbarIconButton>
  <ToolbarDivider />
  {/* One filled wide button draws the eye — avoid emphasising more than one */}
  <ToolbarIconButton emphasis="filled" width="wide" aria-label="Add">
    <AddIcon />
  </ToolbarIconButton>
</HorizontalFloatingToolbar>

Video-Like Toolbar Integration

Toolbars seamlessly host complex child components. By nesting a ButtonGroup with variant="connected" and fullWidth inside a HorizontalFloatingToolbar along with startContent and endContent, you can create highly sophisticated media or navigation surfaces:

<HorizontalFloatingToolbar
  colors={colors}
  expanded={expanded}
  itemGap={6}
  contentPadding="px-2!"
  startContent={<ToolbarIconButton aria-label="Volume"><VolumeIcon /></ToolbarIconButton>}
  endContent={<ToolbarIconButton aria-label="More"><MoreIcon /></ToolbarIconButton>}
>
  <ButtonGroup variant="connected" fullWidth className="h-full">
    <Button selected>Chapter 1</Button>
    <Button>Chapter 2</Button>
  </ButtonGroup>
</HorizontalFloatingToolbar>

Features

Scroll Behavior

Toolbars can be configured to respond to scrolling.

  • Floating Toolbars: Use the useFloatingToolbarScrollBehavior hook to automatically collapse or hide.
  • Docked Toolbars: Use the hideOnScroll prop to slide off-screen.

Floating Toolbar Scroll

Loading demo...

Docked Toolbar Scroll

Loading demo...

Accessibility

  • Roles: All toolbars apply role="toolbar" to ensure correct screen reader behavior.
  • Labels: Every interactive element within a toolbar must have an aria-label or visible text.
  • Keyboard Navigation: Toolbars support standard Tab navigation; focus remains visible through the MD3 focus ring.
  • Reduced Motion: All animations (expansion, translation, color shifts) respect the prefers-reduced-motion setting.

API Reference

BottomDockedToolbar

PropTypeDefaultDescription
variant'standard' | 'vibrant' | 'surface-high' | 'surface-highest' | 'tertiary' | 'xr''standard'The color and surface elevation configuration.
hideOnScrollbooleanfalseWhether to hide the toolbar when scrolling down.
startContentReactNodeContent at the left/start.
endContentReactNodeContent at the right/end.
childrenReactNodeCentered content.
paddingXnumber16Horizontal padding in px.
justify'between' | 'center' | 'end-weighted''between'Content distribution layout.
shape'none' | 'large' | 'full''none'Container shape. Use large for modern web feel.
scrollContainerRefRefObjectReference to the scrollable viewport.

Floating Toolbars (Horizontal/Vertical)

PropTypeDefaultDescription
expandedbooleanControls visibility of leading/trailing content.
variant'standard' | 'vibrant' | 'surface-high' | 'surface-highest' | 'tertiary' | 'xr''standard'Surface elevation & color configuration. Use xr for glassmorphic backdrop.
orientation'horizontal' | 'vertical''horizontal'Layout direction.
shape'full' | 'large''full''full' for pill, 'large' for rounded rectangle.
contentPaddingstring | objectCustom padding for the internal container.
startContentReactNodeContent revealed when expanded (start/top).
endContentReactNodeContent revealed when expanded (end/bottom).
childrenReactNodeMain content, always visible.
scrollBehaviorobjectResult from useFloatingToolbarScrollBehavior.
itemGapnumber4Gap (px) between items.
childrenAlignment'start' | 'center' | 'end''center'Justify-content of the center slot.
itemClassNamestringCustom CSS class applied to each child item.
colorsobjectstandardCustom color configuration override.
disableScrollTranslationbooleanfalseDisable automatic scroll-based movement.
disableLayoutAnimationbooleanfalseDisable framer-motion layout transitions.

ToolbarToggleButton

PropTypeDefaultDescription
selectedbooleanfalseActive toggle state (applies aria-pressed).
emphasis'standard' | 'tonal' | 'filled''standard'Visual emphasis style.
iconReactNodeOptional leading icon.
childrenReactNodeButton text label or content.
asChildbooleanfalseRenders as the child element (Radix Slot).

ToolbarIconButton

Inherits all IconButton props:

PropTypeDefaultDescription
selectedbooleanActive toggle state (applies aria-pressed).
emphasis'standard' | 'tonal' | 'filled''standard'Visual color style. Use filled for the single highest-priority action.
width'narrow' | 'default' | 'wide''default'Slot width ratio (MD3SlotWidth): 40 / 48 / 64px. Height always 48px (touch target).
asChildbooleanfalseRenders as the child element (e.g., Next.js Link) while keeping toolbar button styles.
aria-labelstringRequired accessible label.