UI Kit/Sidebar 2

Sidebar 2

Simple navigation with your team below it and the signed-in person at the bottom.

View code
"use client";

import { Calendar, ChartColumn, FileText, House, MessageSquare, Settings, ShoppingCart, Users } from "lucide-react";
import { useState } from "react";

import {
  Sidebar2,
  Sidebar2Brand,
  Sidebar2Item,
  Sidebar2Person,
  Sidebar2Section,
  Sidebar2User,
} from "@/components/kit/sidebar-2";

const photo = (id: string) => `https://images.unsplash.com/photo-${id}?w=64&h=64&fit=crop&crop=faces`;

const pages = [
  { name: "Dashboard", icon: <House /> },
  { name: "Analytics", icon: <ChartColumn /> },
  { name: "Team", icon: <Users /> },
  { name: "Messages", icon: <MessageSquare /> },
  { name: "Documents", icon: <FileText /> },
  { name: "Calendar", icon: <Calendar /> },
  { name: "Settings", icon: <Settings /> },
];

const team = [
  { name: "Sarah Kim", role: "Design", id: "1494790108377-be9c29b29330", online: true },
  { name: "John Doe", role: "Engineering", id: "1507003211169-0a1dd7228f2d", online: true },
  { name: "Mike Taylor", role: "Engineering", id: "1500648767791-00dcc994a43e", online: false },
  { name: "Lisa Park", role: "Product", id: "1438761681033-6461ffad8d80", online: true },
  { name: "Ravi Singh", role: "Data", id: "1534528741775-53994a69daeb", online: false },
];

export function Sidebar2Demo() {
  const [page, setPage] = useState("Dashboard");

  return (
    <div className="flex h-180 w-full justify-center bg-background">
      <Sidebar2 aria-label="Main" className="border-s">
        <Sidebar2Brand logo={<ShoppingCart aria-hidden="true" />} title="Acme Store" />
        {pages.map(({ name, icon }) => (
          <Sidebar2Item key={name} icon={icon} active={page === name} onClick={() => setPage(name)}>
            {name}
          </Sidebar2Item>
        ))}
        <Sidebar2Section label="Your team">
          {team.map(({ name, role, id, online }) => (
            <Sidebar2Person key={name} name={name} role={role} avatar={photo(id)} online={online} />
          ))}
        </Sidebar2Section>
        <Sidebar2User name="Jordan Diaz" email="jordan@example.com" avatar={photo("1472099645785-5658abf4ff4e")} />
      </Sidebar2>
    </div>
  );
}

A simpler sidebar for smaller apps. It has no collapse or nesting, and it adds people to the navigation.

Installation

bunx --bun shadcn@latest add HarshitMahajan/UI/sidebar-2

Copies the code to components/kit/sidebar-2.tsx installs its packages, and adds the tokens it needs to your globals.css. Your existing shadcn components aren't touched.

Usage

import {
  Sidebar2,
  Sidebar2Brand,
  Sidebar2Item,
  Sidebar2Person,
  Sidebar2Section,
  Sidebar2User,
} from "@/components/kit/sidebar-2"
<Sidebar2 aria-label="Main">
  <Sidebar2Brand logo={<ShoppingCart aria-hidden="true" />} title="Acme Store" />
  <Sidebar2Item icon={<House />} active>Dashboard</Sidebar2Item>
  <Sidebar2Section label="Your team">
    <Sidebar2Person name="Sarah Kim" role="Design" online />
  </Sidebar2Section>
  <Sidebar2User name="Jordan Diaz" email="jordan@example.com" />
</Sidebar2>

Composition

Sidebar2
├── Sidebar2Brand
├── Sidebar2Item
├── Sidebar2Section
│   └── Sidebar2Person
└── Sidebar2User

Features

  • Pictures with a green online dot
  • The person's first letter when there's no picture
  • The signed-in person stays pinned to the bottom
  • Items render as buttons or as links through the render prop

Navigation only

Leave out the team section for plain navigation.

View code
import { ChartColumn, House, Settings, ShoppingCart } from "lucide-react";

import { Sidebar2, Sidebar2Brand, Sidebar2Item, Sidebar2User } from "@/components/kit/sidebar-2";

export function Sidebar2Navigation() {
  return (
    <div className="flex h-96 w-full justify-center bg-background">
      <Sidebar2 aria-label="Main" className="border-s">
        <Sidebar2Brand logo={<ShoppingCart aria-hidden="true" />} title="Acme Store" />
        <Sidebar2Item icon={<House />} active>
          Dashboard
        </Sidebar2Item>
        <Sidebar2Item icon={<ChartColumn />}>Analytics</Sidebar2Item>
        <Sidebar2Item icon={<Settings />}>Settings</Sidebar2Item>
        <Sidebar2User name="Jordan Diaz" email="jordan@example.com" />
      </Sidebar2>
    </div>
  );
}

Without pictures

Leave out avatar to show the person's first letter instead.

View code
import { Sidebar2, Sidebar2Person, Sidebar2Section } from "@/components/kit/sidebar-2";

export function Sidebar2Initials() {
  return (
    <div className="flex h-64 w-full justify-center bg-background">
      <Sidebar2 aria-label="Team" className="border-s">
        <Sidebar2Section label="Your team" className="mt-1">
          <Sidebar2Person name="Sarah Kim" role="Design" online />
          <Sidebar2Person name="John Doe" role="Engineering" online />
          <Sidebar2Person name="Lisa Park" />
        </Sidebar2Section>
      </Sidebar2>
    </div>
  );
}

Accessibility

Online state

The green dot includes hidden text saying Online, so the state isn't conveyed by color alone.

API Reference

Sidebar2

The frame. Renders an aside element.

PropTypeDefaultDescription
classNamestring-Additional classes for the frame.

Sidebar2Brand

Your logo and name.

PropTypeDefaultDescription
logoReactNode-An icon or a letter.
titlestring-The name.

Sidebar2Item

One row.

PropTypeDefaultDescription
iconReactNode-The row's icon.
activebooleanfalseMarks the current page.
renderReactElement | function-Render the row as another element, such as a link or your router's Link.

Sidebar2Section

A labeled set of rows.

PropTypeDefaultDescription
labelstring-The section's name.

Sidebar2Person

A teammate.

PropTypeDefaultDescription
namestring-Their name.
rolestring-Shown on the right.
avatarstring-The picture's URL.
onlinebooleanfalseShows the green dot.

Sidebar2User

The signed-in person, pinned to the bottom.

PropTypeDefaultDescription
namestring-Their name.
emailstring-A line under the name.
avatarstring-The picture's URL.