Usage
Toolbar groups related actions in a docked or floating container. It is a composition wrapper: put Button, IconButton, an image, or another appropriately labelled custom control inside it. The toolbar does not duplicate the action’s state, tooltip, or keyboard behavior.
Docked toolbar
Use a docked toolbar at the bottom of the current app surface. It can be paired with a FAB when the FAB represents the primary action; the screen owns the placement and the action state.
Document canvas
The docked toolbar stays attached to the bottom of this surface.
Last action: None
import { useState } from 'react';
import { Fab, Toolbar } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iMoreHoriz } from '@udixio/icons-rounded-400/more_horiz';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
export default function ToolbarDockedReact() {
const [lastAction, setLastAction] = useState('None');
const actions = [
{
id: 'undo',
label: 'Undo',
icon: iUndo,
onClick: () => setLastAction('Undo'),
},
{
id: 'redo',
label: 'Redo',
icon: iRedo,
onClick: () => setLastAction('Redo'),
},
{
id: 'share',
label: 'Share document',
icon: iShare,
onClick: () => setLastAction('Share document'),
},
];
return (
<div className="relative flex min-h-80 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low">
<div className="flex flex-1 flex-col justify-center gap-2 p-6">
<p className="text-title-medium">Document canvas</p>
<p className="text-body-medium text-on-surface-variant">
The docked toolbar stays attached to the bottom of this surface.
</p>
<p
className="text-body-small text-on-surface-variant"
role="status"
aria-live="polite"
>
Last action: {lastAction}
</p>
</div>
<div className="relative">
<Fab
className="absolute -top-8 right-4 z-10"
label="Create document"
icon={iAdd}
onClick={() => setLastAction('Create document')}
/>
<Toolbar
accessibleLabel="Document actions"
actions={actions}
maxVisible={2}
more={{ label: 'More document actions', icon: iMoreHoriz }}
/>
</div>
</div>
);
}Document canvas
The docked toolbar stays attached to the bottom of this surface.
Last action: None
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Fab, Toolbar, type AngularToolbarAction } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iMoreHoriz } from '@udixio/icons-rounded-400/more_horiz';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
@Component({
selector: 'docs-toolbar-docked-angular',
standalone: true,
imports: [Fab, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div
class="relative flex min-h-80 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low"
>
<div class="flex flex-1 flex-col justify-center gap-2 p-6">
<p class="text-title-medium">Document canvas</p>
<p class="text-body-medium text-on-surface-variant">
The docked toolbar stays attached to the bottom of this surface.
</p>
<p
class="text-body-small text-on-surface-variant"
role="status"
aria-live="polite"
>
Last action: {{ lastAction() }}
</p>
</div>
<div class="relative">
<udx-fab
class="absolute -top-8 right-4 z-10"
label="Create document"
[icon]="addIcon"
(click)="setLastAction('Create document')"
/>
<udx-toolbar
accessibleLabel="Document actions"
[actions]="actions"
[maxVisible]="2"
[more]="moreOptions"
/>
</div>
</div>
`,
})
export class ToolbarDockedAngular {
protected readonly addIcon = iAdd;
protected readonly lastAction = signal('None');
protected readonly actions: readonly AngularToolbarAction[] = [
{
id: 'undo',
label: 'Undo',
icon: iUndo,
onClick: () => this.setLastAction('Undo'),
},
{
id: 'redo',
label: 'Redo',
icon: iRedo,
onClick: () => this.setLastAction('Redo'),
},
{
id: 'share',
label: 'Share document',
icon: iShare,
onClick: () => this.setLastAction('Share document'),
},
];
protected readonly moreOptions = {
label: 'More document actions',
icon: iMoreHoriz,
};
protected setLastAction(action: string): void {
this.lastAction.set(action);
}
}Document canvas
The docked toolbar stays attached to the bottom of this surface.
Last action: None
<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iMoreHoriz } from '@udixio/icons-rounded-400/more_horiz';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
import { Fab, Toolbar } from '@udixio/ui-svelte';
let lastAction = $state('None');
const setLastAction = (action: string) => {
lastAction = action;
};
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo, onClick: () => setLastAction('Undo') },
{ id: 'redo', label: 'Redo', icon: iRedo, onClick: () => setLastAction('Redo') },
{
id: 'share',
label: 'Share document',
icon: iShare,
onClick: () => setLastAction('Share document'),
},
];
const more = { label: 'More document actions', icon: iMoreHoriz };
</script>
<div class="relative flex min-h-80 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low">
<div class="flex flex-1 flex-col justify-center gap-2 p-6">
<p class="text-title-medium">Document canvas</p>
<p class="text-body-medium text-on-surface-variant">
The docked toolbar stays attached to the bottom of this surface.
</p>
<p class="text-body-small text-on-surface-variant" role="status" aria-live="polite">
Last action: {lastAction}
</p>
</div>
<div class="relative">
<Fab
class="absolute -top-8 right-4 z-10"
label="Create document"
icon={iAdd}
onclick={() => setLastAction('Create document')}
/>
<Toolbar accessibleLabel="Document actions" {actions} maxVisible={2} {more} />
</div>
</div>Combining toolbars
Two toolbars can coexist when they serve separate responsibilities: this example uses a floating selection group over a docked document group. Keep enough space between the groups, and collapse one group into overflow in compact layouts.
Document canvas
Keep each toolbar responsible for a distinct action group.
import { IconButton, Toolbar } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
export default function ToolbarCombinedReact() {
return (
<div className="relative flex min-h-96 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low">
<div className="relative flex flex-1 items-center justify-center p-6">
<div className="max-w-72 text-center">
<p className="text-title-medium">Document canvas</p>
<p className="text-body-medium text-on-surface-variant">
Keep each toolbar responsible for a distinct action group.
</p>
</div>
<Toolbar
variant="floating"
className="absolute left-1/2 top-6 -translate-x-1/2"
accessibleLabel="Selection actions"
>
<IconButton size="small" label="Undo selection" icon={iUndo} />
<IconButton size="small" label="Redo selection" icon={iRedo} />
<IconButton size="small" label="Copy selection" icon={iContentCopy} />
<IconButton size="small" label="Delete selection" icon={iDelete} />
</Toolbar>
</div>
<Toolbar accessibleLabel="Document actions">
<IconButton size="small" label="Add page" icon={iAdd} />
<IconButton size="small" label="Share document" icon={iShare} />
<IconButton size="small" label="Document settings" icon={iSettings} />
<IconButton size="small" label="Delete page" icon={iDelete} />
</Toolbar>
</div>
);
}Document canvas
Keep each toolbar responsible for a distinct action group.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton, Toolbar } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
@Component({
selector: 'docs-toolbar-combined-angular',
standalone: true,
imports: [IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div
class="relative flex min-h-96 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low"
>
<div class="relative flex flex-1 items-center justify-center p-6">
<div class="max-w-72 text-center">
<p class="text-title-medium">Document canvas</p>
<p class="text-body-medium text-on-surface-variant">
Keep each toolbar responsible for a distinct action group.
</p>
</div>
<udx-toolbar
variant="floating"
class="absolute left-1/2 top-6 -translate-x-1/2"
accessibleLabel="Selection actions"
>
<udx-icon-button size="small" label="Undo selection" [icon]="undoIcon" />
<udx-icon-button size="small" label="Redo selection" [icon]="redoIcon" />
<udx-icon-button size="small" label="Copy selection" [icon]="copyIcon" />
<udx-icon-button size="small" label="Delete selection" [icon]="deleteIcon" />
</udx-toolbar>
</div>
<udx-toolbar accessibleLabel="Document actions">
<udx-icon-button size="small" label="Add page" [icon]="addIcon" />
<udx-icon-button size="small" label="Share document" [icon]="shareIcon" />
<udx-icon-button size="small" label="Document settings" [icon]="settingsIcon" />
<udx-icon-button size="small" label="Delete page" [icon]="deleteIcon" />
</udx-toolbar>
</div>
`,
})
export class ToolbarCombinedAngular {
protected readonly addIcon = iAdd;
protected readonly copyIcon = iContentCopy;
protected readonly deleteIcon = iDelete;
protected readonly redoIcon = iRedo;
protected readonly settingsIcon = iSettings;
protected readonly shareIcon = iShare;
protected readonly undoIcon = iUndo;
}Document canvas
Keep each toolbar responsible for a distinct action group.
<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
import { IconButton, Toolbar } from '@udixio/ui-svelte';
</script>
<div class="relative flex min-h-96 w-full flex-col overflow-hidden rounded-2xl border border-outline bg-surface-container-low">
<div class="relative flex flex-1 items-center justify-center p-6">
<div class="max-w-72 text-center">
<p class="text-title-medium">Document canvas</p>
<p class="text-body-medium text-on-surface-variant">
Keep each toolbar responsible for a distinct action group.
</p>
</div>
<Toolbar
variant="floating"
class="absolute left-1/2 top-6 -translate-x-1/2"
accessibleLabel="Selection actions"
>
<IconButton size="small" label="Undo selection" icon={iUndo} />
<IconButton size="small" label="Redo selection" icon={iRedo} />
<IconButton size="small" label="Copy selection" icon={iContentCopy} />
<IconButton size="small" label="Delete selection" icon={iDelete} />
</Toolbar>
</div>
<Toolbar accessibleLabel="Document actions">
<IconButton size="small" label="Add page" icon={iAdd} />
<IconButton size="small" label="Share document" icon={iShare} />
<IconButton size="small" label="Document settings" icon={iSettings} />
<IconButton size="small" label="Delete page" icon={iDelete} />
</Toolbar>
</div>Floating toolbar
Use a floating toolbar when actions should remain visible in context. This example focuses on the default horizontal floating arrangement.
import { IconButton, Toolbar } from '@udixio/ui-react';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
export default function ToolbarFloatingReact() {
return (
<Toolbar variant="floating" accessibleLabel="Document tools">
<IconButton size="small" label="Share" icon={iShare} />
<IconButton size="small" label="Settings" icon={iSettings} />
</Toolbar>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton, Toolbar } from '@udixio/ui-angular';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
@Component({
selector: 'docs-toolbar-floating-angular',
standalone: true,
imports: [IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-toolbar variant="floating" accessibleLabel="Document tools">
<udx-icon-button size="small" label="Share" [icon]="shareIcon" />
<udx-icon-button size="small" label="Settings" [icon]="settingsIcon" />
</udx-toolbar>
`,
})
export class ToolbarFloatingAngular {
protected readonly shareIcon = iShare;
protected readonly settingsIcon = iSettings;
}<script lang="ts">
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { IconButton, Toolbar } from '@udixio/ui-svelte';
</script>
<Toolbar variant="floating" accessibleLabel="Document tools">
<IconButton size="small" label="Share" icon={iShare} />
<IconButton size="small" label="Settings" icon={iSettings} />
</Toolbar>Vibrant toolbar
Use color="vibrant" when the toolbar needs the expressive color treatment. This is a separate visual choice from the floating arrangement.
import { IconButton, Toolbar } from '@udixio/ui-react';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
export default function ToolbarVibrantReact() {
return (
<Toolbar
variant="floating"
color="vibrant"
accessibleLabel="Presentation tools"
>
<IconButton size="small" label="Share presentation" icon={iShare} />
<IconButton size="small" label="Presentation settings" icon={iSettings} />
</Toolbar>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton, Toolbar } from '@udixio/ui-angular';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
@Component({
selector: 'docs-toolbar-vibrant-angular',
standalone: true,
imports: [IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-toolbar
variant="floating"
color="vibrant"
accessibleLabel="Presentation tools"
>
<udx-icon-button size="small" label="Share presentation" [icon]="shareIcon" />
<udx-icon-button size="small" label="Presentation settings" [icon]="settingsIcon" />
</udx-toolbar>
`,
})
export class ToolbarVibrantAngular {
protected readonly shareIcon = iShare;
protected readonly settingsIcon = iSettings;
}<script lang="ts">
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { IconButton, Toolbar } from '@udixio/ui-svelte';
</script>
<Toolbar
variant="floating"
color="vibrant"
accessibleLabel="Presentation tools"
>
<IconButton size="small" label="Share presentation" icon={iShare} />
<IconButton size="small" label="Presentation settings" icon={iSettings} />
</Toolbar>Flexible slots
Toolbar is only a container, so its slots can hold buttons, icon buttons, images, or custom content. A filled button or filled icon button can give one action more emphasis without changing the toolbar itself.
import { Button, IconButton, Toolbar } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iShare } from '@udixio/icons-rounded-400/share';
export default function ToolbarSlotsReact() {
return (
<Toolbar accessibleLabel="Project actions">
<Button
label="Publish"
variant="filled"
size="small"
className="min-h-12"
/>
<IconButton size="small" label="Add" icon={iAdd} />
<IconButton size="small" label="Share" icon={iShare} />
<img
className="size-12 rounded-full object-cover"
src="https://picsum.photos/seed/udixio-toolbar/48/48"
alt="Project avatar"
/>
</Toolbar>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Button, IconButton, Toolbar } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iShare } from '@udixio/icons-rounded-400/share';
@Component({
selector: 'docs-toolbar-slots-angular',
standalone: true,
imports: [Button, IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-toolbar accessibleLabel="Project actions">
<udx-button
label="Publish"
variant="filled"
size="small"
class="min-h-12"
/>
<udx-icon-button size="small" label="Add" [icon]="addIcon" />
<udx-icon-button size="small" label="Share" [icon]="shareIcon" />
<img
class="size-12 rounded-full object-cover"
src="https://picsum.photos/seed/udixio-toolbar/48/48"
alt="Project avatar"
/>
</udx-toolbar>
`,
})
export class ToolbarSlotsAngular {
protected readonly addIcon = iAdd;
protected readonly shareIcon = iShare;
}<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iShare } from '@udixio/icons-rounded-400/share';
import { Button, IconButton, Toolbar } from '@udixio/ui-svelte';
</script>
<Toolbar accessibleLabel="Project actions">
<Button label="Publish" variant="filled" size="small" class="min-h-12" />
<IconButton size="small" label="Add" icon={iAdd} />
<IconButton size="small" label="Share" icon={iShare} />
<img
class="size-12 rounded-full object-cover"
src="https://picsum.photos/seed/udixio-toolbar/48/48"
alt="Project avatar"
/>
</Toolbar>Vertical toolbar
Vertical floating toolbars suit spacious layouts with a secondary action group. Material 3 does not recommend this orientation in compact layouts; prefer an overflow action when width is limited.
Quick actions
Use this spacious arrangement for contextual actions.
import { IconButton, Toolbar } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
export default function ToolbarVerticalReact() {
return (
<div className="flex min-h-72 w-full items-center justify-end rounded-2xl border border-outline bg-surface-container-low p-6">
<div className="flex items-center gap-4">
<div className="max-w-48">
<p className="text-title-medium">Quick actions</p>
<p className="text-body-small text-on-surface-variant">
Use this spacious arrangement for contextual actions.
</p>
</div>
<Toolbar
variant="floating"
orientation="vertical"
accessibleLabel="Quick actions"
>
<IconButton size="small" label="Add" icon={iAdd} />
<IconButton size="small" label="Share" icon={iShare} />
<IconButton size="small" label="Settings" icon={iSettings} />
</Toolbar>
</div>
</div>
);
}Quick actions
Use this spacious arrangement for contextual actions.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton, Toolbar } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
@Component({
selector: 'docs-toolbar-vertical-angular',
standalone: true,
imports: [IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div
class="flex min-h-72 w-full items-center justify-end rounded-2xl border border-outline bg-surface-container-low p-6"
>
<div class="flex items-center gap-4">
<div class="max-w-48">
<p class="text-title-medium">Quick actions</p>
<p class="text-body-small text-on-surface-variant">
Use this spacious arrangement for contextual actions.
</p>
</div>
<udx-toolbar
variant="floating"
orientation="vertical"
accessibleLabel="Quick actions"
>
<udx-icon-button size="small" label="Add" [icon]="addIcon" />
<udx-icon-button size="small" label="Share" [icon]="shareIcon" />
<udx-icon-button size="small" label="Settings" [icon]="settingsIcon" />
</udx-toolbar>
</div>
</div>
`,
})
export class ToolbarVerticalAngular {
protected readonly addIcon = iAdd;
protected readonly shareIcon = iShare;
protected readonly settingsIcon = iSettings;
}Quick actions
Use this spacious arrangement for contextual actions.
<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { IconButton, Toolbar } from '@udixio/ui-svelte';
</script>
<div class="flex min-h-72 w-full items-center justify-end rounded-2xl border border-outline bg-surface-container-low p-6">
<div class="flex items-center gap-4">
<div class="max-w-48">
<p class="text-title-medium">Quick actions</p>
<p class="text-body-small text-on-surface-variant">
Use this spacious arrangement for contextual actions.
</p>
</div>
<Toolbar variant="floating" orientation="vertical" accessibleLabel="Quick actions">
<IconButton size="small" label="Add" icon={iAdd} />
<IconButton size="small" label="Share" icon={iShare} />
<IconButton size="small" label="Settings" icon={iSettings} />
</Toolbar>
</div>
</div>Overflow actions
Pass an actions model when the toolbar should manage visibility for you. maxVisible keeps the first actions visible and moves the rest into a generated menu; set pinned: true on an action that must remain visible. The example uses several editing actions so the generated menu has meaningful content.
The generated menu uses automatic placement by default: it opens below a horizontal toolbar in the upper half of the viewport and above it in the lower half; vertical toolbars use the equivalent right/left rule. Use morePosition to force a specific placement when needed.
import { Toolbar } from '@udixio/ui-react';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy formatting', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Editor settings', icon: iSettings },
{ id: 'delete', label: 'Delete draft', icon: iDelete },
];
export default function ToolbarOverflowReact() {
return (
<Toolbar
variant="floating"
accessibleLabel="Editing actions"
actions={actions}
maxVisible={3}
more={{ label: 'More editing actions' }}
/>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Toolbar } from '@udixio/ui-angular';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy formatting', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Editor settings', icon: iSettings },
{ id: 'delete', label: 'Delete draft', icon: iDelete },
];
@Component({
selector: 'docs-toolbar-overflow-angular',
standalone: true,
imports: [Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<udx-toolbar
variant="floating"
accessibleLabel="Editing actions"
[actions]="actions"
[maxVisible]="3"
[more]="moreOptions"
/>
`,
})
export class ToolbarOverflowAngular {
protected readonly actions = actions;
protected readonly moreOptions = { label: 'More editing actions' };
}<script lang="ts">
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
import { Toolbar } from '@udixio/ui-svelte';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy formatting', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Editor settings', icon: iSettings },
{ id: 'delete', label: 'Delete draft', icon: iDelete },
];
const more = { label: 'More editing actions' };
</script>
<Toolbar
variant="floating"
accessibleLabel="Editing actions"
{actions}
maxVisible={3}
{more}
/>Responsive overflow
Use responsive when the visible action count should follow the toolbar’s actual width instead of a fixed maxVisible value. Resize the example to see actions move into or out of the generated overflow menu.
Resize this container to move actions into the overflow menu.
import { Toolbar } from '@udixio/ui-react';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Settings', icon: iSettings },
{ id: 'delete', label: 'Delete', icon: iDelete },
{ id: 'add', label: 'Add', icon: iAdd },
];
export default function ToolbarResponsiveReact() {
return (
<div className="w-full max-w-xs resize-x overflow-x-auto rounded-2xl border border-outline bg-surface-container-low">
<Toolbar
accessibleLabel="Responsive editing actions"
actions={actions}
responsive
itemWidth={48}
more={{ label: 'More editing actions' }}
/>
<p className="px-4 pb-3 text-body-small text-on-surface-variant">
Resize this container to move actions into the overflow menu.
</p>
</div>
);
}Resize this container to move actions into the overflow menu.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Toolbar } from '@udixio/ui-angular';
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Settings', icon: iSettings },
{ id: 'delete', label: 'Delete', icon: iDelete },
{ id: 'add', label: 'Add', icon: iAdd },
];
@Component({
selector: 'docs-toolbar-responsive-angular',
standalone: true,
imports: [Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div
class="w-full max-w-xs resize-x overflow-x-auto rounded-2xl border border-outline bg-surface-container-low"
>
<udx-toolbar
accessibleLabel="Responsive editing actions"
[actions]="actions"
responsive
[itemWidth]="48"
[more]="moreOptions"
/>
<p class="px-4 pb-3 text-body-small text-on-surface-variant">
Resize this container to move actions into the overflow menu.
</p>
</div>
`,
})
export class ToolbarResponsiveAngular {
protected readonly actions = actions;
protected readonly moreOptions = { label: 'More editing actions' };
}Resize this container to move actions into the overflow menu.
<script lang="ts">
import { iAdd } from '@udixio/icons-rounded-400/add';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iRedo } from '@udixio/icons-rounded-400/redo';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iUndo } from '@udixio/icons-rounded-400/undo';
import { Toolbar } from '@udixio/ui-svelte';
const actions = [
{ id: 'undo', label: 'Undo', icon: iUndo },
{ id: 'redo', label: 'Redo', icon: iRedo },
{ id: 'copy', label: 'Copy', icon: iContentCopy },
{ id: 'share', label: 'Share', icon: iShare },
{ id: 'settings', label: 'Settings', icon: iSettings },
{ id: 'delete', label: 'Delete', icon: iDelete },
{ id: 'add', label: 'Add', icon: iAdd },
];
const more = { label: 'More editing actions' };
</script>
<div class="w-full max-w-xs resize-x overflow-x-auto rounded-2xl border border-outline bg-surface-container-low">
<Toolbar
accessibleLabel="Responsive editing actions"
{actions}
responsive
itemWidth={48}
{more}
/>
<p class="px-4 pb-3 text-body-small text-on-surface-variant">
Resize this container to move actions into the overflow menu.
</p>
</div>Custom overflow trigger
The generated menu stays the same when its trigger needs a different treatment. Use renderMore, moreTemplate, or the equivalent framework-specific slot with a custom button to replace the default icon button while keeping the automatic action management.
import { IconButton, Toolbar } from '@udixio/ui-react';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iMoreVert } from '@udixio/icons-rounded-400/more_vert';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iSettings } from '@udixio/icons-rounded-400/settings';
const actions = [
{ id: 'share', label: 'Share presentation', icon: iShare },
{ id: 'settings', label: 'Presentation settings', icon: iSettings },
{ id: 'copy', label: 'Copy presentation link', icon: iContentCopy },
{ id: 'delete', label: 'Delete presentation', icon: iDelete },
];
export default function ToolbarCustomOverflowReact() {
return (
<Toolbar
variant="floating"
accessibleLabel="Presentation tools"
actions={actions}
maxVisible={1}
more={{ label: 'More presentation tools' }}
renderMore={({ label, ariaExpanded, ariaHasPopup, onClick }) => (
<IconButton
size="small"
label={label}
icon={iMoreVert}
tooltip={false}
variant="filled"
aria-haspopup={ariaHasPopup}
aria-expanded={ariaExpanded}
onClick={onClick}
/>
)}
/>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { IconButton, Toolbar } from '@udixio/ui-angular';
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iMoreVert } from '@udixio/icons-rounded-400/more_vert';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iSettings } from '@udixio/icons-rounded-400/settings';
const actions = [
{ id: 'share', label: 'Share presentation', icon: iShare },
{ id: 'settings', label: 'Presentation settings', icon: iSettings },
{ id: 'copy', label: 'Copy presentation link', icon: iContentCopy },
{ id: 'delete', label: 'Delete presentation', icon: iDelete },
];
@Component({
selector: 'docs-toolbar-custom-overflow-angular',
standalone: true,
imports: [IconButton, Toolbar],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<ng-template
#customMore
let-label="label"
let-ariaHasPopup="ariaHasPopup"
let-ariaExpanded="ariaExpanded"
let-toggle="toggle"
>
<udx-icon-button
size="small"
[label]="label"
[icon]="moreIcon"
[tooltip]="false"
variant="filled"
[aria-haspopup]="ariaHasPopup"
[aria-expanded]="ariaExpanded"
(click)="toggle()"
/>
</ng-template>
<udx-toolbar
variant="floating"
accessibleLabel="Presentation tools"
[actions]="actions"
[maxVisible]="1"
[more]="moreOptions"
[moreTemplate]="customMore"
/>
`,
})
export class ToolbarCustomOverflowAngular {
protected readonly actions = actions;
protected readonly moreOptions = { label: 'More presentation tools' };
protected readonly moreIcon = iMoreVert;
}<script lang="ts">
import { iContentCopy } from '@udixio/icons-rounded-400/content_copy';
import { iDelete } from '@udixio/icons-rounded-400/delete';
import { iMoreVert } from '@udixio/icons-rounded-400/more_vert';
import { iShare } from '@udixio/icons-rounded-400/share';
import { iSettings } from '@udixio/icons-rounded-400/settings';
import { IconButton, Toolbar } from '@udixio/ui-svelte';
const actions = [
{ id: 'share', label: 'Share presentation', icon: iShare },
{ id: 'settings', label: 'Presentation settings', icon: iSettings },
{ id: 'copy', label: 'Copy presentation link', icon: iContentCopy },
{ id: 'delete', label: 'Delete presentation', icon: iDelete },
];
const more = { label: 'More presentation tools' };
</script>
{#snippet customMore({ label, ariaHasPopup, ariaExpanded, toggle })}
<IconButton
size="small"
{label}
icon={iMoreVert}
tooltip={false}
variant="filled"
aria-haspopup={ariaHasPopup}
aria-expanded={ariaExpanded}
onclick={toggle}
/>
{/snippet}
<Toolbar
variant="floating"
accessibleLabel="Presentation tools"
{actions}
maxVisible={1}
{more}
moreTemplate={customMore}
/>Guidelines
- Toolbars are 64dp high by default; use
IconButton size="small"for the 48dp toolbar slots and keep every interactive child at or above that target. - Docked toolbars use 16dp edge padding and 8dp minimum spacing between actions; compact widths distribute the actions evenly.
- Floating toolbars use compact 8dp internal padding and 4dp between actions.
- Keep a horizontal floating toolbar at least 16dp from surrounding edges and a vertical floating toolbar at least 24dp away.
- Docked toolbars belong at the bottom of the surface and should not be shown simultaneously with a navigation bar.
- Avoid multiple toolbars in compact layouts. Use overflow when actions do not fit and keep the overflow action in its logical position in RTL layouts.
Accessibility
The root exposes role="toolbar". Provide accessibleLabel, or connect an external heading with aria-labelledby, so assistive technology can identify the action group. In actions mode, the generated trigger exposes its menu relationship and the menu items reuse each action’s accessible label. In composition mode, children own focus, activation, pressed state, and labels. In particular, an IconButton should always receive a meaningful label.
This wrapper intentionally does not implement roving focus or arrow-key navigation. If a product needs a composite keyboard model, use a dedicated interaction pattern around the child controls rather than assuming that every toolbar is a single composite widget.