# Sidebar

> The app shell: a collapsible left sidebar beside an inset content panel (`SidebarProvider` › `Sidebar` + `SidebarInset`).

## Facts

- **Product**: Max
- **Family**: Navigation
- **Global**: `window.DigitalCrew.Sidebar`
- **Source**: `max-agent: src/components/ui/sidebar.tsx`
- **Import in the app**: `import { Sidebar } from "@/components/ui/sidebar";`
- **Live preview**: /design/components/sidebar/preview.html
- **Page**: /design/components/sidebar

## Guidelines

**Measurements**: 16rem wide, 3rem when collapsed to icons, 18rem as the mobile Sheet below 768px. Max uses `variant="inset"` and `collapsible="offcanvas"`; the inset panel takes an 8px margin, `radius-xl` corners and `shadow-sm`. The toggle cycles large → small → hidden, is remembered for 7 days, and ⌘/Ctrl+B toggles it. Width changes run 300ms on `cubic-bezier(0.32, 0.72, 0, 1)`.

**What you provide**: `SidebarHeader` (workspace logo or name), `SidebarContent` with `SidebarGroup`s (`SidebarGroupLabel` in sentence case — never "OVERVIEW") and `SidebarMenu` › `SidebarMenuItem` › `SidebarMenuButton` (`isActive`, `tooltip` for the collapsed state, a 16px icon then the label), `SidebarMenuBadge` for counts, and a `SidebarFooter` with the account. Put the page header (56px, 64px from `sm`) and `main` inside `SidebarInset`.

**Active item**: `sidebar-accent` fill with `sidebar-primary` text. On phones the sidebar hides behind a 56px bottom tab bar (four destinations plus More); pages add `--app-bottom-inset` so nothing hides behind it.

## API

```ts
type SidebarContextValue = {
    state: SidebarMode;
    mode: SidebarMode;
    setMode: React.Dispatch<React.SetStateAction<SidebarMode>>;
    setPeek: React.Dispatch<React.SetStateAction<boolean>>;
    setFlyoutOpen: (id: string, open: boolean) => void;
    setSidebarFocus: React.Dispatch<React.SetStateAction<boolean>>;
    open: boolean;
    isMobile: boolean;
    openMobile: boolean;
    setOpenMobile: React.Dispatch<React.SetStateAction<boolean>>;
    toggleSidebar: () => void;
};
declare function useSidebar(): SidebarContextValue;
type SidebarProviderProps = React.HTMLAttributes<HTMLDivElement> & {
    defaultMode?: SidebarMode;
    children?: React.ReactNode;
};
declare function SidebarProvider({ defaultMode, className, style, children, ...props }: SidebarProviderProps): any;
type SidebarProps = React.HTMLAttributes<HTMLDivElement> & {
    side?: "left" | "right";
    variant?: string;
    collapsible?: "offcanvas" | "icon" | "none";
};
declare function Sidebar({ side, variant, collapsible, className, children, ...props }: SidebarProps): any;
declare function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>): any;
declare function SidebarRail({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarInset({ className, ...props }: React.HTMLAttributes<HTMLElement>): any;
declare function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>): any;
declare function SidebarHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): any;
declare function SidebarContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarGroup({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarGroupLabel({ className, asChild, ...props }: React.HTMLAttributes<HTMLDivElement> & {
    asChild?: boolean;
}): any;
declare function SidebarGroupAction({ className, asChild, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement> & {
    asChild?: boolean;
}): any;
declare function SidebarGroupContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarMenu({ className, ...props }: React.HTMLAttributes<HTMLUListElement>): any;
declare function SidebarMenuItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>): any;
type SidebarMenuButtonProps = React.ComponentProps<"button"> & {
    asChild?: boolean;
    isActive?: boolean;
    variant?: "default" | "outline";
    size?: "default" | "sm" | "lg";
    tooltip?: string | {
        children: React.ReactNode;
    };
    className?: string;
};
declare function SidebarMenuButton({ asChild, isActive, variant, size, tooltip, className, ref, ...props }: SidebarMenuButtonProps): any;
type SidebarMenuFlyoutProps = React.ComponentProps<typeof DropdownMenu>;
/**
 * Dropdown root for compact sidebar navigation. Portalled content sits outside
 * the sidebar's pointer boundary, so an open flyout must hold a Hidden hover
 * preview in place until the menu closes.
 */
declare function SidebarMenuFlyout({ open: controlledOpen, defaultOpen, onOpenChange, ...props }: SidebarMenuFlyoutProps): any;
type SidebarMenuFlyoutTriggerProps = Omit<React.ComponentProps<typeof DropdownMenuTrigger>, "asChild"> & {
    children: React.ReactElement;
};
/** Binds Radix directly to the real menu button so pointer props, focus, and
 * the trigger ref all survive the `asChild` composition. */
declare function SidebarMenuFlyoutTrigger({ children, ...props }: SidebarMenuFlyoutTriggerProps): any;
declare function SidebarMenuFlyoutContent({ className, side, align, sideOffset, collisionPadding, ...props }: React.ComponentProps<typeof DropdownMenuContent>): any;
declare function SidebarMenuAction({ className, asChild, showOnHover, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement> & {
    asChild?: boolean;
    showOnHover?: boolean;
}): any;
declare function SidebarMenuBadge({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): any;
declare function SidebarMenuSkeleton({ className, showIcon, ...props }: React.HTMLAttributes<HTMLDivElement> & {
    showIcon?: boolean;
}): any;
declare function SidebarMenuSub({ className, ...props }: React.HTMLAttributes<HTMLUListElement>): any;
declare function SidebarMenuSubItem({ className, ...props }: React.HTMLAttributes<HTMLLIElement>): any;
declare function SidebarMenuSubButton({ asChild, size, isActive, className, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
    asChild?: boolean;
    size?: "sm" | "md";
    isActive?: boolean;
    className?: string;
}): any;
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuFlyout, SidebarMenuFlyoutContent, SidebarMenuFlyoutTrigger, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar, };
```

