Interactive Toolbar
Building this toolbar started with a simple frustration โ I was tired of seeing toolbars that felt disconnected from their actions. While working on a Knowledge Base project, I noticed users struggling to find basic formatting controls. They were there, but not where users expected them to be, making the experience less intuitive.
Play around with the toolbar below to see how it appears at different screen positions.
Getting the grouping right was trickier than I anticipated. In the early versions, there were no separators, making it hard for users to mentally chunk related actions. Adding those subtle dividers made a surprising difference. Suddenly, users could navigate the toolbar much more efficiently, and their feedback was overwhelmingly positive.
One detail I'm particularly happy with is how the hover states work. I wanted them to be subtle enough not to be distracting
, yet clear enough to indicate interactivity. It took several iterations to find that sweet spot.
This component (with different layouts) has since become a key component in our projects, consistently enhancing the user experience without overwhelming them.
Overview
Modern applications require intuitive command interfaces. This toolbar provides:
- Flexible layout options
- Customizable actions
- Responsive design
- Grouping capabilities
Use Cases
- Text editors
- Media controls
- Document manipulation
- Command centers
Usage
import {Bell, Bold, FolderOpen, Heart, Inbox, Italic, MessageCircle, Strikethrough} from "lucide-react";
import {
Toolbar,
ToolbarButton,
ToolbarButtonLink,
ToolbarLink,
ToolbarPortal,
ToolbarSeparator,
ToolbarToggleGroup,
ToolbarToggleItem,
} from "@/components/ui/toolbar";
const items = [
{
id: 0,
type: "link",
label: "Notifications",
icon: Bell,
},
{
id: 1,
type: "item",
label: "Inbox",
icon: Inbox,
},
{
id: 2,
type: "separator",
},
{
id: 3,
type: "item",
label: "Likes",
icon: Heart,
},
{
id: 4,
type: "item",
label: "Files",
icon: FolderOpen,
},
];
const ToolbarComponent = () => {
return (
<ToolbarPortal>
<Toolbar orientation="horizontal" position={"bottom"}>
{items.map((item, index) =>
item.type === "item" ? (
<ToolbarButton key={item.id}>
{item?.icon ? <item.icon size={16} /> : null}
</ToolbarButton>
) : item.type === "link" ? (
<ToolbarButtonLink href={""} key={item.id}>
{item?.icon ? <item.icon size={16} /> : null}
</ToolbarButtonLink>
) : (
<ToolbarSeparator key={item.id} />
)
)}
<ToolbarSeparator />
<ToolbarButton size={"text"} label="Comments" variant={"destructive"}>
<MessageCircle size={16} />
</ToolbarButton>
<ToolbarSeparator />
<ToolbarToggleGroup type={"single"}>
<ToolbarToggleItem value="bold">
<Bold size={16} />
</ToolbarToggleItem>
<ToolbarToggleItem value="italic">
<Italic size={16} />
</ToolbarToggleItem>
<ToolbarToggleItem value="strike">
<Strikethrough size={16} />
</ToolbarToggleItem>
</ToolbarToggleGroup>
<ToolbarSeparator />
<ToolbarLink>Edited 2 hours ago</ToolbarLink>
</Toolbar>
</ToolbarPortal>
);
};
export default ToolbarComponent;
Installation
npm install @radix-ui/react-toolbar @radix-ui/react-portal class-variance-authority framer-motion
API
type ToolbarProps = {
orientation: "horizontal" | "vertical";
position: "top" | "bottom" | "left" | "right";
};