Sidebar

A composable, themeable and customizable sidebar component.

import {  Sidebar,  SidebarClose,  SidebarHeader,  SidebarInset,  SidebarOpen,  SidebarProvider,  SidebarRail,} from "@notion-kit/sidebar";export default function Basic() {  return (    <SidebarProvider className="h-full min-h-full">      <Sidebar className="absolute z-0 h-full">        <SidebarClose />        <SidebarHeader className="p-3 font-semibold">My App</SidebarHeader>        <SidebarRail />      </Sidebar>      <SidebarInset>        <header className="flex h-11 shrink-0 items-center gap-2 border-b px-4">          <SidebarOpen />          Navbar        </header>      </SidebarInset>    </SidebarProvider>  );}

Installation

pnpm add @notion-kit/sidebar

Anatomy

<SidebarProvider>
  <Sidebar>
    <SidebarClose />
    <SidebarHeader>{/* Your sidebar header */}</SidebarHeader>
    <SidebarContent>{/* Your sidebar content */}</SidebarContent>
    <SidebarFooter>{/* Your sidebar footer */}</SidebarFooter>
    <SidebarRail />
  </Sidebar>
  <SidebarInset>{/* Your main content */}</SidebarInset>
</SidebarProvider>

Examples


Notion Sidebar

import { Plan, Role } from "@notion-kit/schemas";import type { Page, User, Workspace } from "@notion-kit/schemas";import { randomInt } from "@notion-kit/utils";export const GROUPS = {  document: "Document",  private: "Private",  shared: "Shared",} as const;export const SHORTCUT_OPTIONS = { preventDefault: true };export const user: User = {  id: "u1",  name: "Admin",  email: "admin@email.com",  avatarUrl: "",};export const workspaces: Workspace[] = [  {    id: "w1",    name: "Workspace",    role: Role.OWNER,    memberCount: 5,    plan: Plan.FREE,  },  {    id: "w2",    name: "Workspace 2",    role: Role.GUEST,    memberCount: 2,    plan: Plan.EDUCATION,  },  {    id: "w3",    name: "Workspace 3",    role: Role.OWNER,    memberCount: 10,    plan: Plan.ENTERPRISE,  },  {    id: "w4",    name: "Workspace 4",    role: Role.MEMBER,    memberCount: 12,    plan: Plan.PLUS,  },];const getRandomTs = () =>  randomInt(Date.UTC(2024, 1, 1), Date.UTC(2024, 10, 31));export const pages: Page[] = [  {    type: "document",    id: "page1",    title: "Korean",    parentId: null,    icon: {      type: "url",      src: "https://img.freepik.com/premium-vector/line-art-flag-language-korean-illustration-vector_490632-422.jpg",    },    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isArchived: false,    isFavorite: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page2",    title: "Pronunciation",    parentId: "page1",    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page3",    title: "Study list",    parentId: null,    icon: { type: "lucide", src: "book", color: "#CB912F" },    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: true,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page4",    title: "My secret document",    icon: { type: "lucide", src: "book-check", color: "#CB912F" },    parentId: null,    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page5",    title: "System flowchart",    parentId: null,    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page6",    title: "Deprecated documents",    parentId: null,    icon: { type: "lucide", src: "book", color: "#337EA9" },    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: true,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "private",    id: "page7",    title: "TODO List",    parentId: null,    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "shared",    id: "page8",    title: "System flowchart",    parentId: null,    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page9",    parentId: "page3",    title: "The High Table",    icon: {      type: "url",      src: "https://cdn.iconscout.com/icon/premium/png-256-thumb/bar-table-1447763-1224177.png",    },    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },  {    type: "document",    id: "page10",    parentId: "page3",    title: "The Continental",    icon: { type: "emoji", src: "🏠" },    lastEditedBy: "",    lastEditedAt: getRandomTs(),    isFavorite: false,    isArchived: false,    isPublished: false,    createdAt: Date.UTC(2023, 3, 5),    createdBy: "",  },];

API Reference

SidebarProvider

PropTypeDefaultDescription
configPartial<SidebarConfig>-The configuration object of the sidebar.
defaultOpenboolean-The open state of the sidebar when it is initially rendered. Use when you do not need to control its open state.
openboolean-The (controlled) open state of the sidebar. Must be used in conjunction with onOpenChange.
onOpenChange(open: boolean) => void-Handler that is called when the open state of the sidebar changes.

Note

All the layout components below must be used within <SidebarProvider>.

A Sidebar extends the HTML <div> element. We list the extended properties only.

PropTypeDefaultDescription
side"left" | "right""left"The side of the sidebar.
variant"sidebar" | "floating""sidebar"The variant of the sidebar.
collapsible"offcanvas" | "none""offcanvas"Collapsible state of the sidebar.

SidebarHeader

A SidebarHeader extends the HTML <div> element.

SidebarContent

A SidebarContent extends the HTML <div> element.

SidebarFooter

A SidebarFooter extends the HTML <div> element.

SidebarGroup

A SidebarGroup extends the HTML <div> element.

SidebarInset

A SidebarInset extends the HTML <main> element.

SidebarRail

The SidebarRail is used to render a rail within a <Sidebar>. This rail can be used to toggle and resize the sidebar. It extends the HTML <div> element. We list the extended properties only.

PropTypeDefaultDescription
enableDragbooleantrueWhether the sidebar is draggable.

SidebarClose

The SidebarClose is used to close the sidebar. It can be triggered by keyboard shortcut. It extends the <Button> component.

SidebarOpen

The SidebarOpen is used to open the sidebar. It can be triggered by keyboard shortcut. It extends the <Button> component.

SidebarMenuItem

A SidebarMenuItem extends the HTML <div> element. We list the extended properties only.

PropTypeDefaultDescription
label*string-The title of the item.
hint*string-The tooltip of the item.
icon*LucideIcon-The displayed icon of the item.
shortcutstring-The keyboard shortcut of the item.

type SidebarConfig

The configuration object of the sidebar.

PropTypeDefaultDescription
defaultWidth*string248pxDefault width of the sidebar.
defaultModileWidth*string248pxDefault width of the sidebar on mobile.
minWidth*string248pxMinimum draggable width of the sidebar.
maxWidth*string400pxMaximum draggable width of the sidebar.
shortcut*string\Keyboard shortcut ⌘ + <shortcut> to toggle the sidebar.
cookieName*{ state: string, width: string }{ state: "sidebar:state", width: "sidebar:width" }Cookie names for sidebar state and sidebar width.
cookieMaxAge*number7dCookie's maximum lifetime (in seconds).