Search

Search the site

All components

Editor Sidebar

VS Code-style activity rail with switchable sidebar views. Composable primitives for explorer, search, extensions, or any custom panel.

Default
Basic activity rail with three switchable views
Overview

Project overview, recent activity, and quick stats.

1"use client";
2
3import { useState } from "react";
4import { BookOpen, LayoutDashboard, Settings } from "lucide-react";
5import {
6 EditorSidebar,
7 EditorSidebarRail,
8 EditorSidebarTrigger,
9 EditorSidebarContent,
10 EditorSidebarPanel,
11} from "@/registry/ui";
12
13const panelCopy: Record<string, string> = {
14 overview: "Project overview, recent activity, and quick stats.",
15 settings: "Workspace defaults, themes, and notification rules.",
16 help: "Documentation links, shortcuts, and support resources.",
17};
18
19export function EditorSidebarDefaultExample() {
20 const [active, setActive] = useState("overview");
21
22 return (
23 <div className="mx-auto h-[360px] w-full max-w-md overflow-hidden rounded-lg border border-border">
24 <EditorSidebar
25 value={active}
26 onValueChange={setActive}
27 variant="bordered"
28 className="h-full"
29 >
30 <EditorSidebarRail>
31 <EditorSidebarTrigger
32 value="overview"
33 icon={<LayoutDashboard />}
34 label="Overview"
35 />
36 <EditorSidebarTrigger
37 value="settings"
38 icon={<Settings />}
39 label="Settings"
40 />
41 <EditorSidebarTrigger value="help" icon={<BookOpen />} label="Help" />
42 </EditorSidebarRail>
43 <EditorSidebarContent>
44 <EditorSidebarPanel value="overview" title="Overview">
45 <p className="text-sm text-muted-foreground">
46 {panelCopy.overview}
47 </p>
48 </EditorSidebarPanel>
49 <EditorSidebarPanel value="settings" title="Settings">
50 <p className="text-sm text-muted-foreground">
51 {panelCopy.settings}
52 </p>
53 </EditorSidebarPanel>
54 <EditorSidebarPanel value="help" title="Help">
55 <p className="text-sm text-muted-foreground">{panelCopy.help}</p>
56 </EditorSidebarPanel>
57 </EditorSidebarContent>
58 </EditorSidebar>
59 </div>
60 );
61}
With badges
Rail triggers with dot and count badges
Inbox

2 unread threads waiting for review.

1"use client";
2
3import { useState } from "react";
4import { Bell, Inbox, MessageSquare } from "lucide-react";
5import {
6 EditorSidebar,
7 EditorSidebarRail,
8 EditorSidebarTrigger,
9 EditorSidebarContent,
10 EditorSidebarPanel,
11} from "@/registry/ui";
12
13export function EditorSidebarBadgesExample() {
14 const [active, setActive] = useState("inbox");
15
16 return (
17 <div className="mx-auto h-[360px] w-full max-w-md overflow-hidden rounded-lg border border-border">
18 <EditorSidebar
19 value={active}
20 onValueChange={setActive}
21 variant="default"
22 className="h-full"
23 >
24 <EditorSidebarRail>
25 <EditorSidebarTrigger
26 value="inbox"
27 icon={<Inbox />}
28 label="Inbox"
29 badge
30 />
31 <EditorSidebarTrigger
32 value="messages"
33 icon={<MessageSquare />}
34 label="Messages"
35 />
36 <EditorSidebarTrigger
37 value="alerts"
38 icon={<Bell />}
39 label="Alerts"
40 badge={
41 <span className="flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground">
42 3
43 </span>
44 }
45 />
46 </EditorSidebarRail>
47 <EditorSidebarContent>
48 <EditorSidebarPanel value="inbox" title="Inbox">
49 <p className="text-sm text-muted-foreground">
50 2 unread threads waiting for review.
51 </p>
52 </EditorSidebarPanel>
53 <EditorSidebarPanel value="messages" title="Messages">
54 <p className="text-sm text-muted-foreground">
55 Direct messages from your team.
56 </p>
57 </EditorSidebarPanel>
58 <EditorSidebarPanel value="alerts" title="Alerts">
59 <p className="text-sm text-muted-foreground">
60 3 deployment alerts require attention.
61 </p>
62 </EditorSidebarPanel>
63 </EditorSidebarContent>
64 </EditorSidebar>
65 </div>
66 );
67}
Sizes
Small and large rail sizing