## Example

```html
<div id="root"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
var NAV = [
  ["Overview", [["Dashboard", I.LayoutDashboard, true], ["Tasks", I.ListChecks], ["Ask Max", I.Sparkles]]],
  ["Revenue", [["Pipeline", I.KanbanSquare], ["Prospects", I.Users], ["Campaigns", I.Megaphone], ["Unibox", I.Inbox, false, "4"]]]];
function App() {
  return h(DC.SidebarProvider, { defaultOpen: true, className: "min-h-0 h-[440px]" },
    h(DC.Sidebar, { variant: "inset", collapsible: "offcanvas", className: "absolute h-full" },
      h(DC.SidebarHeader, null, h("div", { className: "flex items-center gap-2 px-2 py-1.5 text-sm font-semibold" },
        h("span", { className: "grid size-7 place-content-center rounded-md bg-primary text-primary-foreground" }, "N"), "Northwind")),
      h(DC.SidebarContent, null, NAV.map(function (g) {
        return h(DC.SidebarGroup, { key: g[0] },
          h(DC.SidebarGroupLabel, null, g[0]),
          h(DC.SidebarGroupContent, null, h(DC.SidebarMenu, null, g[1].map(function (it) {
            return h(DC.SidebarMenuItem, { key: it[0] },
              h(DC.SidebarMenuButton, { isActive: !!it[2], tooltip: it[0] }, h(it[1]), h("span", null, it[0])),
              it[3] ? h(DC.SidebarMenuBadge, null, it[3]) : null);
          }))));
      })),
      h(DC.SidebarFooter, null, h(DC.SidebarMenu, null, h(DC.SidebarMenuItem, null,
        h(DC.SidebarMenuButton, { size: "lg" }, h(DC.Avatar, { className: "size-8 rounded-lg" }, h(DC.AvatarFallback, { className: "rounded-lg" }, "CD")),
          h("div", { className: "grid text-left text-sm leading-tight" }, h("span", { className: "truncate font-medium" }, "Claire Dubois"), h("span", { className: "truncate text-xs text-muted-foreground" }, "claire@northwind.io"))))))),
    h(DC.SidebarInset, null,
      h("header", { className: "flex h-14 items-center gap-2 border-b border-border/60 px-4" },
        h(DC.SidebarTrigger, { variant: "outline", className: "max-md:hidden" }),
        h(DC.Separator, { orientation: "vertical", className: "h-6" }),
        h(DC.Button, { variant: "outline", size: "sm", className: "h-8 w-52 justify-start bg-muted/25 text-muted-foreground" }, h(I.Search), "Search…")),
      h("main", { className: "px-4 py-6" },
        h("h1", { className: "text-2xl font-bold tracking-tight" }, "Dashboard"),
        h("p", { className: "text-sm text-muted-foreground" }, "Pipeline, replies and today's tasks at a glance."))));
}
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>
```

## More in Navigation

- [Breadcrumb](/design/components/breadcrumb.md): A page trail that shows where the current page sits in the hierarchy, built from composable parts inside a `<nav aria-label="breadcrumb">`.
- [Header](/design/components/header.md): The app's top bar: a sidebar toggle and a divider, followed by whatever you pass in.
- [ListMapToggle](/design/components/list-map-toggle.md): A two-button segmented switch between a List view and a Map view.
- [Pagination](/design/components/pagination.md): Numbered page links with previous/next and an ellipsis.
- [Tabs](/design/components/tabs.md): A segmented list that switches panels in place: a 36px `muted` track with 3px padding; the active tab lifts onto `background`.
- [ThemeSwitcher](/design/components/theme-switcher.md): A round icon button with a Light, Dark and System menu that sets the next-themes theme.
