# Portfolio dashboard

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

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

## Install

```bash
npx shadcn@latest add https://registry.watermelon.sh/r/portfolio-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: `@tabler/icons-react`, `class-variance-authority`, `lucide-react`, `next-themes`, `react-router-dom`, `recharts`
- Registry items: `avatar`, `badge`, `button`, `card`, `dropdown-menu`, `input`, `separator`, `sheet`, `sidebar`, `skeleton`, `tooltip`

## Files

### `src/components/dashboards/portfolio-dashboard/components/portfolio/dashboard-content.tsx`

```tsx
import {
  AlarmClock,
  ArrowRight,
  Download,
  Plus,
  SlidersHorizontal,
  TriangleAlert,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { StatsGrid } from "./stats";
import { PolicyCard } from "./policy-card";
import { policies } from "../../data"; 
import { ActivityFeed, RiskPanel, UpcomingRenewals } from "./lower-panels";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export function DashboardContent() {
  return (
    <main className="mx-auto w-full max-w-screen-2xl flex-1 p-4 md:p-8">
      <div className="mb-6 flex flex-col gap-4 xl:flex-row xl:items-end xl:justify-between">
        <div>
          <h1 className="text-balance text-2xl font-semibold tracking-tight">
            Good Morning, Vansh
          </h1>
          <div className="mt-4 flex flex-wrap gap-3 text-sm">
            <span className="flex items-center gap-2 rounded-full px-3 py-1.5 shadow-border">
              <AlarmClock className="size-4" />3 renewals due this week
            </span>
            <span className="flex items-center gap-2 rounded-full bg-amber-100 px-3 py-1.5 text-amber-500 font-medium dark:bg-amber-950 border border-amber-500/20">
              <TriangleAlert className="size-4" />2 claims require your review
            </span>
          </div>
        </div>
        <div className="flex gap-2">
          <Button className="gap-2 min-h-10 shadow-primary border border-primary">
            New Policy <Plus />
          </Button>
          <Button variant="outline" className="gap-2 min-h-10 shadow-border border-0">
            Export <Download />
          </Button>
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="outline" className="gap-2 min-h-10 shadow-border border-0">
                Filter <SlidersHorizontal className="size-4" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-48">
              <DropdownMenuLabel>Filter Policies</DropdownMenuLabel>
              <DropdownMenuSeparator />
              <DropdownMenuCheckboxItem checked>Active Policies</DropdownMenuCheckboxItem>
              <DropdownMenuCheckboxItem>Pending Renewal</DropdownMenuCheckboxItem>
              <DropdownMenuCheckboxItem checked>High Risk</DropdownMenuCheckboxItem>
              <DropdownMenuCheckboxItem>Open Claims</DropdownMenuCheckboxItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem className="text-red-600 focus:bg-red-50 focus:text-red-600 dark:focus:bg-red-950/50 dark:focus:text-red-500">
                Clear Filters
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>
      <StatsGrid />
      <section className="mt-8 grid gap-4 xl:grid-cols-[3fr_1fr]">
        <div className="flex flex-col">
          <div className="mb-4 flex items-center justify-between">
            <h2 className="text-lg font-medium">Policy Portfolio</h2>
            <Button variant="outline" className="border-0 shadow-border bg-white">
              View all 1235 <ArrowRight />
            </Button>
          </div>
          <div className="grid flex-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
            {policies.map((policy) => (
              <PolicyCard
                key={policy.initials + policy.status}
                policy={policy}
              />
            ))}
          </div>
        </div>
        <div className="flex flex-col">
          <div className="mb-4 flex items-center justify-between">
            <h2 className="text-lg font-medium">AI Insights</h2>
            <Button variant="outline" size="icon" className=" shadow-border border-0 bg-white">
              <ArrowRight />
            </Button>
          </div>
          <Card className="flex flex-1 flex-col gap-3 rounded-2xl p-3 shadow-border">
            <p className="rounded-xl bg-muted p-3 text-sm text-muted-foreground">
              “Henderson Corp renewal due in 4 days. Del Sol property risk score
              elevated, 3 open claims correlate with weather events. 2 policies
              lapsing this month if no action taken.”
            </p>
            <p className="rounded-xl bg-muted p-3 text-sm text-muted-foreground">
              “Pinnacle Group upcoming audit in 10 days. Coastal region risk
              factors increasing, 4 claims associated with flooding incidents. 3
              policies need renewal confirmation this quarter.”
            </p>
            <div className="mt-auto grid grid-cols-2 gap-3 border-t border-border/50 pt-3">
              <Button variant="outline" className="bg-white border-0 shadow-border">Dismiss ×</Button>
              <Button className="min-h-8 border border-primary shadow-primary">
                Open report <ArrowRight />
              </Button>
            </div>
          </Card>
        </div>
      </section>
      <div className="mt-8 grid gap-4 lg:grid-cols-[1.4fr_1fr_1fr]">
        <ActivityFeed />
        <UpcomingRenewals />
        <RiskPanel />
      </div>
    </main>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/logo-icon.tsx`

```tsx
export default function LogoIcon({ className }: { className?: string }) {
  return (
    <svg
      className={className}
      width="785"
      height="506"
      viewBox="0 0 785 506"
      fill="currentColor"
      xmlns="http://www.w3.org/2000/svg"
    >
      <path
        d="M392.688 104.141C299.504 104.141 291.288 234.316 261.147 234.316C231.007 234.316 230.996 0 121.38 0C-30.726 0 -49.9098 505.63 121.38 505.63C196.742 505.63 218.672 442.598 252.926 442.598C287.179 442.598 322.801 505.63 392.688 505.63C462.575 505.63 496.832 442.598 531.085 442.598C565.339 442.598 587.269 505.63 662.631 505.63C833.921 505.63 814.737 0 662.631 0C553.015 0 553.004 234.316 522.864 234.316C492.723 234.316 485.872 104.141 392.688 104.141Z"
        fill="currentColor"
      />
      <circle cx="515.226" cy="332.977" r="46.5892" fill="black" />
      <circle cx="268.575" cy="332.976" r="46.5892" fill="black" />
    </svg>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/lower-panels.tsx`

```tsx
import { activities, renewals } from "../../data"
import { Card } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
export function ActivityFeed() {
  return (
    <section className="flex h-full flex-col">
      <h2 className="mb-3 text-lg font-medium">Activity Feed</h2>
      <Card className="flex-1 gap-0 rounded-2xl p-3 shadow-border">
        {activities.map(([time, title, sub]) => (
          <div
            key={title}
            className="grid grid-cols-[5rem_1fr] gap-3 border-b px-1 py-4 last:border-0"
          >
            <span className="text-xs text-muted-foreground">{time}</span>
            <div>
              <p className="text-sm">{title}</p>
              <p className="mt-1 text-xs text-muted-foreground">{sub}</p>
            </div>
          </div>
        ))}
      </Card>
    </section>
  );
}
export function UpcomingRenewals() {
  return (
    <section className="flex h-full flex-col">
      <h2 className="mb-3 text-lg font-medium">Upcoming Renewals</h2>
      <Card className="flex-1 gap-0 rounded-2xl p-3 shadow-border">
        {renewals.map(([initials, name, type, days, tone]) => (
          <div
            key={name + days}
            className="flex items-center gap-3 border-b py-4 last:border-0"
          >
            <span className="grid size-9 place-items-center rounded-xl bg-blue-100 text-xs text-primary dark:bg-blue-950">
              {initials}
            </span>
            <div>
              <p className="text-sm">{name}</p>
              <p className="text-xs text-muted-foreground">{type}</p>
            </div>
            <Badge
              variant="secondary"
              className={`ml-auto bg-${tone}-100 text-${tone}-600 dark:bg-${tone}-950 dark:text-${tone}-50`}
            >
              {days}
            </Badge>
          </div>
        ))}
      </Card>
    </section>
  );
}
export function RiskPanel() {
  const rows = [
    ["Property", 12, "rose"],
    ["Vehicle", 8, "blue"],
    ["Liability", 9, "amber"],
    ["Life & health", 3, "green"],
  ] as const;
  return (
    <section className="flex h-full flex-col">
      <h2 className="mb-3 text-lg font-medium">Portfolio Risk</h2>
      <Card className="flex-1 gap-0 rounded-2xl p-4 shadow-border">
        {rows.map(([label, bars, tone]) => (
          <div
            key={label}
            className="flex items-center border-b py-5 last:border-0"
          >
            <span className="w-28 text-sm">{label}</span>
            <div className="flex flex-1 gap-1">
              {Array.from({ length: bars }).map((_, i) => (
                <span
                  key={i}
                  className={`h-4 w-1 rounded-full bg-${tone}-500`}
                />
              ))}
            </div>
            <span className="tabular-nums">72</span>
          </div>
        ))}
      </Card>
    </section>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/policy-card.tsx`

```tsx
import { CalendarDays, CircleDollarSign } from "lucide-react";
import { Card } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
export function PolicyCard({
  policy,
}: {
  policy: {
    initials: string;
    name: string;
    type: string;
    status: string;
    tone: string;
    price: string;
    detail: string;
  };
}) {
  const tones: Record<string, string> = {
    green: "bg-green-100 text-green-600 dark:bg-green-950",
    pink: "bg-pink-100 text-pink-600 dark:bg-pink-950",
    amber: "bg-amber-100 text-amber-600 dark:bg-amber-950",
    red: "bg-red-100 text-red-600 dark:bg-red-950",
  };
  return (
    <Card className="gap-5 rounded-2xl p-3 shadow-border transition-[box-shadow,scale] hover:shadow-border-hover active:scale-[0.96]">
      <div className="flex items-start justify-between">
        <span className="grid size-10 place-items-center rounded-xl bg-blue-100 text-sm text-primary dark:bg-blue-950">
          {policy.initials}
        </span>
        <Badge variant="secondary" className={tones[policy.tone]}>
          {policy.status}
        </Badge>
      </div>
      <div className="flex-1">
        <h3 className="font-medium text-lg">{policy.name}</h3>
        <p className="text-xs text-muted-foreground">{policy.type}</p>
      </div>
      <div className="flex items-center justify-between border-t border-border/50 pt-3 text-xs">
        <span className="flex items-center gap-1">
          <CircleDollarSign className="size-4" />
          {policy.price}
        </span>
        <span className="flex items-center gap-1 rounded-full px-2 py-1  border border-border shadow-xs">
          {policy.detail.startsWith("Due") ? (
            <CalendarDays className="size-4" />
          ) : null}
          {policy.detail}
        </span>
      </div>
    </Card>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/sidebar.tsx`

```tsx
"use client";

import { Link} from "react-router-dom";

import {
  ArrowUpRight,
  BadgeHelp,
  FileText,
  FolderOpen,
  HelpCircle,
  LayoutGrid,
  Link2,
  MessageSquareMore,
  RefreshCcw,
  Settings,
  UserRound,
  UsersRound,
  X,
} from 'lucide-react';
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarGroupLabel,
  SidebarHeader,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
} from "@/components/ui/sidebar";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { ThemeToggle } from "../theme-toggle";
import LogoIcon from "./logo-icon";

const groups = [
  {
    label: "WORKSPACE",
    items: [
      [LayoutGrid, "Overview", "/", ""],
      [MessageSquareMore, "Policy Threads", "/policy-threads", "123"],
      [FileText, "Documents", "/documents", "3,154"],
      [BadgeHelp, "Claims Hub", "/claims-hub", ""],
      [RefreshCcw, "Renewals", "/renewals", ""],
    ],
  },
  {
    label: "TEAM",
    items: [
      [UsersRound, "Clients", "/clients", ""],
      [FolderOpen, "Shared Portfolio", "/shared-portfolio", ""],
    ],
  },
  {
    label: "CONFIGURE",
    items: [
      [Link2, "Integrations", "/integrations", ""],
      [Settings, "Settings", "/settings", ""],
    ],
  },
] as const;
function Logo() {
  return (
    <div className="flex items-center gap-3">
      <LogoIcon className="size-8 text-primary" />
      <span className="text-xl font-semibold">Watermelon</span>
    </div>
  );
}
export function DashboardSidebar() {
  

  return (
    <Sidebar className="border-border portfolio-dashboard border-r">
      <SidebarHeader className="h-16 flex-row items-center justify-between border-b px-4">
        <Logo />
      </SidebarHeader>
      <SidebarContent className="px-2 py-5">
        {groups.map((group) => (
          <SidebarGroup key={group.label} className="p-0 pb-5">
            <SidebarGroupLabel className="px-3 text-xs font-normal">
              {group.label}
            </SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                {group.items.map(([Icon, label, href, count]) => {
                  const isActive = label === 'Overview';
                  return (
                    <SidebarMenuItem key={label}>
                      <SidebarMenuButton
                        asChild
                        isActive={isActive}
                        className={`h-11 rounded-xl px-3 text-sm data-active:bg-white dark:data-active:bg-zinc-800 ${isActive ? 'text-primary hover:text-primary shadow-border border-0' : 'text-foreground'}`}
                      >
                        <Link to={href}>
                          <Icon
                            className={`size-5 ${isActive ? 'text-primary' : 'text-foreground'}`}
                          />
                          <span
                            className={`${isActive ? 'text-primary' : 'text-foreground'}`}
                          >
                            {label}
                          </span>
                          {count ? (
                            <span className="shadow-border ml-auto rounded-sm bg-white px-2 py-0.5 text-xs dark:bg-zinc-800">
                              {count}
                            </span>
                          ) : null}
                        </Link>
                      </SidebarMenuButton>
                    </SidebarMenuItem>
                  );
                })}
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        ))}
      </SidebarContent>
      <SidebarFooter className="gap-4 p-4">
        <Card className="shadow-border gap-4 rounded-2xl p-4">
          <div className="flex justify-end">
            <Button
              variant="ghost"
              size="icon"
              className="shadow-border size-8"
            >
              <X className="size-4" />
            </Button>
          </div>
          <div className="flex justify-between text-sm">
            <span>Policy queries today</span>
            <strong className="font-medium tabular-nums">714/1000</strong>
          </div>
          <div className="flex gap-1">
            {Array.from({ length: 30 }).map((_, i) => (
              <span
                key={i}
                className={`h-4 w-1 rounded-full ${i < 16 ? 'bg-primary' : 'bg-muted'}`}
              />
            ))}
          </div>
          <Button className="shadow-primary border-primary min-h-10 border">
            Upgrade plan <ArrowUpRight className="size-4" />
          </Button>
        </Card>
        <div className="space-y-1">
          <Button
            variant="ghost"
            className="text-muted-foreground h-10 w-full justify-start gap-3 px-2"
          >
            <HelpCircle />
            Help
          </Button>
          <ThemeToggle />
          <Button
            variant="ghost"
            className="text-muted-foreground h-10 w-full justify-start gap-3 px-2"
          >
            <UserRound />
            Profile
          </Button>
        </div>
      </SidebarFooter>
    </Sidebar>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/stats.tsx`

```tsx
import {
  ArrowDownRight,
  ArrowRight,
  ArrowUpRight,
  File,
  RefreshCcw,
  ShieldCheck,
  WalletCards,
} from "lucide-react";
import { Card } from "@/components/ui/card";

const stats = [
  {
    icon: ShieldCheck,
    label: "Active policies",
    value: "147,392",
    delta: "23",
    period: "this month",
    trend: "up",
    bars: [8, 10, 9, 13, 12, 15, 18, 22, 28, 35],
  },
  {
    icon: WalletCards,
    label: "Premiums Collected",
    value: "$94.2K",
    delta: "8.4%",
    period: "vs last month",
    trend: "up",
    bars: [9, 14, 18, 17, 14, 16, 22, 21, 28, 35],
  },
  {
    icon: File,
    label: "Open Claims",
    value: "17",
    delta: "4",
    period: "this week",
    trend: "down",
    bars: [14, 11, 9, 12, 10, 15,28, 13, 20, 18],
  },
  {
    icon: RefreshCcw,
    label: "Retention Rate",
    value: "91%",
    delta: "Stable",
    period: "",
    trend: "stable",
    bars: [30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
  },
] as const;

const trendStyles = {
  up: {
    text: "text-green-500",
    bar: "bg-green-400/30 last:bg-green-500",
    icon: ArrowUpRight,
  },
  down: {
    text: "text-red-500",
    bar: "bg-red-400/30 last:bg-red-500",
    icon: ArrowDownRight,
  },
  stable: {
    text: "text-blue-400",
    bar: "bg-blue-400/30 last:bg-blue-500",
    icon: ArrowRight,
  },
} as const;

export function StatsGrid() {
  return (
    <Card className="grid gap-0 overflow-hidden rounded-2xl p-0 shadow-border md:grid-cols-2 xl:grid-cols-4">
      {stats.map((stat, index) => {
        const styles = trendStyles[stat.trend];
        const TrendIcon = styles.icon;

        return (
          <div
            key={stat.label}
            className={`p-4 md:p-5 ${
              index ? "border-t md:border-l border-border/50 " : "md:border-0"
            }`}
          >
            <div className="flex items-center gap-2 text-sm">
              <stat.icon className="size-4" />
              {stat.label}
            </div>

            <div className="mt-8 flex items-end justify-between">
              <div>
                <div className="text-3xl font-light tracking-tight tabular-nums">
                  {stat.value}
                </div>

                <div
                  className={`mt-2 flex items-center gap-1 text-xs ${styles.text}`}
                >
                  <TrendIcon className="size-4" />

                  <span>{stat.delta}</span>

                  {stat.period && (
                    <span className="text-muted-foreground">{stat.period}</span>
                  )}
                </div>
              </div>

              <div className="flex items-end gap-1">
                {stat.bars.map((height, i) => (
                  <span
                    key={i}
                    className={`w-1.5 rounded-full ${styles.bar}`}
                    style={{ height }}
                  />
                ))}
              </div>
            </div>
          </div>
        );
      })}
    </Card>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/components/portfolio/topbar.tsx`

```tsx
import { Bell, ChevronDown, CommandIcon, Search } from "lucide-react";
import { SidebarTrigger } from "@/components/ui/sidebar";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

export function DashboardTopbar() {
  return (
    <header className="sticky top-0 z-20 flex h-16 items-center border-b px-4 backdrop-blur md:px-8">
      <SidebarTrigger className="md:hidden" />
      <h1 className="text-base font-semibold">Portfolio Overview</h1>
      <div className="ml-auto flex items-center gap-2">
        <div className="relative hidden md:block">
          <Search className="text-muted-foreground absolute top-3 left-3 size-4" />
          <Input
            className="shadow-border focus-visible:ring-primary/30 focus-visible:border-primary/50 h-10 w-72 rounded-xl border-0 bg-white pr-8 pl-9 focus-visible:border"
            placeholder="find a control"
          />
          <kbd className="text-muted-foreground shadow-border absolute top-2.5 right-2.5 flex items-center gap-1 rounded-sm bg-white px-1 text-sm dark:bg-zinc-800">
            <CommandIcon className="size-3" /> K
          </kbd>
        </div>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              variant="outline"
              size="icon"
              className="shadow-border relative size-10 border-0 bg-white"
            >
              <Bell className="size-4" />
              <span className="bg-destructive absolute top-2.5 right-2.5 size-1.5 rounded-full" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="portfolio-dashboard w-80">
            <DropdownMenuLabel className="flex items-center justify-between">
              Notifications
              <span className="text-muted-foreground text-xs font-normal">
                3 unread
              </span>
            </DropdownMenuLabel>
            <DropdownMenuSeparator />
            <div className="flex flex-col gap-1 p-1">
              <DropdownMenuItem className="flex flex-col items-start gap-1 p-3 whitespace-normal">
                <span className="text-sm font-medium">Policy renewal due</span>
                <span className="text-muted-foreground text-xs">
                  Acme Corp's general liability policy expires in 2 days.
                </span>
                <span className="text-muted-foreground mt-1 text-[10px]">
                  2 hours ago
                </span>
              </DropdownMenuItem>
              <DropdownMenuItem className="flex flex-col items-start gap-1 p-3 whitespace-normal">
                <span className="text-sm font-medium">New claim filed</span>
                <span className="text-muted-foreground text-xs">
                  Jane Doe has filed a new auto insurance claim.
                </span>
                <span className="text-muted-foreground mt-1 text-[10px]">
                  5 hours ago
                </span>
              </DropdownMenuItem>
              <DropdownMenuItem className="flex flex-col items-start gap-1 p-3 whitespace-normal">
                <span className="text-sm font-medium">System update</span>
                <span className="text-muted-foreground text-xs">
                  Scheduled maintenance will occur tonight at 2 AM EST.
                </span>
                <span className="text-muted-foreground mt-1 text-[10px]">
                  1 day ago
                </span>
              </DropdownMenuItem>
            </div>
            <DropdownMenuSeparator />
            <DropdownMenuItem className="text-primary justify-center text-center text-sm">
              View all notifications
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              variant="outline"
              className="shadow-border h-10 gap-2 rounded-md border-0 bg-white"
            >
              <Avatar className="shadow-border size-6 border-0">
                <AvatarImage src="https://assets.watermelon.sh/wm_ben.png" />
                <AvatarFallback>VP</AvatarFallback>
              </Avatar>
              <span className="hidden sm:inline">Vansh Patel</span>
              <ChevronDown className="size-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-56">
            <DropdownMenuLabel>My Account</DropdownMenuLabel>
            <DropdownMenuSeparator />
            <DropdownMenuItem>Profile</DropdownMenuItem>
            <DropdownMenuItem>Settings</DropdownMenuItem>
            <DropdownMenuItem>Billing</DropdownMenuItem>
            <DropdownMenuSeparator />
            <DropdownMenuItem className="text-red-600 focus:bg-red-50 focus:text-red-600 dark:focus:bg-red-950/50 dark:focus:text-red-500">
              Log out
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </div>
    </header>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/dashboard-layout.tsx`

```tsx
import { DashboardSidebar } from './components/portfolio/sidebar';
import './dashboard.css';

import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';
import type { CSSProperties } from 'react';

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <SidebarProvider
      className="portfolio-dashboard bg-background text-foreground min-h-screen font-sans"
      style={
        {
          '--sidebar-width': 'calc(var(--spacing) * 64)',
          '--sidebar-width-icon': 'calc(var(--spacing) * 14)',
        } as CSSProperties
      }
    >
      <DashboardSidebar />
      <SidebarInset className='bg-background'>{children}</SidebarInset>
    </SidebarProvider>
  );
}
```

### `src/components/dashboards/portfolio-dashboard/dashboard.css`

```css

.portfolio-dashboard {
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.145 0 0);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.145 0 0);
  --primary: oklch(68.5% 0.169 237.323);
  --primary-foreground: oklch(1 0 0);
  --secondary: oklch(0.97 0 0);
  --secondary-foreground: oklch(0.205 0 0);
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);
  --accent: oklch(0.97 0 0);
  --accent-foreground: oklch(0.205 0 0);
  --destructive: oklch(0.577 0.245 27.325);
  --border: oklch(0.922 0 0);
  --input: oklch(0.922 0 0);
  --ring: oklch(0.708 0 0);
  --chart-1: oklch(0.87 0 0);
  --chart-2: oklch(0.556 0 0);
  --chart-3: oklch(0.439 0 0);
  --chart-4: oklch(0.371 0 0);
  --chart-5: oklch(0.269 0 0);
  --radius: 0.625rem;
  --sidebar: oklch(0.985 0.002 250);
  --sidebar-foreground: oklch(0.145 0 0);
  --sidebar-primary: oklch(0.205 0 0);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.97 0 0);
  --sidebar-accent-foreground: oklch(0.205 0 0);
  --sidebar-border: oklch(0.922 0 0);
  --sidebar-ring: oklch(0.708 0 0);
  --background: oklch(0.985 0.002 250);
  --foreground: oklch(0.145 0 0);
  --shadow-border: 0 0 0 0.5px oklch(0 0 0 / 0.06), 0 1px 2px -1px oklch(0 0 0 / 0.06), 0 2px 4px oklch(0 0 0 / 0.04);
  --shadow-border-hover: 0 0 0 0.5px oklch(0 0 0 / 0.08), 0 1px 2px -1px oklch(0 0 0 / 0.08), 0 2px 4px oklch(0 0 0 / 0.06);
  --shadow-primary: inset 0 1px 0 0px rgba(255 255 255 / 0.3);

  background-color: var(--background);
  color: var(--foreground);
}

.portfolio-dashboard.dark,
.dark .portfolio-dashboard {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --card: oklch(0.205 0 0);
  --card-foreground: oklch(0.985 0 0);
  --popover: oklch(0.205 0 0);
  --popover-foreground: oklch(0.985 0 0);
  --primary: oklch(68.5% 0.169 237.323);
  --primary-foreground: oklch(0.205 0 0);
  --secondary: oklch(0.269 0 0);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.269 0 0);
  --muted-foreground: oklch(0.708 0 0);
  --accent: oklch(0.269 0 0);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --ring: oklch(0.556 0 0);
  --chart-1: oklch(0.87 0 0);
  --chart-2: oklch(0.556 0 0);
  --chart-3: oklch(0.439 0 0);
  --chart-4: oklch(0.371 0 0);
  --chart-5: oklch(0.269 0 0);
  --sidebar: oklch(0.205 0 0);
  --sidebar-foreground: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.488 0.243 264.376);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.269 0 0);
  --sidebar-accent-foreground: oklch(0.985 0 0);
  --sidebar-border: oklch(1 0 0 / 10%);
  --sidebar-ring: oklch(0.556 0 0);
  --shadow-border: 0 0 0 1px oklch(1 0 0 / 0.08);
  --shadow-border-hover: 0 0 0 1px oklch(1 0 0 / 0.13);
  --shadow-primary: inset 0 2px 0 0px rgba(255 255 255 / 0.2);
}

.portfolio-dashboard .shadow-border { box-shadow: var(--shadow-border); }
.portfolio-dashboard .shadow-border-hover { box-shadow: var(--shadow-border-hover); }
.portfolio-dashboard .shadow-primary { box-shadow: var(--shadow-primary); }
```

### `src/components/dashboards/portfolio-dashboard/dashboardView.tsx`

```tsx

import { DashboardTopbar } from './components/portfolio/topbar';
import { DashboardContent } from './components/portfolio/dashboard-content';

export default function DashboardView() {
  return (
    <main>
      <DashboardTopbar />
      <DashboardContent />
    </main>
  );
}
```

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

```ts
export const policies = [
  {
    initials: 'HC',
    name: 'Henderson Corp',
    type: 'Commercial Liability',
    status: 'Active',
    tone: 'green',
    price: '$12,400/yr',
    detail: 'Due: Apr 28',
  },
  {
    initials: 'PR',
    name: 'Priya Rajan',
    type: 'Vehicle Insurance',
    status: 'Claim',
    tone: 'pink',
    price: '$2,100/yr',
    detail: 'Claim open',
  },
  {
    initials: 'DS',
    name: 'Henderson Corp',
    type: 'Properties & contents',
    status: 'Review',
    tone: 'amber',
    price: '$8,750/yr',
    detail: 'Risk Flagged',
  },
  {
    initials: 'MA',
    name: 'Malik & Associates',
    type: 'Directors & Officers',
    status: 'Pending',
    tone: 'amber',
    price: '$6,200/yr',
    detail: 'Renewal draft',
  },
  {
    initials: 'GR',
    name: 'Greenfield Retail',
    type: 'Contents cover',
    status: 'Active',
    tone: 'green',
    price: '$2,100/yr',
    detail: 'Due: Jul 26',
  },
  {
    initials: 'NB',
    name: 'N Bergstrom',
    type: 'Lifetime policy',
    status: 'Lapsed',
    tone: 'red',
    price: 'Due: Apr 28',
    detail: 'Follow-up needed',
  },
];
export const activities = [
  [
    'Today - 8:42',
    'Henderson Corp renewed automatically',
    'AI processed commercial liability renewal',
  ],
  [
    'Yesterday',
    'Priya Rajan filed vehicle claim #CLM-0291',
    'Damage estimate: $3,200 · AI summary ready',
  ],
  [
    'Yesterday',
    'Del Sol risk score increased +12%',
    'Review before renewal recommended',
  ],
  [
    'Yesterday',
    'Malik & Assoc. renewal draft generated',
    'Awaiting client approval',
  ],
];
export const renewals = [
  ['GR', 'Greenfield Retail', 'Contents cover', '4 days', 'red'],
  ['MA', 'Malik & Assoc.', 'Directors & Officers', '12 days', 'amber'],
  ['DS', 'Del Sol Properties', 'Property & contents', '12 days', 'amber'],
  ['GR', 'Greenfield Retail', 'Contents cover', '31 days', 'blue'],
];
```

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

```tsx
import DashboardView from "./dashboardView"
import DashboardLayout from "./dashboard-layout"

export default function Web3DashboardDemo() {
    return (
        <DashboardLayout>
            <DashboardView />
        </DashboardLayout>
    )
}
```

### `src/components/dashboards/portfolio-dashboard/portfolio-dashboard.mdx`

```mdx
---
title: portfolio Dashboard
slug: portfolio-dashboard
category: dashboard
image: 'https://assets.watermelon.sh/components/task-management-dashboard.webp'
video: 'https://assets.watermelon.sh/components/task-management-dashboard.mp4'
description: >-
  A unified task management dashboard interface, displaying tasks sorted by
  priority and category.
featured: false
dependencies:
  - lucide-react
  - tabler/icons-react
install:
  - >-
    npx shadcn@latest add
    https://registry.watermelon.sh/r/portfolio-dashboard.json
componentNumber: 15
---
```

### `src/components/dashboards/portfolio-dashboard/components/theme-toggle.tsx`

```tsx
"use client";
import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
export function ThemeToggle() { const { resolvedTheme, setTheme } = useTheme(); const dark = resolvedTheme === "dark"; return <Button variant="ghost" className="h-10 w-full justify-start gap-3 px-2 text-muted-foreground" onClick={() => setTheme(dark ? "light" : "dark")}><span className="relative size-5"><Sun className={`absolute size-5 transition-[opacity,filter,scale] duration-300 ${dark ? "scale-25 opacity-0 blur-sm" : "scale-100 opacity-100"}`} /><Moon className={`absolute size-5 transition-[opacity,filter,scale] duration-300 ${dark ? "scale-100 opacity-100" : "scale-25 opacity-0 blur-sm"}`} /></span>Dark Mode</Button>; }
```