Small

Overview

Compact rail.

Large

Overview

Large rail.

1"use client";
2
3import { useState } from "react";
4import { LayoutDashboard, Settings } from "lucide-react";
5import {
6 EditorSidebar,
7 EditorSidebarRail,
8 EditorSidebarTrigger,
9 EditorSidebarContent,
10 EditorSidebarPanel,
11} from "@/registry/ui";
12
13export function EditorSidebarSizesExample() {
14 const [activeSm, setActiveSm] = useState("overview");
15 const [activeLg, setActiveLg] = useState("overview");
16
17 return (
18 <div className="mx-auto grid w-full max-w-3xl gap-6 md:grid-cols-2">
19 <div>
20 <p className="mb-2 text-xs font-medium text-muted-foreground">Small</p>
21 <div className="h-[280px] overflow-hidden rounded-lg border border-border">
22 <EditorSidebar
23 value={activeSm}
24 onValueChange={setActiveSm}
25 size="sm"
26 variant="ghost"
27 className="h-full"
28 >
29 <EditorSidebarRail>
30 <EditorSidebarTrigger
31 value="overview"
32 icon={<LayoutDashboard />}
33 label="Overview"
34 />
35 <EditorSidebarTrigger
36 value="settings"
37 icon={<Settings />}
38 label="Settings"
39 />
40 </EditorSidebarRail>
41 <EditorSidebarContent width="200px">
42 <EditorSidebarPanel value="overview" title="Overview">
43 <p className="text-xs text-muted-foreground">Compact rail.</p>
44 </EditorSidebarPanel>
45 <EditorSidebarPanel value="settings" title="Settings">
46 <p className="text-xs text-muted-foreground">Small icons.</p>
47 </EditorSidebarPanel>
48 </EditorSidebarContent>
49 </EditorSidebar>
50 </div>
51 </div>
52 <div>
53 <p className="mb-2 text-xs font-medium text-muted-foreground">Large</p>
54 <div className="h-[280px] overflow-hidden rounded-lg border border-border">
55 <EditorSidebar
56 value={activeLg}
57 onValueChange={setActiveLg}
58 size="lg"
59 variant="ghost"
60 className="h-full"
61 >
62 <EditorSidebarRail>
63 <EditorSidebarTrigger
64 value="overview"
65 icon={<LayoutDashboard />}
66 label="Overview"
67 />
68 <EditorSidebarTrigger
69 value="settings"
70 icon={<Settings />}
71 label="Settings"
72 />
73 </EditorSidebarRail>
74 <EditorSidebarContent width="220px">
75 <EditorSidebarPanel value="overview" title="Overview">
76 <p className="text-sm text-muted-foreground">Large rail.</p>
77 </EditorSidebarPanel>
78 <EditorSidebarPanel value="settings" title="Settings">
79 <p className="text-sm text-muted-foreground">
80 Roomier targets.
81 </p>
82 </EditorSidebarPanel>
83 </EditorSidebarContent>
84 </EditorSidebar>
85 </div>
86 </div>
87 </div>
88 );
89}

Installation & source

Install via the shadcn CLI or copy the registry files manually.

bash
npx shadcn@latest add @tt-ui/editor-sidebar

Props

NameTypeDefaultDescription
value / onValueChangestring / (value: string) => voiduncontrolled if omittedControlled active sidebar view id
defaultValuestringundefinedInitial active view in uncontrolled mode
variant (CVA)"default" | "ghost" | "bordered""default"Visual style for the sidebar shell
size (CVA)"sm" | "default" | "lg""default"Rail width and icon sizing
EditorSidebarTrigger.iconReactNoderequiredIcon slot for the rail trigger
EditorSidebarTrigger.labelstringrequiredAccessible label and native tooltip text
EditorSidebarTrigger.badgeboolean | ReactNodeundefinedOptional badge dot or custom badge content
EditorSidebarContent.widthstring"280px"Panel area width beside the rail
EditorSidebarPanel.titlestringtrigger labelOptional header title; falls back to trigger label
useEditorSidebarhookundefinedOptional helper for active view state