# Lead dashboard

A shadcn/ui block from the [@watermelon](https://ui.watermelon.sh) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/watermelon/lead-dashboard).

- Page, with a live preview: https://shadcn.exchange/r/watermelon/lead-dashboard
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/watermelon/lead-dashboard-light-14573b9052a487ee.png
- Registry item: https://registry.watermelon.sh/r/lead-dashboard.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://registry.watermelon.sh/r/lead-dashboard.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: `@dnd-kit/core`, `@dnd-kit/sortable`, `@dnd-kit/utilities`, `@radix-ui/react-avatar`, `@radix-ui/react-collapsible`, `@radix-ui/react-dialog`, `@radix-ui/react-dropdown-menu`, `@radix-ui/react-label`, `@radix-ui/react-popover`, `@radix-ui/react-select`, `@radix-ui/react-separator`, `@radix-ui/react-slot`, `@radix-ui/react-tabs`, `@radix-ui/react-tooltip`, `@tabler/icons-react`, `class-variance-authority`, `lucide-react`
- Registry items: `avatar`, `breadcrumb`, `button`, `card`, `collapsible`, `dialog`, `dropdown-menu`, `input`, `label`, `popover`, `select`, `separator`, `sheet`, `sidebar`, `skeleton`, `tabs`, `tooltip`

## Files

### `src/components/dashboards/lead-dashboard/components/app-sidebar.tsx`

```tsx
"use client"

import * as React from "react"
import {
  IconChevronRight,
  IconRosetteDiscountCheck,
} from "@tabler/icons-react"

import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarHeader,
  SidebarTrigger,
} from "@/components/ui/sidebar"
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from "@/components/ui/collapsible"
import {
  SidebarGroup,
  SidebarGroupLabel,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
  SidebarMenuSubButton,
  SidebarMenuSubItem,
} from "@/components/ui/sidebar"

import { data } from "./data"

export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
  return (
    <Sidebar {...props}>
      <SidebarHeader className="h-14 border-b p-2">
        <SidebarMenu>
          <SidebarMenuItem className="flex items-center gap-2">
            <div className="flex flex-1 items-center gap-2 overflow-hidden px-2 py-1">
              <div className="size-7 rounded-md bg-linear-to-br from-purple-500 via-pink-500 to-orange-400 shrink-0 shadow-sm" />
              <div className="flex items-center justify-center gap-1.5 overflow-hidden">
                <span className="font-semibold text-foreground truncate">OceanLabs</span>
                <IconRosetteDiscountCheck className="size-4 shrink-0 text-primary" />
              </div>
            </div>
            <SidebarTrigger className="h-8 w-8" />
          </SidebarMenuItem>
        </SidebarMenu>
      </SidebarHeader>
      <SidebarContent>
        {/* Workspace Section */}
        <SidebarGroup>
          <SidebarGroupLabel>Workspace</SidebarGroupLabel>
          <SidebarMenu>
            {data.workspace.map((item) => {
              const hasItems = item.items && item.items.length > 0

              if (!hasItems) {
                return (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton tooltip={item.title} className="font-semibold tracking-tight transition-colors duration-200">
                      {item.icon && <item.icon strokeWidth={2.5} />}
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                )
              }

              return (
                <Collapsible
                  key={item.title}
                  asChild
                  defaultOpen={item.isActive}
                  className="group/collapsible"
                >
                  <SidebarMenuItem>
                    <CollapsibleTrigger asChild>
                      <SidebarMenuButton tooltip={item.title} className="font-semibold tracking-tight transition-colors duration-200">
                        {item.icon && <item.icon strokeWidth={2.5} />}
                        <span>{item.title}</span>
                        <IconChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90 h-4 w-4" />
                      </SidebarMenuButton>
                    </CollapsibleTrigger>
                    <CollapsibleContent>
                      <SidebarMenuSub>
                        {item.items?.map((subItem) => (
                          <SidebarMenuSubItem key={subItem.title}>
                            <SidebarMenuSubButton asChild isActive={subItem.isActive} className="font-semibold tracking-tight hover:text-zinc-900 dark:hover:text-white transition-colors duration-200">
                              <a href={subItem.url}>
                                <span>{subItem.title}</span>
                              </a>
                            </SidebarMenuSubButton>
                          </SidebarMenuSubItem>
                        ))}
                      </SidebarMenuSub>
                    </CollapsibleContent>
                  </SidebarMenuItem>
                </Collapsible>
              )
            })}
          </SidebarMenu>
        </SidebarGroup>

        {/* Favorites Section */}
        <Collapsible defaultOpen className="group/favorites">
          <SidebarGroup>
            <div className="flex items-center justify-between">
              <SidebarGroupLabel asChild>
                <CollapsibleTrigger className="flex w-full items-center justify-between hover:text-foreground">
                  Favorites
                  <IconChevronRight className="ml-auto h-4 w-4 transition-transform duration-200 group-data-[state=open]/favorites:rotate-90" />
                </CollapsibleTrigger>
              </SidebarGroupLabel>
            </div>
            <CollapsibleContent>
              <SidebarMenu>
                {data.favorites.map((item) => (
                  <SidebarMenuItem key={item.title}>
                    <SidebarMenuButton tooltip={item.title} className="tracking-tight transition-colors duration-200">
                      {item.icon && <item.icon />}
                      <span>{item.title}</span>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                ))}
              </SidebarMenu>
            </CollapsibleContent>
          </SidebarGroup>
        </Collapsible>
      </SidebarContent>

      {/* Footer Section */}
      <SidebarFooter className="border-t">
        <SidebarMenu>
          {data.footer.map((item) => (
            <SidebarMenuItem key={item.title} className="font-semibold tracking-tight">
              <SidebarMenuButton tooltip={item.title} className="transition-colors duration-200">
                {item.icon && <item.icon strokeWidth={2.5} />}
                <span>{item.title}</span>
              </SidebarMenuButton>
            </SidebarMenuItem>
          ))}
        </SidebarMenu>
      </SidebarFooter>
    </Sidebar>
  )
}
```

### `src/components/dashboards/lead-dashboard/components/data.ts`

```ts
import {
    IconChartBar,
    IconCalendar,
    IconFileText,
    IconFolder,
    IconHome,
    IconLogout,
    IconPhone,
    IconSearch,
    IconSettings,
    IconUser,
    IconUserPlus,
} from "@tabler/icons-react"
import type * as React from "react"

export interface NavItem {
    title: string
    url: string
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    icon?: React.ComponentType<any>
    isActive?: boolean
    items?: NavItem[]
}

export interface SidebarData {
    workspace: NavItem[]
    favorites: NavItem[]
    footer: NavItem[]
}

export const data: SidebarData = {
    workspace: [
        {
            title: "Home",
            url: "#",
            icon: IconHome,
        },
        {
            title: "Analytics",
            url: "#",
            icon: IconChartBar,
            items: [
                {
                    title: "Overview",
                    url: "#",
                },
            ],
        },
        {
            title: "Projects",
            url: "#",
            icon: IconFolder,
            items: [
                {
                    title: "All Projects",
                    url: "#",
                },
            ],
        },
        {
            title: "Leads",
            url: "#",
            icon: IconSearch,
            isActive: true,
            items: [
                {
                    title: "Table",
                    url: "#",
                },
                {
                    title: "Kanban",
                    url: "/dashboard/kanban-board",
                    isActive: true,
                },
            ],
        },
        {
            title: "Schedule",
            url: "#",
            icon: IconCalendar,
        },
        {
            title: "Admin",
            url: "#",
            icon: IconUser,
        },
    ],
    favorites: [
        {
            title: "File #1",
            url: "#",
            icon: IconFileText,
        },
        {
            title: "File #2",
            url: "#",
            icon: IconFileText,
        },
        {
            title: "Project #1",
            url: "#",
            icon: IconFolder,
        },
        {
            title: "Project #2",
            url: "#",
            icon: IconFolder,
        },
        {
            title: "Lead #44",
            url: "#",
            icon: IconSearch,
        },
        {
            title: "Call #1",
            url: "#",
            icon: IconPhone,
        },
        {
            title: "D Call #2",
            url: "#",
            icon: IconPhone,
        },
    ],
    footer: [
        {
            title: "Settings",
            url: "#",
            icon: IconSettings,
        },
        {
            title: "Invite users",
            url: "#",
            icon: IconUserPlus,
        },
        {
            title: "Log out",
            url: "#",
            icon: IconLogout,
        },
    ],
}

export interface KanbanCard {
    id: number
    title: string
    description: string
    user: string
    date: string
    comments: number
    type: string
    avatarColor: string
}

export interface KanbanColumn {
    id: string
    title: string
    leads?: number
    deals?: number
    total: string
    cards: KanbanCard[]
}

export const boardData: KanbanColumn[] = [
    {
        id: "contacted",
        title: "Contacted",
        leads: 3,
        total: "$993,000",
        cards: [
            { id: 1, title: "E-commerce Platform", description: "Development of a responsive online shopping...", user: "Sara Thompson", date: "June 15", comments: 8, type: "urgent", avatarColor: "bg-gradient-to-br from-orange-400 to-rose-500" },
            { id: 2, title: "Social Media Dashboard", description: "Creating an analytics dashboard for social eng...", user: "Mark Chen", date: "July 10", comments: 10, type: "mail", avatarColor: "bg-gradient-to-br from-purple-500 to-indigo-600" },
            { id: 3, title: "Customer Support Chatbot", description: "Developing an AI-powered chatbot for custom...", user: "Noah Hall", date: "October 3", comments: 19, type: "mail", avatarColor: "bg-gradient-to-br from-blue-400 to-cyan-500" },
        ]
    },
    {
        id: "drafting",
        title: "Drafting",
        leads: 4,
        total: "$121,000",
        cards: [
            { id: 4, title: "Landing Page", description: "Designing a high-conversion landing page for...", user: "Elena Garcia", date: "August 1", comments: 5, type: "mail", avatarColor: "bg-gradient-to-br from-pink-500 to-rose-600" },
            { id: 5, title: "Content Management System", description: "Revamping an existing CMS for better user ex...", user: "James Patel", date: "September 12", comments: 20, type: "file", avatarColor: "bg-gradient-to-br from-yellow-400 to-orange-500" },
            { id: 6, title: "Fitness App", description: "Designing a user-friendly app for tracking wor...", user: "Nina Kim", date: "October 22", comments: 15, type: "mail", avatarColor: "bg-gradient-to-br from-red-400 to-pink-500" },
            { id: 7, title: "Fitness Tracker", description: "Designing an app that monitors health and fitn...", user: "Mia Turner", date: "September 18", comments: 13, type: "mail", avatarColor: "bg-gradient-to-br from-cyan-400 to-blue-500" },
        ]
    },
    {
        id: "proposal",
        title: "Proposal",
        leads: 6,
        total: "$938,000",
        cards: [
            { id: 8, title: "Travel Booking Site", description: "Developing a streamlined booking interface fo...", user: "Oliver Smith", date: "November 8", comments: 18, type: "urgent", avatarColor: "bg-gradient-to-br from-blue-500 to-indigo-600" },
            { id: 9, title: "Online Learning Portal", description: "Creating an interactive platform for online cou...", user: "Zoe Martinez", date: "June 30", comments: 25, type: "phone", avatarColor: "bg-gradient-to-br from-red-500 to-rose-600" },
            { id: 10, title: "Corporate Intranet", description: "Designing a user-friendly interface for compa...", user: "Brian Johnson", date: "January 15", comments: 9, type: "file", avatarColor: "bg-gradient-to-br from-indigo-500 to-blue-600" },
            { id: 11, title: "Recipe Sharing App", description: "Building a platform for users to share and disc...", user: "Emma Wilson", date: "February 28", comments: 11, type: "chat", avatarColor: "bg-gradient-to-br from-green-400 to-emerald-600" },
            { id: 12, title: "News Aggregator", description: "Creating an app that curates news from vario...", user: "Ethan Clark", date: "August 30", comments: 17, type: "chat", avatarColor: "bg-gradient-to-br from-amber-400 to-orange-500" },
            { id: 13, title: "Event Management System", description: "Creating a streamlined system for organizing...", user: "David Brown", date: "March 14", comments: 14, type: "file", avatarColor: "bg-gradient-to-br from-sky-400 to-blue-500" },
        ]
    },
    {
        id: "closed",
        title: "Closed",
        deals: 8,
        total: "$382,000",
        cards: [
            { id: 14, title: "Virtual Reality Experience", description: "Designing an immersive virtual reality applicati...", user: "Liam Davis", date: "April 5", comments: 30, type: "done", avatarColor: "bg-gradient-to-br from-purple-500 to-pink-600" },
            { id: 15, title: "Blog Platform", description: "Developing a robust platform for blogging and...", user: "Sophia Lee", date: "May 19", comments: 7, type: "done", avatarColor: "bg-gradient-to-br from-emerald-400 to-teal-500" },
            { id: 16, title: "Real Estate App", description: "Creating a mobile app for real estate listings a...", user: "Lucas White", date: "June 16", comments: 12, type: "done", avatarColor: "bg-gradient-to-br from-teal-400 to-cyan-500" },
            { id: 17, title: "Job Portal", description: "Developing a platform for job seekers and em...", user: "Chloe Martinez", date: "July 25", comments: 22, type: "done", avatarColor: "bg-gradient-to-br from-fuchsia-500 to-purple-600" },
        ]
    }
]
```

### `src/components/dashboards/lead-dashboard/components/kanban/KanbanCard.tsx`

```tsx
import { useSortable } from "@dnd-kit/sortable"
import { CSS } from "@dnd-kit/utilities"
import { IconAlertCircle, IconCircleCheck, IconMail, IconFileText, IconCalendarPlus, IconMessageCircle } from '@tabler/icons-react'
import { Card, CardContent } from "@/components/ui/card"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from "@/components/ui/popover"
import { IconUser, IconMailForward } from '@tabler/icons-react'

export const StatusMarker = ({ type }: { type: string }) => {
    switch (type) {
        case "urgent":
            return (
                <div className="bg-red-100/50 dark:bg-red-500/10 border-[1.5px] border-red-200/60 dark:border-red-500/20 p-1 rounded-full shrink-0 transition-colors duration-200 hover:bg-red-200/50 dark:hover:bg-red-500/20 cursor-default">
                    <IconAlertCircle className="size-3.5 text-red-700 dark:text-red-400" strokeWidth={1.7} />
                </div>
            )
        case "done":
            return (
                <div className="bg-emerald-100/50 dark:bg-emerald-500/10 border-[1.5px] border-emerald-200/60 dark:border-emerald-500/20 p-1 rounded-full shrink-0 transition-colors duration-200 hover:bg-emerald-200/50 dark:hover:bg-emerald-500/20 cursor-default">
                    <IconCircleCheck className="size-3.5 text-emerald-700 dark:text-emerald-400" strokeWidth={2.5} />
                </div>
            )
        default:
            return (
                <div className="bg-zinc-100/50 dark:bg-zinc-500/10 border-[1.5px] border-zinc-200/60 dark:border-zinc-500/20 p-1 rounded-full shrink-0 transition-colors duration-200 hover:bg-zinc-200/50 dark:hover:bg-zinc-500/20 cursor-default">
                    {type === "mail" ? <IconMail className="size-3.5 text-zinc-500 dark:text-zinc-400" /> : <IconFileText className="size-3.5 text-zinc-500 dark:text-zinc-400" />}
                </div>
            )
    }
}

export const getStatusStyles = (type: string) => {
    switch (type) {
        case "urgent":
            return {
                footerBg: "bg-red-700/5 dark:bg-red-500/10",
                textColor: "text-red-700 dark:text-red-400",
                iconColor: "text-red-700 dark:text-red-400"
            }
        case "done":
            return {
                footerBg: "bg-emerald-700/5 dark:bg-emerald-500/10",
                textColor: "text-zinc-500 dark:text-zinc-400",
                iconColor: "text-zinc-500 dark:text-zinc-400"
            }
        default:
            return {
                footerBg: "bg-zinc-700/5 dark:bg-zinc-500/10",
                textColor: "text-zinc-500 dark:text-zinc-400",
                iconColor: "text-zinc-500 dark:text-zinc-400"
            }
    }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const KanbanCard = ({ card, columnId }: { card: any, columnId: string }) => {
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
        isDragging,
    } = useSortable({
        id: card.id,
        data: {
            type: "Card",
            card,
            columnId
        }
    });

    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
        opacity: isDragging ? 0.4 : 1,
    };

    const StatusStyles = getStatusStyles(card.type);

    return (
        <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
            <Card className="touch-none overflow-hidden border-[1.5px] border-neutral-200 dark:border-zinc-800 shadow-xs hover:shadow-sm hover:-translate-y-0.5 transition-colors duration-200 cursor-grab active:cursor-grabbing bg-white dark:bg-zinc-900 group p-0 shrink-0">
                <CardContent className="p-0 flex flex-col pointer-events-none select-none">
                    <div className="p-4 flex flex-col gap-2.5">
                        <div className="flex items-start justify-between gap-2">
                            <h4 className="leading-tight font-semibold tracking-tight text-zinc-900 dark:text-zinc-100 group-hover:text-zinc-950 dark:group-hover:text-white transition-colors text-sm">{card.title}</h4>
                            <StatusMarker type={card.type} />
                        </div>
                        <p className="text-xs text-muted-foreground line-clamp-2">
                            {card.description}
                        </p>
                    </div>

                    <div className={`px-4 py-2.5 flex items-center justify-between gap-3 border-t border-neutral-200 dark:border-zinc-800 ${StatusStyles.footerBg}`}>
                        <Popover>
                            <PopoverTrigger asChild>
                                <div className="flex items-center gap-2 min-w-0 pointer-events-auto cursor-pointer hover:z-10 group/avatar">
                                    <Avatar className="size-4.5 shadow-xs shrink-0 transition-transform duration-200">
                                        <AvatarFallback className={`${card.avatarColor} text-[6px] text-white font-bold`}>
                                            {card.user.split(' ').map((n: string) => n[0]).join('')}
                                        </AvatarFallback>
                                    </Avatar>
                                    <span className="text-xs font-semibold text-zinc-600 dark:text-zinc-400 group-hover/avatar:text-zinc-900 dark:group-hover/avatar:text-white truncate transition-colors">{card.user}</span>
                                </div>
                            </PopoverTrigger>
                            <PopoverContent align="start" className="w-56 p-1.5 shadow-lg border-neutral-200 dark:border-zinc-800 pointer-events-auto">
                                <div className="flex items-center gap-2.5 px-2 py-2 mb-1 border-b border-neutral-100 dark:border-zinc-800/50 pb-3">
                                    <Avatar className="size-9 rounded-full">
                                        <AvatarImage src="" />
                                        <AvatarFallback className={`${card.avatarColor} text-white font-medium text-xs rounded-full`}>
                                            {card.user.split(' ').map((n: string) => n[0]).join('')}
                                        </AvatarFallback>
                                    </Avatar>
                                    <div className="flex flex-col">
                                        <span className="text-sm font-semibold">{card.user}</span>
                                        <span className="text-[11px] text-muted-foreground">Sales Representative</span>
                                    </div>
                                </div>
                                <div className="flex flex-col gap-0.5 mt-1.5">
                                    <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none transition-colors text-left focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80">
                                        <IconUser className="size-4" />
                                        View Profile
                                    </button>
                                    <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none transition-colors text-left focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80">
                                        <IconMailForward className="size-4" />
                                        Send Message
                                    </button>
                                </div>
                            </PopoverContent>
                        </Popover>

                        <div className="flex items-center gap-3 text-xs font-medium tracking-tight shrink-0">
                            <div className={`flex items-center gap-1 shrink-0 ${StatusStyles.textColor}`}>
                                <IconCalendarPlus strokeWidth={1.7} className={`size-4 shrink-0 ${StatusStyles.iconColor}`} />
                                <span className="whitespace-nowrap">{card.date}</span>
                            </div>
                            <div className="flex items-center gap-1 shrink-0 text-zinc-500 dark:text-zinc-400">
                                <IconMessageCircle className="size-4 shrink-0" strokeWidth={2} />
                                <span>{card.comments}</span>
                            </div>
                        </div>
                    </div>
                </CardContent>
            </Card>
        </div>
    );
};
```

### `src/components/dashboards/lead-dashboard/components/kanban/KanbanColumn.tsx`

```tsx
import { IconDots, IconEdit, IconTrash, IconSettings } from '@tabler/icons-react'
import { Button } from "@/components/ui/button"
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from "@/components/ui/popover"

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const BoardColumn = ({ column, children }: { column: any, children: React.ReactNode }) => {
    return (
        <div className="flex flex-col gap-4.5 w-[85vw] sm:w-[320px] lg:w-auto shrink-0 snap-center lg:snap-align-none h-full min-h-0">
            <div className="flex justify-between items-center px-2.5 pointer-events-none select-none">
                <div className="flex flex-col gap-0.5 min-w-0">
                    <h3 className="font-semibold tracking-tight text-[15px] text-zinc-900 dark:text-zinc-50 truncate">{column.title}</h3>
                    <div className="flex flex-wrap items-center gap-x-1.5 gap-y-0.5 text-[12px] text-muted-foreground font-medium">
                        <span className="whitespace-nowrap">{column.cards.length} {column.id === 'closed' ? 'Deals' : 'Leads'}</span>
                        <span className="hidden sm:inline-block">•</span>
                        <span className="whitespace-nowrap">{column.total} <span className="text-neutral-300 dark:text-neutral-600 font-normal">Total</span></span>
                    </div>
                </div>
                <Popover>
                    <PopoverTrigger asChild>
                        <Button variant="ghost" size="icon" className="size-8 text-muted-foreground hover:text-foreground dark:hover:text-zinc-100 dark:hover:bg-zinc-800 transition-colors duration-200 pointer-events-auto outline-none focus-visible:ring-0">
                            <IconDots className="size-4" />
                        </Button>
                    </PopoverTrigger>
                    <PopoverContent align="end" className="w-48 p-1.5 shadow-lg border-neutral-200 dark:border-zinc-800 pointer-events-auto">
                        <div className="flex flex-col gap-0.5">
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80 transition-colors text-left">
                                <IconEdit className="size-4" />
                                Rename column
                            </button>
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80 transition-colors text-left">
                                <IconSettings className="size-4" />
                                Column settings
                            </button>
                            <div className="h-px bg-border my-1" />
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-500/10 rounded-md outline-none focus-visible:bg-red-50 dark:focus-visible:bg-red-500/10 transition-colors text-left font-medium">
                                <IconTrash className="size-4" />
                                Delete column
                            </button>
                        </div>
                    </PopoverContent>
                </Popover>
            </div>

            <div className="flex flex-col gap-3 flex-1 overflow-y-auto no-scrollbar pb-4 px-2 -mx-2 pt-2 -mt-2 min-h-0">
                {children}
            </div>

        </div>
    );
};
```

### `src/components/dashboards/lead-dashboard/components/site-header.tsx`

```tsx
import {
    SidebarTrigger,
    useSidebar,
} from "@/components/ui/sidebar"
import {
    Breadcrumb,
    BreadcrumbItem,
    BreadcrumbLink,
    BreadcrumbList,
    BreadcrumbPage,
    BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
import { Separator } from "@/components/ui/separator"
import { Input } from "@/components/ui/input"
import {
    Avatar,
    AvatarFallback,
    AvatarImage,
} from "@/components/ui/avatar"
import {
    IconSearch,
    IconBell,
    IconSettings,
    IconUser,
    IconLogout
} from "@tabler/icons-react"
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from "@/components/ui/popover"

export function SiteHeader() {
    const { isMobile, state } = useSidebar()
    const isCollapsed = state === "collapsed"
    const showTrigger = isMobile || isCollapsed

    return (
        <header className="flex h-14 shrink-0 items-center justify-between border-b px-4 md:px-8">
            <div className="flex items-center gap-2">
                {showTrigger && (
                    <>
                        <SidebarTrigger className="-ml-1" />
                        <Separator
                            orientation="vertical"
                            className="mr-2 data-[orientation=vertical]:h-4"
                        />
                    </>
                )}
                <Breadcrumb>
                    <BreadcrumbList>
                        <BreadcrumbItem className="hidden md:block">
                            <BreadcrumbLink href="#" className="flex items-center gap-1 text-muted-foreground">
                                Lead
                            </BreadcrumbLink>
                        </BreadcrumbItem>
                        <BreadcrumbSeparator className="hidden md:block" />
                        <BreadcrumbItem>
                            <BreadcrumbPage className="font-medium">Kanban Board</BreadcrumbPage>
                        </BreadcrumbItem>
                    </BreadcrumbList>
                </Breadcrumb>
            </div>

            <div className="flex items-center gap-4">
                {/* Search Bar */}
                <div className="relative hidden lg:block">
                    <IconSearch className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" strokeWidth={2.5} />
                    <Input
                        placeholder="Search or ⌘K..."
                        className="h-8 w-52 rounded-md bg-muted/40 pl-9 pr-12 text-sm transition-colors focus-visible:ring-0 focus-visible:border-neutral-400 dark:focus-visible:border-neutral-600 outline-none shadow-none"
                    />
                </div>

                {/* Notifications */}
                <Popover>
                    <PopoverTrigger asChild>
                        <button className="flex h-8 items-center gap-1.5 rounded-full border bg-background px-2 hover:bg-muted/50 transition-colors shadow cursor-pointer group">
                            <IconBell className="ml-1 size-4 text-muted-foreground group-hover:text-foreground transition-colors" />
                            <div className="flex h-5 min-w-[26px] items-center justify-center rounded-full bg-zinc-800 dark:bg-zinc-200 px-1.5 text-[10px] font-medium text-white dark:text-zinc-900 leading-none">
                                12
                            </div>
                        </button>
                    </PopoverTrigger>
                    <PopoverContent align="end" className="w-80 p-0 overflow-hidden shadow-lg border-neutral-200 dark:border-zinc-800">
                        <div className="flex items-center justify-between px-4 py-3 border-b border-neutral-100 dark:border-zinc-800 bg-zinc-50/50 dark:bg-zinc-900/50">
                            <h4 className="font-semibold text-sm">Notifications</h4>
                            <span className="text-xs text-muted-foreground cursor-pointer hover:text-foreground">Mark all read</span>
                        </div>
                        <div className="flex flex-col max-h-[300px] overflow-y-auto">
                            <div className="p-4 flex gap-3 hover:bg-muted/50 transition-colors cursor-pointer border-b border-neutral-100 dark:border-zinc-800">
                                <div className="size-8 rounded-full bg-blue-100/50 dark:bg-blue-500/10 flex items-center justify-center shrink-0">
                                    <IconUser className="size-4 text-blue-600 dark:text-blue-400" />
                                </div>
                                <div className="flex flex-col gap-1">
                                    <p className="text-sm font-medium leading-none">New Lead Assigned</p>
                                    <p className="text-xs text-muted-foreground">Sarah assigned the 'TechCorp' lead to you.</p>
                                    <p className="text-[10px] text-muted-foreground mt-0.5">2 hours ago</p>
                                </div>
                            </div>
                            <div className="p-4 flex gap-3 hover:bg-muted/50 transition-colors cursor-pointer border-b border-neutral-100 dark:border-zinc-800">
                                <div className="size-8 rounded-full bg-emerald-100/50 dark:bg-emerald-500/10 flex items-center justify-center shrink-0">
                                    <IconBell className="size-4 text-emerald-600 dark:text-emerald-400" />
                                </div>
                                <div className="flex flex-col gap-1">
                                    <p className="text-sm font-medium leading-none">Deal Closed!</p>
                                    <p className="text-xs text-muted-foreground">The 'OceanLabs' deal was marked as closed won.</p>
                                    <p className="text-[10px] text-muted-foreground mt-0.5">5 hours ago</p>
                                </div>
                            </div>
                            <div className="p-4 text-center">
                                <span className="text-xs text-blue-600 dark:text-blue-400 hover:underline cursor-pointer font-medium">View all notifications</span>
                            </div>
                        </div>
                    </PopoverContent>
                </Popover>

                {/* User Profile */}
                <Popover>
                    <PopoverTrigger asChild>
                        <Avatar className="size-8 rounded-full shadow-sm cursor-pointer hover:opacity-90 transition-opacity">
                            <AvatarImage src="" />
                            <AvatarFallback className="bg-linear-to-br from-blue-400 via-purple-500 to-pink-500 text-white rounded-full">AJ</AvatarFallback>
                        </Avatar>
                    </PopoverTrigger>
                    <PopoverContent align="end" className="w-56 p-1.5 shadow-lg border-neutral-200 dark:border-zinc-800">
                        <div className="flex items-center gap-2.5 px-2 py-2 mb-1 border-b border-neutral-100 dark:border-zinc-800/50 pb-3">
                            <Avatar className="size-9 rounded-full">
                                <AvatarImage src="" />
                                <AvatarFallback className="bg-linear-to-br from-blue-400 via-purple-500 to-pink-500 text-white font-medium text-xs rounded-full">AJ</AvatarFallback>
                            </Avatar>
                            <div className="flex flex-col">
                                <span className="text-sm font-semibold">Alex Johnson</span>
                                <span className="text-[11px] text-muted-foreground">alex@oceanlabs.co</span>
                            </div>
                        </div>
                        <div className="flex flex-col gap-0.5 mt-1.5">
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80 transition-colors text-left">
                                <IconUser className="size-4" />
                                Profile Profile
                            </button>
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-zinc-600 dark:text-zinc-300 hover:text-zinc-900 dark:hover:text-white hover:bg-zinc-100 dark:hover:bg-zinc-800/80 rounded-md outline-none focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-800/80 transition-colors text-left">
                                <IconSettings className="size-4" />
                                Account Settings
                            </button>
                            <div className="h-px bg-border my-1" />
                            <button className="w-full flex items-center gap-2 px-2 py-1.5 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-500/10 rounded-md outline-none focus-visible:bg-red-50 dark:focus-visible:bg-red-500/10 transition-colors text-left font-medium">
                                <IconLogout className="size-4" />
                                Sign out
                            </button>
                        </div>
                    </PopoverContent>
                </Popover>
            </div>
        </header>
    )
}
```

### `src/components/dashboards/lead-dashboard/dashboardLayout.tsx`

```tsx
"use client"

import { AppSidebar } from "./components/app-sidebar"
import {
    SidebarInset,
    SidebarProvider,
} from "@/components/ui/sidebar"
import { SiteHeader } from "./components/site-header"

export const DashboardLayout = ({ children }: { children: React.ReactNode }) => {
    return (
        <SidebarProvider>
            <AppSidebar />
            <SidebarInset className="h-svh overflow-hidden">
                <SiteHeader />
                <main className="flex-1 overflow-hidden h-full">
                    {children}
                </main>
            </SidebarInset>
        </SidebarProvider>
    )
}
```

### `src/components/dashboards/lead-dashboard/demo.tsx`

```tsx
"use client";

import { DashboardLayout } from "./dashboardLayout";
import { KanbanBoardView } from "./kanbanBoardView";

export default function LeadDashboardDemo() {
    return (
        <DashboardLayout>
            <KanbanBoardView />
        </DashboardLayout>
    );
}
```

### `src/components/dashboards/lead-dashboard/kanbanBoardView.tsx`

```tsx
"use client"

import { useState } from "react"
import {
    IconLayoutColumns,
    IconLayoutList,
    IconAdjustmentsHorizontal,
    IconCirclePlus,
    IconPlus
} from '@tabler/icons-react'
import {
    DndContext,
    closestCorners,
    KeyboardSensor,
    PointerSensor,
    useSensor,
    useSensors,
    type DragEndEvent,
    type DragOverEvent
} from "@dnd-kit/core"
import {
    arrayMove,
    SortableContext,
    sortableKeyboardCoordinates,
    verticalListSortingStrategy,
} from "@dnd-kit/sortable"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from "@/components/ui/popover"
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
    DialogFooter
} from "@/components/ui/dialog"
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from "@/components/ui/select"
import {
    Tabs,
    TabsList,
    TabsTrigger,
} from "@/components/ui/tabs"
import { boardData as initialBoardData } from "./components/data"
import { KanbanCard } from "./components/kanban/KanbanCard"
import { BoardColumn } from "./components/kanban/KanbanColumn"

export const KanbanBoardView = () => {
    const [board, setBoard] = useState(initialBoardData);

    const sensors = useSensors(
        useSensor(PointerSensor, {
            activationConstraint: {
                distance: 5,
            },
        }),
        useSensor(KeyboardSensor, {
            coordinateGetter: sortableKeyboardCoordinates,
        })
    );

    const handleDragOver = (event: DragOverEvent) => {
        const { active, over } = event;
        if (!over) return;

        const activeId = active.id;
        const overId = over.id;

        if (activeId === overId) return;

        const isActiveACard = active.data.current?.type === "Card";
        const isOverACard = over.data.current?.type === "Card";
        const isOverAColumn = over.data.current?.type === "Column";

        if (!isActiveACard) return;

        setBoard((columns) => {
            const activeColumn = columns.find(col => col.cards.some(c => c.id === activeId));
            const activeCard = activeColumn?.cards.find(c => c.id === activeId);

            if (!activeColumn || !activeCard) return columns;

            if (isOverACard) {
                const overColumn = columns.find(col => col.cards.some(c => c.id === overId));
                if (!overColumn) return columns;

                if (activeColumn.id === overColumn.id) return columns;

                const overCardIndex = overColumn.cards.findIndex(c => c.id === overId);
                return columns.map(col => {
                    if (col.id === activeColumn.id) {
                        return { ...col, cards: col.cards.filter(c => c.id !== activeId) };
                    }
                    if (col.id === overColumn.id) {
                        const newCards = [...col.cards];
                        newCards.splice(overCardIndex, 0, activeCard);
                        return { ...col, cards: newCards };
                    }
                    return col;
                });
            }

            if (isOverAColumn) {
                if (activeColumn.id === overId) return columns;

                return columns.map(col => {
                    if (col.id === activeColumn.id) {
                        return { ...col, cards: col.cards.filter(c => c.id !== activeId) };
                    }
                    if (col.id === overId) {
                        return { ...col, cards: [...col.cards, activeCard] };
                    }
                    return col;
                });
            }

            return columns;
        });
    };

    const handleDragEnd = (event: DragEndEvent) => {
        const { active, over } = event;
        if (!over) return;

        const activeId = active.id;
        const overId = over.id;

        if (activeId === overId) return;

        setBoard((columns) => {
            const activeColumn = columns.find(col => col.cards.some(c => c.id === activeId));
            const overColumn = columns.find(col => col.cards.some(c => c.id === overId));

            if (!activeColumn || !overColumn) return columns;

            if (activeColumn.id === overColumn.id) {
                const activeIndex = activeColumn.cards.findIndex(c => c.id === activeId);
                const overIndex = overColumn.cards.findIndex(c => c.id === overId);

                return columns.map(col => {
                    if (col.id === activeColumn.id) {
                        return { ...col, cards: arrayMove(col.cards, activeIndex, overIndex) };
                    }
                    return col;
                });
            }

            return columns;
        });
    };

    return (
        <DndContext
            id="kanban-dnd-context"
            sensors={sensors}
            collisionDetection={closestCorners}
            onDragOver={handleDragOver}
            onDragEnd={handleDragEnd}
        >
            <div className="flex flex-col h-full bg-zinc-50/50 dark:bg-zinc-950/50 overflow-hidden">
                <div className="flex flex-col md:flex-row md:items-center justify-between gap-3 md:gap-4 min-h-14 border-b dark:border-zinc-800 bg-white dark:bg-zinc-900/50 px-4 md:px-8 py-3 md:py-0 shrink-0">
                    <div className="flex items-center gap-2 text-[13px] shrink-0">
                        <span className="text-muted-foreground">Total: <span className="font-semibold text-foreground">17 Leads</span></span>
                        <span className="text-muted-foreground">•</span>
                        <span className="text-muted-foreground">Closed: <span className="font-semibold text-foreground">8 Deals</span></span>
                    </div>

                    <div className="flex items-center gap-2 md:gap-3 overflow-x-auto overflow-y-hidden no-scrollbar w-full md:w-auto md:pb-0 shrink-0">
                        <Tabs defaultValue="kanban" className="w-auto shrink-0">
                            <TabsList className="h-8! rounded-lg bg-muted/50 border p-0">
                                <TabsTrigger value="kanban" className="h-full w-9 p-0 rounded-lg data-[state=active]:bg-background data-[state=active]:shadow-xs hover:bg-muted/80 transition-colors duration-200 outline-none focus-visible:ring-0">
                                    <IconLayoutColumns className="size-4" strokeWidth={2} />
                                </TabsTrigger>
                                <TabsTrigger value="list" className="h-full w-9 p-0 rounded-lg data-[state=active]:bg-background data-[state=active]:shadow-xs hover:bg-muted/80 transition-colors duration-200 outline-none focus-visible:ring-0">
                                    <IconLayoutList className="size-4" strokeWidth={2} />
                                </TabsTrigger>
                            </TabsList>
                        </Tabs>

                        <Select defaultValue="all">
                            <SelectTrigger className="h-8! w-fit gap-1 rounded-lg border bg-background px-2.5 hover:bg-muted/50 transition-colors duration-200 font-medium text-[13px] shrink-0 outline-none focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0">
                                <SelectValue placeholder="All leads" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">All leads</SelectItem>
                                <SelectItem value="active">Active leads</SelectItem>
                                <SelectItem value="lost">Lost leads</SelectItem>
                            </SelectContent>
                        </Select>

                        <Popover>
                            <PopoverTrigger asChild>
                                <Button variant="outline" className="h-8 px-2.5 rounded-lg gap-1.5 font-medium text-[13px] hover:bg-muted/50 transition-colors duration-200 shrink-0 outline-none focus-visible:ring-0">
                                    <IconAdjustmentsHorizontal className="size-4" strokeWidth={2} />
                                    Filter
                                </Button>
                            </PopoverTrigger>
                            <PopoverContent align="end" className="w-64 p-3 shadow-lg border-neutral-200 dark:border-zinc-800">
                                <h4 className="font-semibold text-sm mb-3">Filter Leads</h4>
                                <div className="flex flex-col gap-3">
                                    <div className="flex flex-col gap-1.5">
                                        <Label className="text-xs">Assigned to</Label>
                                        <Select defaultValue="any">
                                            <SelectTrigger className="h-8 text-xs outline-none focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0">
                                                <SelectValue placeholder="Select user" />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectItem value="any">Any user</SelectItem>
                                                <SelectItem value="me">Assigned to me</SelectItem>
                                            </SelectContent>
                                        </Select>
                                    </div>
                                    <div className="flex flex-col gap-1.5">
                                        <Label className="text-xs">Date matched</Label>
                                        <Select defaultValue="any">
                                            <SelectTrigger className="h-8 text-xs outline-none focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0">
                                                <SelectValue placeholder="Select date range" />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectItem value="any">Any time</SelectItem>
                                                <SelectItem value="today">Today</SelectItem>
                                                <SelectItem value="week">This week</SelectItem>
                                            </SelectContent>
                                        </Select>
                                    </div>
                                </div>
                            </PopoverContent>
                        </Popover>

                        <Dialog>
                            <DialogTrigger asChild>
                                <Button className="h-8 px-2.5 rounded-lg gap-1.5 text-[13px] font-semibold bg-zinc-950 text-white hover:bg-zinc-800 hover:shadow-md transition-colors duration-200 shrink-0 outline-none focus-visible:ring-0">
                                    <IconCirclePlus className="size-4" strokeWidth={2.5} />
                                    Add lead
                                </Button>
                            </DialogTrigger>
                            <DialogContent className="sm:max-w-[425px]">
                                <DialogHeader>
                                    <DialogTitle>Create New Lead</DialogTitle>
                                    <DialogDescription>
                                        Add a new lead to the Kanban board.
                                    </DialogDescription>
                                </DialogHeader>
                                <div className="grid gap-4 py-4">
                                    <div className="grid gap-2">
                                        <Label htmlFor="company">Company / Title</Label>
                                        <Input id="company" placeholder="e.g. Acme Corp Web Redesign" className="focus-visible:ring-0 focus-visible:border-neutral-400 dark:focus-visible:border-neutral-600 outline-none shadow-none transition-colors" />
                                    </div>
                                    <div className="grid gap-2">
                                        <Label htmlFor="contact">Primary Contact</Label>
                                        <Input id="contact" placeholder="e.g. John Doe" className="focus-visible:ring-0 focus-visible:border-neutral-400 dark:focus-visible:border-neutral-600 outline-none shadow-none transition-colors" />
                                    </div>
                                    <div className="grid gap-2">
                                        <Label htmlFor="status">Initial Status</Label>
                                        <Select defaultValue="contacted">
                                            <SelectTrigger className="outline-none focus:ring-0 focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-neutral-400 dark:focus:border-neutral-600 shadow-none transition-colors">
                                                <SelectValue />
                                            </SelectTrigger>
                                            <SelectContent>
                                                <SelectItem value="contacted">Contacted</SelectItem>
                                                <SelectItem value="negotiation">Negotiation</SelectItem>
                                                <SelectItem value="won">Closed Won</SelectItem>
                                            </SelectContent>
                                        </Select>
                                    </div>
                                </div>
                                <DialogFooter>
                                    <Button type="submit">Create Lead</Button>
                                </DialogFooter>
                            </DialogContent>
                        </Dialog>
                    </div>
                </div>

                <div className="flex-1 overflow-hidden px-4 md:px-8 py-4 md:py-6 min-h-0 flex flex-col">
                    <div className="flex lg:grid lg:grid-cols-4 overflow-x-auto lg:overflow-visible snap-x snap-mandatory lg:snap-none gap-4 md:gap-6 w-full max-w-(--breakpoint-2xl) mx-auto flex-1 min-h-0 pb-4 no-scrollbar items-start">
                        {board.map((column) => (
                            <BoardColumn key={column.id} column={column}>
                                <SortableContext
                                    items={column.cards.map(c => c.id)}
                                    strategy={verticalListSortingStrategy}
                                >
                                    {column.cards.map((card) => (
                                        <KanbanCard key={card.id} card={card} columnId={column.id} />
                                    ))}
                                </SortableContext>

                                <Dialog>
                                    <DialogTrigger asChild>
                                        <Button variant="outline" className="h-10 w-full rounded-lg border-neutral-200 dark:border-zinc-800 bg-white/50 dark:bg-zinc-900/50 hover:bg-white dark:hover:bg-zinc-800 hover:border-neutral-300 dark:hover:border-zinc-700 gap-1.5 text-muted-foreground font-semibold text-sm shadow-xs hover:shadow-sm transition-colors duration-200 shrink-0 outline-none focus-visible:ring-0">
                                            <IconPlus className="size-4" />
                                            Add
                                        </Button>
                                    </DialogTrigger>
                                    <DialogContent className="sm:max-w-[425px]">
                                        <DialogHeader>
                                            <DialogTitle>Add card to {column.title}</DialogTitle>
                                            <DialogDescription>
                                                Create a new lead card in this column.
                                            </DialogDescription>
                                        </DialogHeader>
                                        <div className="grid gap-4 py-4">
                                            <div className="grid gap-2">
                                                <Label htmlFor="title">Lead Title</Label>
                                                <Input id="title" placeholder="e.g. Acme Corp Redesign" className="focus-visible:ring-0 focus-visible:border-neutral-400 dark:focus-visible:border-neutral-600 outline-none shadow-none transition-colors" />
                                            </div>
                                            <div className="grid gap-2">
                                                <Label htmlFor="desc">Description</Label>
                                                <Input id="desc" placeholder="Brief details about the lead..." className="focus-visible:ring-0 focus-visible:border-neutral-400 dark:focus-visible:border-neutral-600 outline-none shadow-none transition-colors" />
                                            </div>
                                        </div>
                                        <DialogFooter>
                                            <Button type="submit">Create Card</Button>
                                        </DialogFooter>
                                    </DialogContent>
                                </Dialog>
                            </BoardColumn>
                        ))}
                    </div>
                </div>
            </div>
        </DndContext>
    )
}
```
