Toolbar
A row of grouped controls with a toolbar role and roving keyboard focus.
Basic
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { Menu, MenuContent, MenuItem } from "@makeplane/propel/components/menu";
import {
Toolbar,
ToolbarButton,
ToolbarGroup,
ToolbarMenuTrigger,
ToolbarSeparator,
ToolbarToggle,
ToolbarToggleGroup,
} from "@makeplane/propel/components/toolbar";
import {
AlignCenter,
AlignLeft,
AlignRight,
Bold,
Code,
Image,
Italic,
Link,
List,
ListChecks,
ListOrdered,
MessageSquare,
Quote,
Strikethrough,
Table,
Underline,
} from "lucide-react";
const TEXT_STYLES = ["Paragraph", "Heading 1", "Heading 2", "Heading 3"];
const FONTS = ["Sans", "Serif", "Mono"];
export default function BasicDemo() {
return (
<Toolbar elevation="raised" density="compact">
<Menu>
<ToolbarMenuTrigger aria-label="Text style" label="Text" />
<MenuContent>
{TEXT_STYLES.map((style) => (
<MenuItem key={style} label={style} />
))}
</MenuContent>
</Menu>
<Menu>
<ToolbarMenuTrigger aria-label="Font" label="Aa" />
<MenuContent>
{FONTS.map((font) => (
<MenuItem key={font} label={font} />
))}
</MenuContent>
</Menu>
<ToolbarButton aria-label="Comment" icon={<Icon icon={MessageSquare} />} />
<ToolbarSeparator />
<ToolbarGroup aria-label="Text formatting">
<ToolbarToggle aria-label="Bold" icon={<Icon icon={Bold} />} />
<ToolbarToggle aria-label="Italic" icon={<Icon icon={Italic} />} />
<ToolbarToggle aria-label="Underline" icon={<Icon icon={Underline} />} />
<ToolbarToggle aria-label="Strikethrough" icon={<Icon icon={Strikethrough} />} />
</ToolbarGroup>
<ToolbarSeparator />
<ToolbarToggleGroup defaultValue={["left"]} aria-label="Text alignment">
<ToolbarToggle value="left" aria-label="Align left" icon={<Icon icon={AlignLeft} />} />
<ToolbarToggle
value="center"
aria-label="Align center"
icon={<Icon icon={AlignCenter} />}
/>
<ToolbarToggle value="right" aria-label="Align right" icon={<Icon icon={AlignRight} />} />
</ToolbarToggleGroup>
<ToolbarSeparator />
<ToolbarGroup aria-label="Lists">
<ToolbarToggle aria-label="Bullet list" icon={<Icon icon={List} />} />
<ToolbarToggle aria-label="Numbered list" icon={<Icon icon={ListOrdered} />} />
<ToolbarToggle aria-label="Checklist" icon={<Icon icon={ListChecks} />} />
</ToolbarGroup>
<ToolbarSeparator />
<ToolbarGroup aria-label="Blocks">
<ToolbarToggle aria-label="Quote" icon={<Icon icon={Quote} />} />
<ToolbarToggle aria-label="Code block" icon={<Icon icon={Code} />} />
<ToolbarButton aria-label="Insert table" icon={<Icon icon={Table} />} />
</ToolbarGroup>
<ToolbarSeparator />
<ToolbarButton aria-label="Insert link" icon={<Icon icon={Link} />} />
<ToolbarButton aria-label="Insert image" icon={<Icon icon={Image} />} />
</Toolbar>
);
}Elevations
raised draws its own card (border and shadow) so the toolbar can float over content; flat draws no surface and sits flush inside an existing bar.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import {
Toolbar,
ToolbarButton,
ToolbarGroup,
ToolbarSeparator,
ToolbarToggle,
} from "@makeplane/propel/components/toolbar";
import type { ToolbarElevation } from "@makeplane/propel/components/toolbar";
import { Bold, Italic, Link, Underline } from "lucide-react";
function Formatting({ elevation }: { elevation: ToolbarElevation }) {
return (
<Toolbar elevation={elevation} density="compact" aria-label="Text formatting">
<ToolbarGroup aria-label="Text formatting">
<ToolbarToggle aria-label="Bold" icon={<Icon icon={Bold} />} />
<ToolbarToggle aria-label="Italic" icon={<Icon icon={Italic} />} />
<ToolbarToggle aria-label="Underline" icon={<Icon icon={Underline} />} />
</ToolbarGroup>
<ToolbarSeparator />
<ToolbarButton aria-label="Insert link" icon={<Icon icon={Link} />} />
</Toolbar>
);
}
export default function ElevationsDemo() {
return (
<div className="flex flex-col gap-6">
<Formatting elevation="raised" />
<Formatting elevation="flat" />
</div>
);
}Densities
density sets the control hit targets: compact packs them to 24px, comfortable gives them 28px.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import {
Toolbar,
ToolbarButton,
ToolbarGroup,
ToolbarSeparator,
ToolbarToggle,
} from "@makeplane/propel/components/toolbar";
import type { ToolbarDensity } from "@makeplane/propel/components/toolbar";
import { Bold, Italic, Link, Underline } from "lucide-react";
function Formatting({ density }: { density: ToolbarDensity }) {
return (
<Toolbar elevation="raised" density={density} aria-label="Text formatting">
<ToolbarGroup aria-label="Text formatting">
<ToolbarToggle aria-label="Bold" icon={<Icon icon={Bold} />} />
<ToolbarToggle aria-label="Italic" icon={<Icon icon={Italic} />} />
<ToolbarToggle aria-label="Underline" icon={<Icon icon={Underline} />} />
</ToolbarGroup>
<ToolbarSeparator />
<ToolbarButton aria-label="Insert link" icon={<Icon icon={Link} />} />
</Toolbar>
);
}
export default function DensitiesDemo() {
return (
<div className="flex flex-col gap-6">
<Formatting density="compact" />
<Formatting density="comfortable" />
</div>
);
}With filter
ToolbarInput is an inline filter box that joins the roving tab order, its height tracking the toolbar’s density like every other item.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import {
Toolbar,
ToolbarGroup,
ToolbarInput,
ToolbarSeparator,
ToolbarToggle,
} from "@makeplane/propel/components/toolbar";
import { Bold, Italic } from "lucide-react";
export default function WithFilterDemo() {
return (
<Toolbar elevation="raised" density="compact" aria-label="Issue actions">
<ToolbarInput aria-label="Filter issues" placeholder="Filter…" />
<ToolbarSeparator />
<ToolbarGroup aria-label="Text formatting">
<ToolbarToggle aria-label="Bold" icon={<Icon icon={Bold} />} />
<ToolbarToggle aria-label="Italic" icon={<Icon icon={Italic} />} />
</ToolbarGroup>
</Toolbar>
);
}With tooltips
Toolbar controls are icon-only, so pair each with a Tooltip naming it (plus a dimmed shortcut hint). A shared TooltipProvider keeps open and close timing consistent across the bar.
Show codeHide code
import { Icon } from "@makeplane/propel/components/icon";
import { Toolbar, ToolbarToggle } from "@makeplane/propel/components/toolbar";
import { Tooltip, TooltipProvider } from "@makeplane/propel/components/tooltip";
import { Bold, Italic, Underline } from "lucide-react";
export default function WithTooltipsDemo() {
return (
<TooltipProvider>
<Toolbar elevation="raised" density="compact" aria-label="Text formatting">
<Tooltip label="Bold" shortcut="⌘ B">
<ToolbarToggle aria-label="Bold" aria-keyshortcuts="Meta+B" icon={<Icon icon={Bold} />} />
</Tooltip>
<Tooltip label="Italic" shortcut="⌘ I">
<ToolbarToggle
aria-label="Italic"
aria-keyshortcuts="Meta+I"
icon={<Icon icon={Italic} />}
/>
</Tooltip>
<Tooltip label="Underline" shortcut="⌘ U">
<ToolbarToggle
aria-label="Underline"
aria-keyshortcuts="Meta+U"
icon={<Icon icon={Underline} />}
/>
</Tooltip>
</Toolbar>
</TooltipProvider>
);
}Installation
import {
Toolbar,
ToolbarButton,
ToolbarGroup,
ToolbarMenuTrigger,
ToolbarSeparator,
ToolbarToggle,
ToolbarToggleGroup,
} from "@makeplane/propel/components/toolbar";
Props
Toolbar
| Prop | Type | Required | Description |
|---|---|---|---|
| render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | No | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| elevation | "raised" | "flat" | Yes | |
| density | "compact" | "comfortable" | Yes |
ToolbarButton
| Prop | Type | Required | Description |
|---|---|---|---|
| render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | No | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| density | "compact" | "comfortable" | No | Density override; defaults to the surrounding `Toolbar`'s density. |
| icon | ReactNode | Yes | Icon element rendered inside the toolbar button. |
ToolbarToggle
| Prop | Type | Required | Description |
|---|---|---|---|
| density | "compact" | "comfortable" | No | Density override; defaults to the surrounding `Toolbar`'s density. |
| icon | ReactNode | Yes | Icon element rendered inside the toolbar toggle. |
| render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}> | No | Custom render for the underlying styled toolbar button. |
ToolbarMenuTrigger
| Prop | Type | Required | Description |
|---|---|---|---|
| render | ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, MenuTriggerState> | No | Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| label | string | Yes | Visible menu-trigger label. |