Cnippet

Toolbar

Buttons 44

About

A container for grouping related actions into a single keyboard-navigable bar, built on Base UI's Toolbar primitive. Ships Toolbar, ToolbarButton, ToolbarLink, ToolbarInput, ToolbarGroup and ToolbarSeparator. Each part uses the render prop so it can compose with buttons, toggle groups and inputs while keeping a single roving-tabindex focus model. Demos compose it with the Button, Tooltip and ToggleGroup components (shipped alongside).

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Toolbar to your project and fits it to your theme.

Code

How Toolbar is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import {
  AlignCenterIcon,
  AlignJustifyIcon,
  AlignLeftIcon,
  AlignRightIcon,
  BoldIcon,
  ItalicIcon,
  ListIcon,
  ListOrderedIcon,
  RedoIcon,
  StrikethroughIcon,
  UnderlineIcon,
  UndoIcon,
} from "lucide-react";
import { Button } from "@/components/ui/cnippet-toolbar-utils/button";
import {
  ToggleGroup,
  ToggleGroupItem,
} from "@/components/ui/cnippet-toolbar-utils/toggle-group";
import {
  Toolbar,
  ToolbarButton,
  ToolbarGroup,
  ToolbarSeparator,
} from "@/components/ui/cnippet-toolbar";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/cnippet-toolbar-utils/tooltip";

const formatTools = [
  { icon: BoldIcon, label: "Bold", shortcut: "⌘B" },
  { icon: ItalicIcon, label: "Italic", shortcut: "⌘I" },
  { icon: UnderlineIcon, label: "Underline", shortcut: "⌘U" },
  { icon: StrikethroughIcon, label: "Strikethrough", shortcut: "⌘⇧X" },
] as const;

const alignTools = [
  { icon: AlignLeftIcon, label: "Align left", value: "left" },
  { icon: AlignCenterIcon, label: "Align center", value: "center" },
  { icon: AlignRightIcon, label: "Align right", value: "right" },
  { icon: AlignJustifyIcon, label: "Justify", value: "justify" },
] as const;

const listTools = [
  { icon: ListIcon, label: "Bullet list" },
  { icon: ListOrderedIcon, label: "Numbered list" },
] as const;

export default function ToolbarRichText() {
  return (
    <TooltipProvider>
      <Toolbar>
        <ToolbarGroup>
          <Tooltip>
            <TooltipTrigger
              render={
                <ToolbarButton render={<Button size="icon" variant="ghost" />}>
                  <UndoIcon />
                </ToolbarButton>
              }
            />
            <TooltipContent>Undo (⌘Z)</TooltipContent>
          </Tooltip>
          <Tooltip>
            <TooltipTrigger
              render={
                <ToolbarButton render={<Button size="icon" variant="ghost" />}>
                  <RedoIcon />
                </ToolbarButton>
              }
            />
            <TooltipContent>Redo (⌘⇧Z)</TooltipContent>
          </Tooltip>
        </ToolbarGroup>

        <ToolbarSeparator />

        <ToggleGroup className="border-none p-0">
          {formatTools.map(({ icon: Icon, label, shortcut }) => (
            <Tooltip key={label}>
              <TooltipTrigger
                render={
                  <ToolbarButton
                    aria-label={label}
                    render={<ToggleGroupItem value={label.toLowerCase()} />}
                  >
                    <Icon />
                  </ToolbarButton>
                }
              />
              <TooltipContent>
                {label}
                <span className="ml-1.5 text-muted-foreground">{shortcut}</span>
              </TooltipContent>
            </Tooltip>
          ))}
        </ToggleGroup>

        <ToolbarSeparator />

        <ToggleGroup className="border-none p-0" defaultValue={["left"]}>
          {alignTools.map(({ icon: Icon, label, value }) => (
            <Tooltip key={value}>
              <TooltipTrigger
                render={
                  <ToolbarButton
                    aria-label={label}
                    render={<ToggleGroupItem value={value} />}
                  >
                    <Icon />
                  </ToolbarButton>
                }
              />
              <TooltipContent>{label}</TooltipContent>
            </Tooltip>
          ))}
        </ToggleGroup>

        <ToolbarSeparator />

        <ToolbarGroup>
          {listTools.map(({ icon: Icon, label }) => (
            <Tooltip key={label}>
              <TooltipTrigger
                render={
                  <ToolbarButton
                    aria-label={label}
                    render={<Button size="icon" variant="ghost" />}
                  >
                    <Icon />
                  </ToolbarButton>
                }
              />
              <TooltipContent>{label}</TooltipContent>
            </Tooltip>
          ))}
        </ToolbarGroup>
      </Toolbar>
    </TooltipProvider>
  );
}

Dependencies

More by Cnippet

View all
  • Team

    Team

    1.3K
  • Davincho Hero-1

    Davincho Hero-1

    683
  • Aero Hero-3

    Aero Hero-3

    559
  • Features

    Features

    510
  • Random Letter Swap Navigation

    Random Letter Swap Navigation

    487
  • Services with Animated Hover Modal

    Services with Animated Hover Modal

    465
  • Blogs

    Blogs

    396
  • Aero Hero-1

    Aero Hero-1

    356

More in Buttons

View all
  • Button Save

    Button Save

    46
  • Button

    Button

    20
  • Eclipse Button

    Eclipse Button

    5
  • Button

    Button

    6
  • Button

    Button

    14
  • Button Group

    Button Group

    37
  • Button

    Button

    32
  • Split Button

    Split Button

    32