Design
llms.txt digitalcrew.tech

Navigation

Sidebar

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

MaxNavigationDigitalCrew.Sidebar
Sidebar · live · 960px wideOpen

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 SidebarGroups (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.

Facts#

GroupNavigation
ProductMax
Globalwindow.DigitalCrew.Sidebar
Sourcemax-agent: src/components/ui/sidebar.tsx
Import in the appimport { Sidebar } from "@/components/ui/sidebar";

API#

TypeScript declarations emitted from src/components/ui/sidebar.tsx (the module also exports its other parts).

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#

The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.

<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>