# Topbar 05 - Sidebar Integrated Topbar

> Topbar paired with a collapsible sidebar, combining primary navigation, quick actions, notifications, and user controls in a unified workspace layout.

A shadcn/ui block from the [@shadcn-space](https://shadcnspace.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcn-space/topbar-05).

- Page, with a live preview: https://shadcn.exchange/r/shadcn-space/topbar-05
- Screenshot: https://shadcn.exchange/shot/shadcn-space/topbar-05/light.png
- Registry item: https://shadcnspace.com/r/topbar-05.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/shadcn-space/topbar-05.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `sidebar`, `sheet`, `button`, `separator`, `avatar`, `accordion`, `dropdown-menu`, `scroll-area`, `navigation-menu`, `badge`

## Files

### `src/components/shadcn-space/blocks/topbar-05/page.tsx`

```tsx
import { Sidebar, SidebarProvider } from "@/components/ui/sidebar";
import Header from "@/components/shadcn-space/blocks/topbar-05/header";

export default function Page() {
  return (
    <div className="flex min-h-dvh w-full">
      <SidebarProvider>
        <Sidebar>
          <div className="flex flex-1 flex-col gap-4 p-4">
            {Array.from({ length: 12 }).map((_, index) => (
              <div
                key={index}
                className="skeleton bg-muted/50 aspect-video h-10 w-full rounded-lg"
              />
            ))}
          </div>
        </Sidebar>
        <div className="flex flex-1 flex-col">
          <Header />
          <main>
            <div className="flex flex-1 flex-col gap-4 p-4">
              {Array.from({ length: 9 }).map((_, index) => (
                <div
                  key={index}
                  className="skeleton bg-muted/50 aspect-video h-11 w-full rounded-lg"
                />
              ))}
            </div>
          </main>

          <footer className="bg-card h-10 border-t">
            <div className="flex flex-1 flex-col gap-4 p-4">
              <div className="skeleton bg-muted/50 aspect-video h-14 w-full rounded-lg" />
            </div>
          </footer>
        </div>
      </SidebarProvider>
    </div>
  );
}
```

### `src/components/shadcn-space/blocks/topbar-05/data.ts`

```ts
import { BringToFront, CalendarHeart, ChartColumnBig, CircleArrowDown, Flag, Form, GalleryVerticalEnd, Grid2x2Plus, LayersPlus, PanelRightClose, Pentagon, Presentation, RectangleCircle, Shapes, Shredder, Zap } from "lucide-react";

const NavData: any[] = [
    {
        type: "dropdown",
        label: "Dashboards",
        icon: LayersPlus,
        items: [
            { label: "Ecommerce", icon: Grid2x2Plus, href: "#" },
            { label: "Analytics", icon: ChartColumnBig, href: "#" },
            { label: "Projects", icon: BringToFront, href: "#" },
            { label: "Frontend Pages", icon: Form, href: "#" },
            { label: "Landing Pages", icon: Presentation, href: "#" },
        ],
    },
    {
        type: "dropdown",
        label: "Shadcn UI",
        icon: Shapes,
        items: [
            { label: "Accordian", icon: CircleArrowDown, href: "#" },
            { label: "Alert", icon: Flag, href: "#" },
            { label: "Bedge", icon: Pentagon, href: "#" },
            { label: "Button", icon: RectangleCircle, href: "#" },
            { label: "Dropdown", icon: GalleryVerticalEnd, href: "#" },
            { label: "Dialog", icon: Zap, href: "#" },
            { label: "Drawer", icon: PanelRightClose, href: "#" },
            { label: "Datepicker", icon: CalendarHeart, href: "#" }
        ]
    },
    {
        type: "link",
        label: "Docs",
        icon: Shredder,
        href: '#'
    }
]

export default NavData;
```

### `src/components/shadcn-space/blocks/topbar-05/types.ts`

```ts
import { LucideIcon } from "lucide-react";

export interface NavItem {
  label: string;
  icon: LucideIcon;
  href: string;
}

export interface NavGroup {
  type: string;
  label: string;
  icon: LucideIcon;
  href?: string;
  items?: NavItem[];
}
```

### `src/components/shadcn-space/blocks/topbar-05/header/index.tsx`

```tsx
"use client";

import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { SidebarTrigger } from "@/components/ui/sidebar";
import { BellRing, Globe } from "lucide-react";
import { NavigationMenu, NavigationMenuList } from "@/components/ui/navigation-menu";
import LanguageDropdown from "@/components/shadcn-space/blocks/topbar-05/header/dropdown-language";
import ProfileDropdown from "@/components/shadcn-space/blocks/topbar-05/header/dropdown-profile";
import { NavDropdown, NavButton } from "@/components/shadcn-space/blocks/topbar-05/header/desktop-nav";
import NavData from "@/components/shadcn-space/blocks/topbar-05/data";
import { NavGroup } from "@/components/shadcn-space/blocks/topbar-05/types";
import NotificationDropdown from "@/components/shadcn-space/blocks/topbar-05/header/notification-dropdown";

export default function Header() {
  return (
    <header className="bg-card sticky top-0 z-50 border-b">
      <div className="mx-auto flex items-center justify-between gap-6 px-4 py-2 sm:px-6">
        <div className="flex items-center gap-4">
          <SidebarTrigger className="[&_svg]:size-5! cursor-pointer" />
          <Separator
            orientation="vertical"
            className="hidden h-4! sm:block self-center!"
          />
          <div className="hidden lg:flex items-center justify-between">
            <NavigationMenu>
              <NavigationMenuList className="space-x-0">
                {(NavData as NavGroup[]).map((item) => {
                  if (item.type === "dropdown" && item.items) {
                    return (
                      <NavDropdown
                        key={item.label}
                        label={item.label}
                        Icon={item.icon}
                        items={item.items}
                      />
                    );
                  }
                  return (
                    <NavButton
                      key={item.label}
                      label={item.label}
                      Icon={item.icon}
                      href={item.href}
                    />
                  );
                })}
              </NavigationMenuList>
            </NavigationMenu>
          </div>
        </div>

        <div className="flex items-center gap-2.5">
          <NotificationDropdown
            defaultOpen={false}
            align="center"
            trigger={
              <div className="rounded-full p-2 hover:bg-accent relative before:absolute before:bottom-0 before:left-1/2 before:z-10 before:w-2 before:h-2 before:rounded-full before:bg-red-500 before:top-1">
                <BellRing className="size-4" />
              </div>
            }
          />
          <LanguageDropdown
            trigger={
              <Button
                id="language-dropdown-trigger-05"
                variant="ghost"
                size="icon"
                className="focus-visible:ring-0! focus-visible:shadow-none! rounded-full! hover:bg-accent/80! cursor-pointer"
                suppressHydrationWarning
              >
                <Globe size={16} />
              </Button>
            }
          />
          <ProfileDropdown
            trigger={
              <Button
                id="profile-dropdown-trigger-05"
                variant="ghost"
                size="icon"
                className="size-7 rounded-full cursor-pointer"
                suppressHydrationWarning
              >
                <Avatar className="size-7 rounded-full">
                  <AvatarImage src="https://images.shadcnspace.com/assets/profiles/user-11.jpg" />
                  <AvatarFallback>NJ</AvatarFallback>
                </Avatar>
              </Button>
            }
          />
        </div>
      </div>
    </header>
  );
}
```

### `src/components/shadcn-space/blocks/topbar-05/header/desktop-nav.tsx`

```tsx
import { LucideIcon } from "lucide-react";
import {
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";
import { NavItem } from "../types";

export function NavDropdown({
  label,
  Icon,
  items,
}: {
  label: string;
  Icon: LucideIcon;
  items: NavItem[];
}) {
  return (
    <NavigationMenuItem>
      <NavigationMenuTrigger
        className="gap-2 rounded-lg border border-transparent bg-transparent! cursor-pointer"
      >
        <Icon size={16} />
        <span className="text-sm">{label}</span>
      </NavigationMenuTrigger>

      <NavigationMenuContent className="min-w-48 p-1">
        <ul className="space-y-1">
          {items.map((item) => {
            const ItemIcon = item.icon;
            return (
              <li key={item.label}>
                <NavigationMenuLink
                  render={
                    <a
                      href={item.href}
                      className="flex items-left gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-accent hover:text-foreground"
                    >
                      <div className="flex items-center gap-2">
                        <ItemIcon size={16} />
                        <span>{item.label}</span>
                      </div>
                    </a>
                  }
                />
              </li>
            );
          })}
        </ul>
      </NavigationMenuContent>
    </NavigationMenuItem>
  );
}

export function NavButton({
  label,
  Icon,
  href = "#",
}: {
  label: string;
  Icon: LucideIcon;
  href?: string;
}) {
  return (
    <NavigationMenuItem>
      <NavigationMenuLink
        render={
          <a
            href={href}
            className="flex items-center gap-2 rounded-lg px-3 py-2 text-sm hover:bg-accent transition-colors"
          >
            <Icon size={16} />
            <span className="text-sm">{label}</span>
          </a>
        }
      />
    </NavigationMenuItem>
  );
}
```

### `src/components/shadcn-space/blocks/topbar-05/header/dropdown-language.tsx`

```tsx
'use client'

import { useState, type ReactElement } from 'react'
import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'

type Props = {
    trigger: ReactElement
    defaultOpen?: boolean
    align?: 'start' | 'center' | 'end'
}

type Language = {
    value: string
    label: string
    icon: string
}

const LANGUAGES: Language[] = [
    {
        value: 'english',
        label: 'English (UK)',
        icon: 'https://images.shadcnspace.com/assets/flags/flag-us.svg',
    },
    {
        value: 'chinese',
        label: '中国人 (Chinese)',
        icon: 'https://images.shadcnspace.com/assets/flags/flag-china.svg',
    },
    {
        value: 'french',
        label: 'français (French)',
        icon: 'https://images.shadcnspace.com/assets/flags/flag-france.svg',
    },
    {
        value: 'arabic',
        label: 'عربي (Arabic)',
        icon: 'https://images.shadcnspace.com/assets/flags/flag-australia.svg',
    },
]

const itemClass =
    'cursor-pointer gap-2 pl-2 text-sm data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground [&>span]:hidden'

const LanguageDropdown = ({ trigger, defaultOpen, align = 'end' }: Props) => {
    const [language, setLanguage] = useState(LANGUAGES[0].value)

    return (
        <DropdownMenu defaultOpen={defaultOpen}>
            <DropdownMenuTrigger render={trigger} />

            <DropdownMenuContent className="w-50" align={align}>
                <DropdownMenuRadioGroup
                    value={language}
                    onValueChange={setLanguage}
                    className="flex flex-col gap-2"
                >
                    {LANGUAGES.map(({ value, label, icon }) => (
                        <DropdownMenuRadioItem key={value} value={value} className={itemClass}>
                            <img src={icon} alt={label} width={16} height={16} className='rounded-full'/>
                            {label}
                        </DropdownMenuRadioItem>
                    ))}
                </DropdownMenuRadioGroup>
            </DropdownMenuContent>
        </DropdownMenu>
    )
}

export default LanguageDropdown
```

### `src/components/shadcn-space/blocks/topbar-05/header/dropdown-profile.tsx`

```tsx
"use client";

import type { ReactElement } from "react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
  BookMarked,
  LogOut,
  LucideIcon,
  ReceiptIndianRupee,
  Settings,
  UserPlus,
} from "lucide-react";

type Props = {
  trigger: ReactElement;
  defaultOpen?: boolean;
  align?: "start" | "center" | "end";
};

type MenuItem = {
  label: string;
  icon: LucideIcon;
  destructive?: boolean;
};

const PROFILE_ITEMS: MenuItem[] = [
  { label: "My Profile", icon: UserPlus },
  { label: "My Subscription", icon: BookMarked },
  { label: "My Invoice", icon: ReceiptIndianRupee },
];

const SETTINGS_ITEMS: MenuItem[] = [
  { label: "Account Settings", icon: Settings },
];

const LOGOUT_ITEM: MenuItem = {
  label: "Signout",
  icon: LogOut,
  destructive: true,
};

const itemClass = "px-4 py-2.5 text-base cursor-pointer gap-3";

const ProfileDropdown = ({ trigger, defaultOpen, align = "end" }: Props) => {
  return (
    <DropdownMenu defaultOpen={defaultOpen}>
      <DropdownMenuTrigger render={trigger} />

      <DropdownMenuContent className="w-80" align={align}>
        <DropdownMenuGroup>
          {/* User Info */}
          <DropdownMenuLabel className="flex items-center gap-4 px-4 py-2.5 font-normal">
            <div className="relative">
              <Avatar className="size-10">
                <AvatarImage
                  src="https://images.shadcnspace.com/assets/profiles/user-11.jpg"
                  alt="David McMichael"
                />
                <AvatarFallback>DM</AvatarFallback>
              </Avatar>
              <span className="ring-card absolute right-0 bottom-0 size-2 rounded-full bg-green-600 ring-2" />
            </div>

            <div className="flex flex-col">
              <span className="text-foreground text-lg font-semibold">
                David McMichael
              </span>
              <span className="text-muted-foreground text-sm">
                david.mcmichael@example.com
              </span>
            </div>
          </DropdownMenuLabel>

          <DropdownMenuSeparator />

          {/* Main Links */}
          {PROFILE_ITEMS.map(({ label, icon: Icon }) => (
            <DropdownMenuItem key={label} className={itemClass}>
              <Icon size={20} className="text-foreground" />
              <span>{label}</span>
            </DropdownMenuItem>
          ))}

          <DropdownMenuSeparator />

          {/* Settings */}
          <DropdownMenuGroup>
            {SETTINGS_ITEMS.map(({ label, icon: Icon }) => (
              <DropdownMenuItem key={label} className={itemClass}>
                <Icon size={20} className="text-foreground" />
                <span>{label}</span>
              </DropdownMenuItem>
            ))}
          </DropdownMenuGroup>

          <DropdownMenuSeparator />

          {/* Logout */}
          <DropdownMenuItem variant="destructive" className={itemClass}>
            <LOGOUT_ITEM.icon size={20} className="size-5" />
            <span>{LOGOUT_ITEM.label}</span>
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  );
};

export default ProfileDropdown;
```

### `src/components/shadcn-space/blocks/topbar-05/header/notification-dropdown.tsx`

```tsx
"use client";

import type { ReactNode } from "react";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import {
  Headset,
  LucideIcon,
  Salad,
  ScanText,
  Star,
  Video,
} from "lucide-react";

type Props = {
  trigger: ReactNode;
  defaultOpen?: boolean;
  align?: "start" | "center" | "end";
};

type MenuItem = {
  textColor: string;
  bgColor: string;
  icon: LucideIcon;
  title: string;
  desc: string;
  time: string;
};

const PROFILE_ITEMS: MenuItem[] = [
  {
    textColor: "stroke-blue-500",
    bgColor: "bg-blue-500/10",
    icon: Star,
    title: "Event Today",
    desc: "Just reminder that you have to",
    time: "9:00 AM",
  },
  {
    textColor: "stroke-orange-400",
    bgColor: "bg-orange-400/10",
    icon: Video,
    title: "Team Meeting",
    desc: "Discuss project updates and next steps",
    time: "10:00 AM",
  },
  {
    textColor: "stroke-teal-400",
    bgColor: "bg-teal-400/10",
    icon: Salad,
    title: "Lunch Break",
    desc: "Take a break and recharge",
    time: "12:30 PM",
  },
  {
    textColor: "stroke-red-500",
    bgColor: "bg-red-500/10",
    icon: Headset,
    title: "Client Call",
    desc: "Monthly check-in with the client",
    time: "3:00 PM",
  },
  {
    textColor: "stroke-sky-400",
    bgColor: "bg-sky-400/10",
    icon: ScanText,
    title: "Project Review",
    desc: "Review project deliverables with client",
    time: "4:00 PM",
  },
];

const NotificationDropdown = ({
  trigger,
  defaultOpen,
  align = "end",
}: Props) => {
  return (
    <div className="flex items-center justify-center">
      <DropdownMenu defaultOpen={defaultOpen}>
        <DropdownMenuTrigger>{trigger}</DropdownMenuTrigger>

        <DropdownMenuContent
          align={align}
          className="p-0 w-sm rounded-2xl data-open:slide-in-from-top-20! data-closed:slide-out-to-top-20 data-open:fade-in-0 data-closed:fade-out-0 data-closed:zoom-out-100 duration-400"
        >
          <DropdownMenuGroup>
            {/* title */}
            <DropdownMenuLabel className="flex items-center justify-between p-4">
              <p className="text-base font-medium text-popover-foreground">
                Notifications
              </p>
              <Badge className="h-5 font-normal leading-0">5 New</Badge>
            </DropdownMenuLabel>

            {/* Notifications */}
            {PROFILE_ITEMS.map(
              ({ bgColor, textColor, icon: Icon, title, desc, time }) => (
                <DropdownMenuItem
                  key={title}
                  className={
                    "mx-1.5 my-1 p-2 flex items-center justify-between cursor-pointer"
                  }
                >
                  <div className="flex items-center gap-3">
                    <div className={cn("p-2.5 rounded-xl", bgColor)}>
                      <Icon size={20} className={cn("size-5", textColor)} />
                    </div>
                    <div>
                      <p className="text-sm font-medium text-popover-foreground">
                        {title}
                      </p>
                      <p className="max-w-52 truncate text-sm text-muted-foreground">
                        {desc}
                      </p>
                    </div>
                  </div>
                  <p className="text-xs text-muted-foreground">{time}</p>
                </DropdownMenuItem>
              ),
            )}

            {/* button */}
            <div className="mx-1.5 my-1 p-2">
              <Button className="rounded-xl w-full cursor-pointer hover:bg-primary/80">
                See All Notifications
              </Button>
            </div>
          </DropdownMenuGroup>
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  );
};

export default NotificationDropdown;
```
