zeroUI

Sidebar

The column down the side of an app: a black, hatched strip whose rows are the Dropdown menu's, the current page filled with the accent.

Install

terminal
# once per project: where @zeroui items come frompnpm dlx shadcn@latest registry add @zeroui=https://zeroui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zeroui/sidebar

Examples

An app's sidebar, folding to icons

Board

Press the button or ⌘B / Ctrl+B to fold the sidebar to its icons.

sidebar-app.tsx
import {  ArrowRightIcon,  ExternalIcon,  InfoIcon,  LockIcon,  SearchIcon,} from "@/components/zero/icons";import {  Sidebar,  SidebarContent,  SidebarFooter,  SidebarGroup,  SidebarGroupLabel,  SidebarHeader,  SidebarInset,  SidebarMenu,  SidebarMenuBadge,  SidebarMenuButton,  SidebarMenuItem,  SidebarMenuSub,  SidebarMenuSubButton,  SidebarMenuSubItem,  SidebarProvider,  SidebarSeparator,  SidebarTrigger,} from "@/components/zero/sidebar";const jobs = [  { label: "Board", icon: SearchIcon, count: 12, active: true },  { label: "Taken", icon: ArrowRightIcon, count: 3 },  { label: "Locked", icon: LockIcon },];export default function SidebarApp() {  return (    // A box instead of a whole page: the sidebar's container is absolute here, not fixed.    <SidebarProvider className="relative h-[26rem] min-h-0 w-full overflow-hidden border-(length:--zero-stroke-thin) border-zero-line">      <Sidebar collapsible="icon" className="absolute h-full">        <SidebarHeader>          <div className="flex items-center gap-3 px-3 py-2">            <span className="h-5 w-3 shrink-0 -skew-x-(--zero-slant) bg-zero-accent" />            <span className="truncate font-black font-zero text-zero-lg italic group-data-[collapsible=icon]/sidebar:hidden">              Dispatch            </span>          </div>        </SidebarHeader>        <SidebarContent>          <SidebarGroup>            <SidebarGroupLabel>Jobs</SidebarGroupLabel>            <SidebarMenu>              {jobs.map(({ label, icon: Icon, count, active }) => (                <SidebarMenuItem key={label}>                  <SidebarMenuButton isActive={active} tooltip={label}>                    <Icon />                    <span>{label}</span>                  </SidebarMenuButton>                  {count ? <SidebarMenuBadge>{count}</SidebarMenuBadge> : null}                </SidebarMenuItem>              ))}              <SidebarMenuItem>                <SidebarMenuButton tooltip="Districts">                  <ExternalIcon />                  <span>Districts</span>                </SidebarMenuButton>                <SidebarMenuSub>                  <SidebarMenuSubItem>                    <SidebarMenuSubButton href="#harbor" isActive>                      Harbor                    </SidebarMenuSubButton>                  </SidebarMenuSubItem>                  <SidebarMenuSubItem>                    <SidebarMenuSubButton href="#rail-yards">                      Rail yards                    </SidebarMenuSubButton>                  </SidebarMenuSubItem>                </SidebarMenuSub>              </SidebarMenuItem>            </SidebarMenu>          </SidebarGroup>        </SidebarContent>        <SidebarSeparator />        <SidebarFooter>          <SidebarMenu>            <SidebarMenuItem>              <SidebarMenuButton tooltip="Help">                <InfoIcon />                <span>Help</span>              </SidebarMenuButton>            </SidebarMenuItem>          </SidebarMenu>        </SidebarFooter>      </Sidebar>      <SidebarInset className="gap-4 p-4">        <div className="flex items-center gap-3">          <SidebarTrigger />          <span className="font-black font-zero text-zero-lg italic">            Board          </span>        </div>        <p className="font-medium font-zero-text text-zero-sm text-zero-text-2">          Press the button or ⌘B / Ctrl+B to fold the sidebar to its icons.        </p>      </SidebarInset>    </SidebarProvider>  );}

Behaviour

On a wide screen it folds away entirely (collapsible="offcanvas") or down to a rail of icons ("icon"), where each row shows only its icon and names itself in a tooltip. On a phone it opens as a Sheet. SidebarTrigger, or ⌘B / Ctrl+B, opens and closes it.

It fills the screen's height by default; to put it in a box, as in the example, give the provider a height and the sidebar className="absolute h-full". useSidebar gives the open state to anything inside the provider.

Props

SidebarProvider

PropTypeDefaultDescription
defaultOpenbooleantrueOpen at first, uncontrolled.
open / onOpenChangeboolean / (open) => void—Open, controlled.

Sidebar

PropTypeDefaultDescription
collapsible"offcanvas" | "icon" | "none""offcanvas"What closing does on a wide screen.
side"left" | "right""left"The edge it sits on.

SidebarMenuButton

PropTypeDefaultDescription
isActivebooleanfalseThe page you are on: filled with the accent.
tooltipstring—Names the row while the sidebar is folded to icons.
renderReactElement—The element to render as, such as a link.

SidebarHeader, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuItem, SidebarMenuBadge, SidebarMenuSub, SidebarMenuSubButton, SidebarSeparator, SidebarTrigger, SidebarInset