# Dashboard Layout 03 - Horizontal Layout

> Choose a horizontal navigation pattern for dashboards that need maximum workspace and simplified navigation. Great for enterprise tools, reporting platforms, and data heavy applications.

A shadcn/ui block from the [@shadcn-dashboard](https://shadcndashboard.dev) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcn-dashboard/dashboard-layout-03).

- Page, with a live preview: https://shadcn.exchange/r/shadcn-dashboard/dashboard-layout-03
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/shadcn-dashboard/dashboard-layout-03-light-755ae67e61dc14ac.png
- Registry item: https://shadcndashboard.dev/r/dashboard-layout-03.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcndashboard.dev/r/dashboard-layout-03.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`, `simplebar-react`
- Registry items: `navigation-menu`, `collapsible`, `sheet`, `button`, `avatar`, `dropdown-menu`, `dialog`, `input`, `breadcrumb`, `card`

## Files

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/page.tsx`

```tsx
import { AppSidebar } from "@/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/app-sidebar";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
import { Card } from "@/components/ui/card";
import Search from "@/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/search";

const Page = () => {
  return (
    <div className="flex min-h-svh w-full flex-col">
      <div className="border-b border-border">
        <AppSidebar />
      </div>
      <main className="flex-1 bg-[linear-gradient(180deg,var(--primary)_0%,var(--primary)_40%,var(--secondary)_40%,var(--secondary)_100%)]">
        <div className="px-4 max-w-[1440px] mx-auto overflow-hidden">
          <div className="py-5 flex items-center justify-between">
            <Breadcrumb>
              <BreadcrumbList className="text-primary-foreground text-sm">
                <BreadcrumbItem className="hidden md:block">
                  <BreadcrumbLink href="#" className="hover:text-primary-foreground/80">
                    Dashboard
                  </BreadcrumbLink>
                </BreadcrumbItem>
                <BreadcrumbSeparator className="hidden md:block" />
                <BreadcrumbItem>
                  <BreadcrumbPage className="text-primary-foreground/60">Analytics</BreadcrumbPage>
                </BreadcrumbItem>
              </BreadcrumbList>
            </Breadcrumb>
            <Search/>
          </div>
          <Card className="flex flex-1 flex-col gap-4 p-4">
            {Array.from({ length: 8 }).map((_, index) => (
              <div
                key={index}
                className="skeleton bg-muted/50 aspect-video h-12 w-full rounded-lg"
              />
            ))}
          </Card>
        </div>
      </main>
    </div>
  );
};

export default Page;
```

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/app-sidebar.tsx`

```tsx
"use client";

import { useState } from "react";
import SimpleBar from "simplebar-react";
import "simplebar-react/dist/simplebar.min.css";
import { Button } from "@/components/ui/button";
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import {
  NavMain,
  MobileNav,
  NavSection,
} from "@/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/nav-main";
import {
  AlignStartVertical,
  PieChart,
  CircleUserRound,
  ClipboardList,
  Menu,
  Notebook,
  NotepadText,
  Table,
  Languages,
  Ticket,
  ShoppingCart,
  House,
  Sparkles,
  GraduationCap,
  HeartPulse,
  Settings,
  HelpCircle,
  Tag,
  ShieldCheck,
  Plug,
  Key,
  Calendar,
  MessageCircle,
  Mail,
  NotebookText,
  Contact,
  TextCursorInput,
  MousePointer2,
  ListChecks,
  Disc,
  Calendar1,
  LaptopMinimalCheck,
  MapPinCheckInside,
  Globe,
} from "lucide-react";
import ProfileDropdown from "@/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/dropdown-profile";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import LanguageDropdown from "@/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/dropdown-language";

export const navData: NavSection[] = [
  {
    label: "Dashboards",
    items: [
      { title: "Analytics", icon: PieChart, href: "#" },
      { title: "CRM Dashboard", icon: ClipboardList, href: "#" },
      { title: "eCommerce", icon: ShoppingCart, href: "#" },
      { title: "Modern", icon: House, href: "#" },
      { title: "SaaS + AI Dashboard", icon: Sparkles, href: "#" },
      { title: "School Management", icon: GraduationCap, href: "#" },
      { title: "Health Management", icon: HeartPulse, href: "#" },
    ],
  },
  {
    label: "Pages",
    items: [
      { title: "Account Setting", icon: Settings, href: "#" },
      { title: "FAQ", icon: HelpCircle, href: "#" },
      { title: "Pricing", icon: Tag, href: "#" },
      { title: "Roll Base Access", icon: ShieldCheck, href: "#" },
      { title: "Integrations", icon: Plug, href: "#" },
      { title: "API Keys", icon: Key, href: "#" },
    ],
  },
  {
    label: "Apps",
    items: [
      { title: "Notes", icon: Notebook, href: "#" },
      { title: "Tickets", icon: Ticket, href: "#" },
      { title: "Blogs", icon: Languages, href: "#" },
      { title: "Calendar", icon: Calendar, href: "#" },
      { title: "Chats", icon: MessageCircle, href: "#" },
      { title: "Email", icon: Mail, href: "#" },
      { title: "Notes", icon: NotebookText, href: "#" },
      { title: "Contacts", icon: Contact, href: "#" },
    ],
  },
  {
    label: "Form Elements",
    items: [
      { title: "Input", icon: TextCursorInput, href: "#" },
      { title: "Select", icon: MousePointer2, href: "#" },
      { title: "Checkbox", icon: ListChecks, href: "#" },
      { title: "Radio", icon: Disc, href: "#" },
      { title: "Datepicker", icon: Calendar1, href: "#" },
      { title: "Autocomplete", icon: LaptopMinimalCheck, href: "#" },
      { title: "Dropzone", icon: MapPinCheckInside, href: "#" },
    ],
  },
];

export function AppSidebar() {
  const [mobileOpen, setMobileOpen] = useState(false);

  return (
    <header className="sticky top-0 z-50 flex h-16 w-full items-center gap-10 px-4 max-w-[1440px] mx-auto">
      {/* ---------------- Logo ---------------- */}
      <a href="#" className="flex shrink-0 items-center">
        <img
          src="https://images.shadcnspace.com/assets/shadcn-dashboard/logo/fulldark-logo.svg"
          alt="fulldark-logo"
          width={100}
          height={32}
          className="block dark:hidden"
        />
        <img
          src="https://images.shadcnspace.com/assets/shadcn-dashboard/logo/fullwhite-logo.svg"
          alt="fulldark-logo"
          width={100}
          height={32}
          className="hidden dark:block"
        />
      </a>

      {/* ---------------- Desktop horizontal nav (left aligned) ---------------- */}
      <NavMain sections={navData} className="hidden md:flex" />

      <div className="ms-auto flex shrink-0 items-center gap-2">
        <LanguageDropdown
          trigger={
            <div
              id="language-dropdown-trigger"
              className="rounded-md hover:bg-accent/80 cursor-pointer p-2"
            >
              <Globe size={16} />
            </div>
          }
        />

        <ProfileDropdown
          trigger={
            <div
              id="profile-dropdown-trigger"
              className="rounded-full cursor-pointer"
            >
              <Avatar className="size-7 rounded-full">
                <AvatarImage src="https://images.shadcnspace.com/assets/shadcn-dashboard/profile/user-2.webp" />
                <AvatarFallback>NJ</AvatarFallback>
              </Avatar>
            </div>
          }
        />

        {/* ---------------- Mobile trigger ---------------- */}
        <Button
          variant="outline"
          size="icon"
          className="md:hidden"
          onClick={() => setMobileOpen(true)}
        >
          <Menu className="size-4" />
        </Button>
        <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>
          <SheetContent side="left" className="flex w-72 flex-col p-0">
            <SheetHeader className="border-b px-4 py-3">
              <SheetTitle className="text-start text-sm">Menu</SheetTitle>
            </SheetHeader>
            <SimpleBar className="flex-1 min-h-0 p-3">
              <MobileNav sections={navData} onNavigate={() => setMobileOpen(false)} />
            </SimpleBar>
          </SheetContent>
        </Sheet>
      </div>
    </header>
  );
}
```

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/nav-main.tsx`

```tsx
"use client";

import * as React from "react";
import { ChevronDown, LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import {
  Collapsible,
  CollapsibleTrigger,
  CollapsibleContent,
} from "@/components/ui/collapsible";
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";

export type NavChild = {
  title: string;
  href: string;
};

export type NavItem = {
  title: string;
  icon?: LucideIcon;
  href?: string;
  children?: NavChild[];
};

export type NavSection = {
  label: string;
  items: NavItem[];
};

export function NavMain({
  sections,
  className,
}: {
  sections: NavSection[];
  className?: string;
}) {
  return (
    <NavigationMenu
      className={cn("max-w-none flex-none items-center justify-start", className)}
    >
      <NavigationMenuList className="gap-1">
        {sections.map((section) => (
          <NavigationMenuItem key={section.label}>
            <NavigationMenuTrigger className="h-9 px-3 text-sm font-medium text-foreground hover:bg-accent hover:text-accent-foreground data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground [&>svg]:ms-1 [&>svg]:size-4">
              {section.label}
            </NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-60 gap-0.5 p-2">
                {section.items.map((item) => (
                  <li key={item.title}>
                    {item.children?.length ? (
                      <div className="pt-3 first:pt-0">
                        <p className="px-2 pb-1 text-xs font-medium uppercase text-muted-foreground">
                          {item.title}
                        </p>
                        <ul className="grid gap-0.5">
                          {item.children.map((child) => (
                            <li key={child.title}>
                              <NavigationMenuLink
                                render={<a href={child.href} />}
                                className="flex items-center px-2 py-1.5 text-sm text-foreground hover:bg-accent hover:text-accent-foreground"
                              >
                                {child.title}
                              </NavigationMenuLink>
                            </li>
                          ))}
                        </ul>
                      </div>
                    ) : (
                      <NavigationMenuLink
                        render={<a href={item.href ?? "#"} />}
                        className="flex items-center gap-2 px-2 py-1.5 text-sm text-foreground hover:bg-accent hover:text-accent-foreground"
                      >
                        {item.icon && <item.icon className="size-4" />}
                        {item.title}
                      </NavigationMenuLink>
                    )}
                  </li>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
        ))}
      </NavigationMenuList>
    </NavigationMenu>
  );
}

export function MobileNav({
  sections,
  onNavigate,
}: {
  sections: NavSection[];
  onNavigate?: () => void;
}) {
  return (
    <div className="flex flex-col gap-4">
      {sections.map((section) => (
        <div key={section.label} className="flex flex-col gap-0.5">
          <p className="px-1 pt-4 pb-1 text-xs font-medium uppercase text-muted-foreground first:pt-0">
            {section.label}
          </p>
          {section.items.map((item) => (
            <MobileNavItem key={item.title} item={item} onNavigate={onNavigate} />
          ))}
        </div>
      ))}
    </div>
  );
}

function MobileNavItem({
  item,
  onNavigate,
}: {
  item: NavItem;
  onNavigate?: () => void;
}) {
  const hasChildren = !!item.children?.length;
  const [isOpen, setIsOpen] = React.useState(false);

  if (hasChildren) {
    return (
      <Collapsible open={isOpen} onOpenChange={setIsOpen}>
        <CollapsibleTrigger className="flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground">
          {item.icon && <item.icon className="size-4" />}
          <span className="flex-1 text-start">{item.title}</span>
          <ChevronDown
            className={cn(
              "size-4 transition-transform duration-200",
              isOpen && "rotate-180"
            )}
          />
        </CollapsibleTrigger>
        <CollapsibleContent className="flex flex-col gap-0.5 py-1 ps-9">
          {item.children!.map((child) => (
            <a
              key={child.title}
              href={child.href}
              onClick={onNavigate}
              className="rounded-md px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
            >
              {child.title}
            </a>
          ))}
        </CollapsibleContent>
      </Collapsible>
    );
  }

  return (
    <a
      href={item.href ?? "#"}
      onClick={onNavigate}
      className="flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium text-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
    >
      {item.icon && <item.icon className="size-4" />}
      {item.title}
    </a>
  );
}
```

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/search.tsx`

```tsx
"use client";

import { useState } from "react";
import SimpleBar from "simplebar-react";
import "simplebar-react/dist/simplebar.min.css";
import { Dialog, DialogContent, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { SearchIcon } from "lucide-react";
import { Button } from "@/components/ui/button";

interface SearchType {
    href: string;
    title: string;
}

const SearchLinks: SearchType[] = [
    {
        title: 'Modern',
        href: '/',
    },
    {
        title: 'eCommerce',
        href: '/dashboards/eCommerce',
    },
    {
        title: 'General',
        href: '/dashboards/general',
    },
    {
        title: 'Music',
        href: '/dashboards/music',
    },
    {
        title: 'General',
        href: '/dashboards/general',
    },
];

const Search = () => {
    const [openModal, setOpenModal] = useState(false);

    return (
        <div>
            <Dialog open={openModal} onOpenChange={setOpenModal}>
                <DialogTrigger
                    render={
                        <Button variant="outline" className="flex h-9 w-9 border border-primary-foreground/20 bg-transparent items-center justify-center transition-colors hover:bg-accent sm:w-auto sm:min-w-48 sm:justify-start sm:gap-2 sm:px-4 sm:py-1.5 sm:hover:bg-transparent cursor-pointer">
                            <SearchIcon size={16} className="text-muted-foreground shrink-0" />
                            <span className="hidden text-sm font-normal text-muted-foreground sm:block">Type to search...</span>
                        </Button>
                    }
                />
                <DialogContent className="w-full max-w-2xl p-0 gap-0 [&>button]:hidden">
                    <DialogTitle className="sr-only">Search</DialogTitle>
                    <div className="p-6 border-b border-border">
                        <Input
                            placeholder="Search links..."
                            className="flex-1 pl-4 focus-visible:ring-0 focus-visible:shadow-none"
                        />
                    </div>

                    <div className="flex-1 overflow-auto pt-0">
                        <SimpleBar className="max-h-72 px-6">
                            <h5 className="text-lg font-medium pt-5">Quick Page Links</h5>
                            {SearchLinks.length > 0 ? (
                                SearchLinks.map((link, index) => (
                                    <a
                                        href={link.href}
                                        className="py-1 px-3 group relative"
                                        key={index}
                                    >
                                        <h6 className="group-hover:text-blue-500 mb-1 font-medium text-sm">
                                            {link.title}
                                        </h6>
                                        <p className="text-xs text-bodytext opacity-90 font-medium">
                                            {link.href}
                                        </p>
                                    </a>
                                ))
                            ) : (
                                <p className="text-sm text-center text-gray-500 py-4">
                                    No results found.
                                </p>
                            )}
                        </SimpleBar>
                    </div>
                </DialogContent>
            </Dialog>
        </div>
    );
};

export default Search;
```

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/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 {
  Bookmark,
  LogOut,
  LucideIcon,
  ReceiptText,
  Settings,
  User,
} 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: User },
  { label: "My Subscription", icon: Bookmark },
  { label: "My Invoice", icon: ReceiptText },
];

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>{trigger}</DropdownMenuTrigger>

      <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} />
            <span>{LOGOUT_ITEM.label}</span>
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  );
};

export default ProfileDropdown;
```

### `src/components/shadcn-dashboard/blocks/dashboard-layout/dashboard-layout-03/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>
                {trigger}
            </DropdownMenuTrigger>

            <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
```
