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
default-example.tsx
1"use client";23import { 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";1213const 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};1819export function EditorSidebarDefaultExample() {20 const [active, setActive] = useState("overview");2122 return (23 <div className="mx-auto h-[360px] w-full max-w-md overflow-hidden rounded-lg border border-border">24 <EditorSidebar25 value={active}26 onValueChange={setActive}27 variant="bordered"28 className="h-full"29 >30 <EditorSidebarRail>31 <EditorSidebarTrigger32 value="overview"33 icon={<LayoutDashboard />}34 label="Overview"35 />36 <EditorSidebarTrigger37 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
badges-example.tsx
1"use client";23import { 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";1213export function EditorSidebarBadgesExample() {14 const [active, setActive] = useState("inbox");1516 return (17 <div className="mx-auto h-[360px] w-full max-w-md overflow-hidden rounded-lg border border-border">18 <EditorSidebar19 value={active}20 onValueChange={setActive}21 variant="default"22 className="h-full"23 >24 <EditorSidebarRail>25 <EditorSidebarTrigger26 value="inbox"27 icon={<Inbox />}28 label="Inbox"29 badge30 />31 <EditorSidebarTrigger32 value="messages"33 icon={<MessageSquare />}34 label="Messages"35 />36 <EditorSidebarTrigger37 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 343 </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
Large
sizes-example.tsx
1"use client";23import { useState } from "react";4import { LayoutDashboard, Settings } from "lucide-react";5import {6 EditorSidebar,7 EditorSidebarRail,8 EditorSidebarTrigger,9 EditorSidebarContent,10 EditorSidebarPanel,11} from "@/registry/ui";1213export function EditorSidebarSizesExample() {14 const [activeSm, setActiveSm] = useState("overview");15 const [activeLg, setActiveLg] = useState("overview");1617 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 <EditorSidebar23 value={activeSm}24 onValueChange={setActiveSm}25 size="sm"26 variant="ghost"27 className="h-full"28 >29 <EditorSidebarRail>30 <EditorSidebarTrigger31 value="overview"32 icon={<LayoutDashboard />}33 label="Overview"34 />35 <EditorSidebarTrigger36 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 <EditorSidebar56 value={activeLg}57 onValueChange={setActiveLg}58 size="lg"59 variant="ghost"60 className="h-full"61 >62 <EditorSidebarRail>63 <EditorSidebarTrigger64 value="overview"65 icon={<LayoutDashboard />}66 label="Overview"67 />68 <EditorSidebarTrigger69 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
| Name | Type | Default | Description |
|---|---|---|---|
| value / onValueChange | string / (value: string) => void | uncontrolled if omitted | Controlled active sidebar view id |
| defaultValue | string | undefined | Initial 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.icon | ReactNode | required | Icon slot for the rail trigger |
| EditorSidebarTrigger.label | string | required | Accessible label and native tooltip text |
| EditorSidebarTrigger.badge | boolean | ReactNode | undefined | Optional badge dot or custom badge content |
| EditorSidebarContent.width | string | "280px" | Panel area width beside the rail |
| EditorSidebarPanel.title | string | trigger label | Optional header title; falls back to trigger label |
| useEditorSidebar | hook | undefined | Optional helper for active view state |