# Mail dashboard

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

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

## Install

```bash
npx shadcn@latest add https://registry.watermelon.sh/r/mail-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: `@radix-ui/react-avatar`, `@radix-ui/react-collapsible`, `@radix-ui/react-dialog`, `@radix-ui/react-dropdown-menu`, `@radix-ui/react-label`, `@radix-ui/react-separator`, `@radix-ui/react-slot`, `@radix-ui/react-switch`, `@radix-ui/react-tabs`, `@radix-ui/react-tooltip`, `@tabler/icons-react`, `class-variance-authority`, `lucide-react`
- Registry items: `avatar`, `breadcrumb`, `button`, `collapsible`, `dialog`, `dropdown-menu`, `field`, `input`, `label`, `separator`, `sheet`, `sidebar`, `skeleton`, `switch`, `tabs`, `textarea`, `tooltip`, `utils`

## Files

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

```tsx
"use client"

import * as React from "react"

import { NavUser } from "./nav-user"
import {
  Sidebar,
  SidebarContent,
  SidebarFooter,
  SidebarGroup,
  SidebarGroupContent,
  SidebarHeader,
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
} from "@/components/ui/sidebar"

import {
  IconMailFilled,
  IconQuoteFilled,
  IconUserFilled,
  IconStarsFilled,
  IconBulbFilled,
  IconSearch,
  IconArchiveFilled,
} from "@tabler/icons-react";

// This is sample data
const data = {
  user: {
    name: "shadcn",
    email: "m@example.com",
    avatar: "/avatars/shadcn.jpg",
  },
  navMain: [
    {
      title: "Inbox",
      url: "/inbox",
      icon: IconMailFilled,
      isDisabled: true
    },
    {
      title: "Messages",
      url: "#",
      icon: IconQuoteFilled,
      isDisabled: true,
    },
    {
      title: "Profile",
      url: "#",
      icon: IconUserFilled,
      isDisabled: true,
    },
    {
      title: "AI",
      url: "#",
      icon: IconStarsFilled,
      isDisabled: true,
    },
    {
      title: "Ideas",
      url: "#",
      icon: IconBulbFilled,
      isDisabled: true,
    },
    {
      title: "Search",
      url: "#",
      icon: IconSearch,
      isDisabled: true,
    },
    {
      title: "Archive",
      url: "#",
      icon: IconArchiveFilled,
      isDisabled: true,
    },
  ],

}

export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {

  return (
    <Sidebar
      collapsible="icon"
      className="border-r p-2 group-data-[collapsible=icon]:p-0 bg-sidebar"
      {...props}
    >
      <SidebarHeader className="border-b max-md:py-4 py-4 flex items-center justify-start group-data-[collapsible=icon]:justify-center px-4 group-data-[collapsible=icon]:px-0">
        <SidebarMenu className="flex items-center justify-start group-data-[collapsible=icon]:items-center">
          <SidebarMenuItem className="flex items-center justify-start w-full group-data-[collapsible=icon]:justify-center">
            <SidebarMenuButton size="lg" className="group-data-[collapsible=icon]:h-10! group-data-[collapsible=icon]:w-10! group-data-[collapsible=icon]:p-0! flex items-center justify-start group-data-[collapsible=icon]:justify-center bg-orange-600 text-white rounded-lg shadow-[inset_0px_1px_2px_rgba(255,255,255,0.4),inset_0px_-2px_4px_rgba(0,0,0,0.3)] px-3 group-data-[collapsible=icon]:px-0 gap-2">
              <svg
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2.5"
                strokeLinecap="round"
                strokeLinejoin="round"
                className="size-6"
              >
                <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
              </svg>
              <span className="font-medium text-base  md:group-data-[collapsible=icon]:hidden">OceanLabs</span>
            </SidebarMenuButton>
          </SidebarMenuItem>
        </SidebarMenu>
      </SidebarHeader>
      <SidebarContent>
        <SidebarGroup className="p-0">
          <SidebarGroupContent className="px-1.5 group-data-[collapsible=icon]:px-3">
            <SidebarMenu className="gap-3 py-4 flex flex-col items-start group-data-[collapsible=icon]:items-center px-2 group-data-[collapsible=icon]:px-0">
              {data.navMain.map((item) => {
                const isActive = item.title === "Inbox";
                return (
                  <SidebarMenuItem key={item.title} className="w-full">
                    <SidebarMenuButton
                      tooltip={{
                        children: item.title,
                        hidden: false,
                      }}
                      isActive={isActive}
                      className="group-data-[collapsible=icon]:h-10! max-md:h-10 group-data-[collapsible=icon]:w-10! group-data-[collapsible=icon]:p-0! flex items-center justify-start group-data-[collapsible=icon]:justify-center rounded-lg hover:bg-sidebar-accent transition-colors duration-200 data-[active=true]:bg-sidebar-accent data-[active=true]:border data-[active=true]:border-sidebar-border data-[active=true]:shadow-[inset_0px_2px_4px_rgba(0,0,0,0.3)] w-full gap-3 px-3 group-data-[collapsible=icon]:px-0"
                      asChild
                    >
                      <a
                        href={item.isDisabled ? "#" : item.url}
                        onClick={(e) => {
                          if (item.isDisabled) {
                            e.preventDefault();
                          }
                        }}
                        className="flex items-center justify-start group-data-[collapsible=icon]:justify-center text-sidebar-foreground/70 w-full gap-3"
                      >
                        <item.icon stroke={1.5} className="size-6! shrink-0 opacity-80" />
                        <span className="md:group-data-[collapsible=icon]:hidden font-medium">{item.title}</span>
                      </a>
                    </SidebarMenuButton>
                  </SidebarMenuItem>
                );
              })}
            </SidebarMenu>
          </SidebarGroupContent>
        </SidebarGroup>
      </SidebarContent>
      <SidebarFooter className="pt-4 flex items-center justify-start group-data-[collapsible=icon]:justify-center px-2 group-data-[collapsible=icon]:px-0">
        <NavUser user={data.user} />
      </SidebarFooter>
    </Sidebar>
  )
}
```

### `src/components/dashboards/mail-dashboard/components/empty-state.tsx`

```tsx
export function EmptyState() {
  return (
    <div className="flex h-full items-center justify-center text-muted-foreground">
      Select an email to read
    </div>
  )
}
```

### `src/components/dashboards/mail-dashboard/components/mail/mail-list.tsx`

```tsx
"use client"

import { IconBrandSlack, IconClockFilled, IconMailFilled, IconPlus, IconSearch } from "@tabler/icons-react"
import { SidebarInput, SidebarTrigger } from "@/components/ui/sidebar"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { mails as mailData, pinnedUsers, type Mail } from "../../data"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"

export function MailList({
  mails = mailData,
  selectedMailId,
  onSelectMail
}: {
  mails?: Mail[]
  selectedMailId?: string | null
  onSelectMail?: (id: string) => void
}) {
  return (
    <div className="flex flex-col h-full bg-sidebar text-foreground overflow-hidden">
      {/* Search Header */}
      <div className="flex flex-col">
        <div className="relative group border-b p-3 flex items-center gap-2">
          <SidebarTrigger className="md:hidden size-9" />
          <div className="relative flex-1 group">
            <IconSearch className="absolute left-3 top-1/2 -translate-y-1/2 size-5 text-muted-foreground/60 transition-colors" />
            <SidebarInput
              placeholder="search"
              className="pl-9 bg-muted-foreground/10 border-transparent focus:border-neutral-300 dark:focus:border-neutral-700 transition-colors h-9 rounded-lg outline-none focus-visible:ring-0 shadow-none"
            />
            <div className="absolute right-2 top-1/2 -translate-y-1/2 flex items-center gap-1 px-1.5  rounded bg-muted border border-border/50 text-[10px] text-muted-foreground font-medium shadow">
              <span className="text-sm">⌘</span>
              <span>K</span>
            </div>
          </div>
        </div>

        {/* Pinned Section */}
        <div className="flex flex-col gap-3 p-3">
          <div className="text-[11px] font-bold text-muted-foreground uppercase px-1">
            Pinned
          </div>
          <div className="flex items-center justify-between overflow-x-auto px-1">
            {pinnedUsers.map((user) => (
              <div key={user.name} className="flex flex-col items-center gap-2">
                <Avatar className="size-9 transition-transform duration-200 cursor-pointer">
                  <AvatarImage src={user.avatar} className="object-cover" />
                  <AvatarFallback className="bg-muted text-[10px]">{user.name[0]}</AvatarFallback>
                </Avatar>
                <span className="text-xs text-muted-foreground font-medium">{user.name}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Tabs Section */}
      <Tabs defaultValue="email" className="flex-1 flex flex-col min-h-0 ">
        <div className="px-3 max-md:px-5 border-y border-border">
          <TabsList variant="line" className="w-full bg-transparent justify-between gap-6 p-0 h-11!">
            <TabsTrigger
              value="email"
              className="bg-transparent border-none p-0 flex items-center gap-2.5 text-xs  text-muted-foreground data-[state=active]:text-foreground data-[state=active]:bg-transparent transition-colors font-normal max-w-fit px-2.5 data-[state=active]:font-normal"
            >
              <IconMailFilled className="size-5" />
              Email
            </TabsTrigger>
            <TabsTrigger
              disabled
              value="slack"
              className="bg-transparent border-none p-0 flex items-center gap-2.5 text-xs text-muted-foreground data-[state=active]:text-foreground data-[state=active]:bg-transparent transition-colors font-normal max-w-fit px-2.5 data-[state=active]:font-normal"
            >
              <IconBrandSlack className="size-5" />
              Slack
            </TabsTrigger>
            <TabsTrigger
              value="unread"
              disabled
              className="bg-transparent border-none p-0 flex items-center gap-2.5 text-xs text-muted-foreground data-[state=active]:text-foreground data-[state=active]:bg-transparent transition-colors font-normal max-w-fit px-2.5 data-[state=active]:font-normal"
            >
              <IconClockFilled className="size-5" />
              Unread
            </TabsTrigger>
          </TabsList>
        </div>

        {/* Action Button */}
        <div className="px-2 py-2 border-b ">
          <Dialog>
            <DialogTrigger asChild>
              <Button variant="ghost" className="flex justify-start gap-3 w-full h-full pb-2 pt-0 text-muted-foreground hover:text-foreground transition-colors group hover:bg-transparent!">
                <IconPlus className="size-5" />
                <span className="text-sm font-medium text-foreground tracking-tight">New message</span>
              </Button>
            </DialogTrigger>
            <DialogContent className="sm:max-w-[500px]">
              <DialogHeader>
                <DialogTitle>New Message</DialogTitle>
                <DialogDescription>
                  Compose a new email or message.
                </DialogDescription>
              </DialogHeader>
              <div className="grid gap-4 py-4">
                <div className="grid gap-2">
                  <Label htmlFor="to">To</Label>
                  <Input id="to" placeholder="recipient@example.com" 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="subject">Subject</Label>
                  <Input id="subject" placeholder="What is this about?" 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="message">Message</Label>
                  <Textarea id="message" placeholder="Type your message here..." className="min-h-[150px] 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="button" variant="outline" className="mr-auto">Save Draft</Button>
                <Button type="submit">Send Message</Button>
              </DialogFooter>
            </DialogContent>
          </Dialog>
        </div>

        {/* List Content */}
        <div className="flex-1 overflow-y-auto overflow-x-hidden  scrollbar-thin scrollbar-thumb-muted">
          <TabsContent value="email" className="m-0 focus-visible:outline-none flex flex-col gap-1">
            {mails.map((mail) => {
              const isActive = selectedMailId === mail.id
              return (
                <button
                  key={mail.id}
                  type="button"
                  onClick={() => onSelectMail?.(mail.id)}
                  className={cn(
                    "w-full text-left",
                  )}
                >
                  <div className={cn("flex gap-3 p-2 max-md:px-4 transition-colors hover:bg-muted-foreground/5", isActive ? "bg-muted-foreground/10" : "")}>
                    <Avatar className="size-5 shrink-0 border border-border">
                      <AvatarImage src={mail.avatar} className="object-cover" />
                      <AvatarFallback className="bg-muted">{mail.name[0]}</AvatarFallback>
                    </Avatar>
                    <div className="flex-1 min-w-0 space-y-1 border-b pb-1">
                      <div className="flex items-center justify-between">
                        <div className="flex items-center gap-2 truncate">
                          <span className={cn(
                            "text-[11px] font-medium truncate text-foreground/80",
                          )}>
                            {mail.name}
                          </span>
                        </div>
                        <div className="flex items-center gap-1">
                          {mail.unread && (
                            <div className="size-1.5 rounded-full bg-orange-500 shadow-[0_0_8px_rgba(249,115,22,0.4)]" />
                          )}
                          <span className="text-[10px] text-muted-foreground font-medium shrink-0">
                            {mail.date}
                          </span>
                        </div>
                      </div>
                      <h4 className={cn(
                        "text-[13px] font-medium truncate leading-tight text-foreground"
                      )}>
                        {mail.subject}
                      </h4>
                      <p className="text-xs text-muted-foreground line-clamp-1 leading-relaxed">
                        {mail.teaser}
                      </p>
                    </div>
                  </div>
                </button>
              )
            })}
          </TabsContent>
          <TabsContent value="slack" className="m-0 p-8 text-center text-sm text-muted-foreground">
            No slack messages yet.
          </TabsContent>
          <TabsContent value="unread" className="m-0 p-8 text-center text-sm text-muted-foreground">
            No unread messages yet.
          </TabsContent>
        </div>
      </Tabs>
    </div>
  )
}
```

### `src/components/dashboards/mail-dashboard/components/mail/mail-viewer.tsx`

```tsx
import { mails } from "../../data"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import {
  IconChevronDown,
  IconPlus,
  IconFileText,
  IconFolder,
  IconX,
  IconBrandTelegram,
  IconSparkles,
  IconUserCircle,
  IconBookmark,
  IconChevronLeft,
  IconDotsVertical,
  IconShare,
  IconTrash,
  IconArchive
} from "@tabler/icons-react"
import { Textarea } from "@/components/ui/textarea"
import { Field, FieldContent } from "@/components/ui/field"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"

export function MailViewer({ id }: { id: string }) {
  const mail = mails.find((m) => m.id === id)

  if (!mail) return <div>Mail not found</div>

  return (
    <div className="flex flex-col h-full bg-background text-foreground px-8 py-6 max-md:px-4 max-md:py-4 overflow-y-auto scrollbar-hide">
      {/* Header */}
      <div className="flex items-center max-md:items-start gap-3 mb-7 border-b pb-2.5">
        <a
          href="/inbox"
          className="md:hidden p-2 -ml-2.5 hover:bg-muted rounded-full transition-colors "
        >
          <IconChevronLeft className="size-5 text-muted-foreground" />
        </a>
        <Avatar className="size-10 border border-border">
          <AvatarImage src={mail.avatar} className="object-cover" />
          <AvatarFallback className="bg-muted">{mail.name[0]}</AvatarFallback>
        </Avatar>
        <div className="flex flex-col gap-0.5">
          <div className="flex items-center gap-2 max-md:flex-col max-md:items-start max-md:gap-0">
            <span className="font-medium text-foreground text-sm">{mail.name}</span>
            <span className="text-muted-foreground text-sm tracking-tight">{mail.email}</span>
          </div>
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <button className="flex items-center gap-1.5 text-muted-foreground text-sm hover:text-foreground transition-colors rounded px-1 -ml-1">
                <span className="text-muted-foreground">To:</span>
                <span className="font-medium text-foreground/80 text-xs">{mail.to}</span>
                <IconChevronDown className="size-4 text-muted-foreground" />
              </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start" className="w-[300px]">
              <div className="flex flex-col gap-2 p-2 text-sm">
                <div className="grid grid-cols-[80px_1fr] gap-2">
                  <span className="text-muted-foreground text-right">From:</span>
                  <span className="font-medium truncate">{mail.email}</span>
                </div>
                <div className="grid grid-cols-[80px_1fr] gap-2">
                  <span className="text-muted-foreground text-right">To:</span>
                  <span className="font-medium truncate">{mail.to}</span>
                </div>
                <div className="grid grid-cols-[80px_1fr] gap-2">
                  <span className="text-muted-foreground text-right">Date:</span>
                  <span className="font-medium truncate">{mail.date}</span>
                </div>
              </div>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>

      {/* Content */}
      <div className="w-full flex-1 flex flex-col gap-4">
        <h1 className="text-2xl font-medium tracking-tight text-foreground leading-tight">
          {mail.subject}
        </h1>

        <div className="whitespace-pre-wrap text-foreground/80 leading-relaxed text-[15px] border-b pb-6 mt-2">
          {mail.body}
        </div>

        {/* Action Icons */}
        <div className="flex items-center gap-2 px-1">
          <TooltipProvider delayDuration={300}>
            <Tooltip>
              <TooltipTrigger asChild>
                <button className="text-muted-foreground hover:text-foreground hover:bg-muted p-1.5 rounded-md transition-colors outline-none focus-visible:bg-muted">
                  <IconSparkles className="size-5" />
                </button>
              </TooltipTrigger>
              <TooltipContent>AI Reply</TooltipContent>
            </Tooltip>
          </TooltipProvider>

          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <button className="text-muted-foreground hover:text-foreground hover:bg-muted p-1.5 rounded-md transition-colors outline-none focus-visible:bg-muted">
                <IconUserCircle className="size-5" />
              </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start">
              <DropdownMenuItem>View Contact</DropdownMenuItem>
              <DropdownMenuItem>Add to VIPs</DropdownMenuItem>
              <DropdownMenuItem className="text-red-500">Block Sender</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>

          <TooltipProvider delayDuration={300}>
            <Tooltip>
              <TooltipTrigger asChild>
                <button className="text-muted-foreground hover:text-foreground hover:bg-muted p-1.5 rounded-md transition-colors outline-none focus-visible:bg-muted">
                  <IconBookmark className="size-5" />
                </button>
              </TooltipTrigger>
              <TooltipContent>Bookmark</TooltipContent>
            </Tooltip>
          </TooltipProvider>

          <TooltipProvider delayDuration={300}>
            <Tooltip>
              <TooltipTrigger asChild>
                <button className="text-muted-foreground hover:text-foreground hover:bg-muted p-1.5 rounded-md transition-colors outline-none focus-visible:bg-muted">
                  <IconArchive className="size-5" />
                </button>
              </TooltipTrigger>
              <TooltipContent>Archive</TooltipContent>
            </Tooltip>
          </TooltipProvider>

          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <button className="text-muted-foreground hover:text-foreground hover:bg-muted p-1.5 rounded-md transition-colors ml-auto outline-none focus-visible:bg-muted">
                <IconDotsVertical className="size-5" />
              </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem className="gap-2"><IconShare className="size-4" /> Forward</DropdownMenuItem>
              <DropdownMenuItem className="gap-2 text-red-500"><IconTrash className="size-4" /> Delete</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>

        {/* Message Input Area */}
        <Field className="mt-auto bg-muted/70 border border-border/60 rounded-2xl overflow-hidden focus-within:border-border/80 transition-colors p-1.5">
          <FieldContent className="gap-0">
            {/* Attachments Section */}
            <div className="flex items-center gap-2 px-1 pb-2 overflow-x-auto scrollbar-hide">
              <div className="flex items-center gap-1 bg-background hover:bg-muted/50 px-2 py-1.5 rounded-md border border-border transition-colors cursor-pointer group shrink-0 text-foreground shadow-sm">
                <IconFileText className="size-3.5 group-hover:text-foreground" />
                <span className="text-[11px] text-foreground/80 font-medium">agreement.pdf</span>
                <button className="text-muted-foreground hover:text-foreground hover:bg-muted-foreground/20 transition-colors bg-muted rounded p-0.5 ml-0.5 outline-none focus-visible:ring-0">
                  <IconX className="size-3" />
                </button>
              </div>
              <div className="flex items-center gap-1 bg-background hover:bg-muted/50 px-2 py-1.5 rounded-md border border-border transition-colors cursor-pointer group shrink-0 text-foreground shadow-sm">
                <IconFolder className="size-3.5 group-hover:text-foreground" />
                <span className="text-[11px] text-foreground/80 font-medium">Roadmap.pdf</span>
                <button className="text-muted-foreground hover:text-foreground hover:bg-muted-foreground/20 transition-colors bg-muted rounded p-0.5 ml-0.5 outline-none focus-visible:ring-0">
                  <IconX className="size-3" />
                </button>
              </div>
            </div>

            {/* Textarea */}
            <div className="flex flex-col bg-background rounded-xl border border-border">
              <Textarea
                placeholder="type message"
                className="w-full border-none bg-background! focus-visible:ring-0 px-4 py-2 min-h-[100px] max-md:min-h-[70px] text-sm text-foreground/80 placeholder:text-muted-foreground resize-none shadow-none rounded-xl"
              />
              {/* Footer Actions */}
              <div className="p-3 flex items-center justify-between">
                <TooltipProvider delayDuration={300}>
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <button className="p-2 rounded-full bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground hover:shadow-sm transition-colors outline-none focus-visible:ring-0">
                        <IconPlus className="size-4" />
                      </button>
                    </TooltipTrigger>
                    <TooltipContent>Attach files</TooltipContent>
                  </Tooltip>
                </TooltipProvider>

                <Button size="sm" className="bg-orange-600 hover:bg-orange-500 text-white rounded-full px-4 h-9 gap-2 font-medium shadow-[0_0_15px_rgba(249,115,22,0.3)] transition-colors hover:shadow-[0_0_20px_rgba(249,115,22,0.4)] outline-none focus-visible:ring-0">
                  <span>Send</span>
                  <IconBrandTelegram className="size-4" />
                </Button>
              </div>
            </div>
          </FieldContent>
        </Field>
      </div>
    </div>
  )
}
```

### `src/components/dashboards/mail-dashboard/components/mail/workspace-layout.tsx`

```tsx
"use client"

import { cn } from "@/lib/utils"

export function WorkspaceLayout({
  list,
  content,
  isMailDetail = false,
}: {
  list: React.ReactNode
  content: React.ReactNode
  isMailDetail?: boolean
}) {
  return (
    <div className="flex h-screen overflow-hidden">
      {/* SECOND PANEL (LIST) */}
      <div className={cn(
        "w-full md:w-[350px] border-r bg-[#121212]",
        isMailDetail ? "hidden md:block" : "block"
      )}>
        {list}
      </div>

      {/* THIRD PANEL (CONTENT) */}
      <div className={cn(
        "flex-1 overflow-y-auto",
        isMailDetail ? "block" : "hidden md:block"
      )}>
        {content}
      </div>
    </div>
  )
}
```

### `src/components/dashboards/mail-dashboard/components/nav-user.tsx`

```tsx
"use client"

import {
  BadgeCheck,
  Bell,
  ChevronsUpDown,
  CreditCard,
  LogOut,
  Sparkles,
} from "lucide-react"

import {
  Avatar,
  AvatarFallback,
  AvatarImage,
} from "@/components/ui/avatar"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  SidebarMenu,
  SidebarMenuButton,
  SidebarMenuItem,
  useSidebar,
} from "@/components/ui/sidebar"

export function NavUser({
  user,
}: {
  user: {
    name: string
    email: string
    avatar: string
  }
}) {
  const { isMobile } = useSidebar()

  return (
    <SidebarMenu className="flex items-center justify-center group-data-[collapsible=icon]:items-center">
      <SidebarMenuItem className="flex items-center justify-center w-full group-data-[collapsible=icon]:justify-center">
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <SidebarMenuButton
              size="lg"
              className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground flex items-center justify-center group-data-[collapsible=icon]:size-9! group-data-[collapsible=icon]:p-0 hover:bg-transparent w-full gap-2 px-2 group-data-[collapsible=icon]:px-0"
            >
              <Avatar className="h-8 w-8 rounded-full shrink-0">
                <AvatarImage src={user.avatar} alt={user.name} />
                <AvatarFallback className="rounded-full dark:bg-zinc-700 bg-muted-foreground/10 text-xs font-medium">CN</AvatarFallback>
              </Avatar>

              <div className="grid flex-1 text-left text-sm leading-tight md:group-data-[collapsible=icon]:hidden">
                <span className="truncate font-medium text-foreground">{user.name}</span>
                <span className="truncate text-xs text-muted-foreground">{user.email}</span>
              </div>
              <ChevronsUpDown className="ml-auto size-4 md:group-data-[collapsible=icon]:hidden text-muted-foreground" />
            </SidebarMenuButton>
          </DropdownMenuTrigger>
          <DropdownMenuContent
            className="w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg"
            side={isMobile ? "bottom" : "right"}
            align="end"
            sideOffset={4}
          >
            <DropdownMenuLabel className="p-0 font-normal">
              <div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
                <Avatar className="h-8 w-8 rounded-lg">
                  <AvatarImage src={user.avatar} alt={user.name} />
                  <AvatarFallback className="rounded-lg">CN</AvatarFallback>
                </Avatar>
                <div className="grid flex-1 text-left text-sm leading-tight">
                  <span className="truncate font-medium">{user.name}</span>
                  <span className="truncate text-xs">{user.email}</span>
                </div>
              </div>
            </DropdownMenuLabel>
            <DropdownMenuSeparator />
            <DropdownMenuGroup>
              <DropdownMenuItem>
                <Sparkles />
                Upgrade to Pro
              </DropdownMenuItem>
            </DropdownMenuGroup>
            <DropdownMenuSeparator />
            <DropdownMenuGroup>
              <DropdownMenuItem>
                <BadgeCheck />
                Account
              </DropdownMenuItem>
              <DropdownMenuItem>
                <CreditCard />
                Billing
              </DropdownMenuItem>
              <DropdownMenuItem>
                <Bell />
                Notifications
              </DropdownMenuItem>
            </DropdownMenuGroup>
            <DropdownMenuSeparator />
            <DropdownMenuItem>
              <LogOut />
              Log out
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </SidebarMenuItem>
    </SidebarMenu>
  )
}
```

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

```tsx
"use client"

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

export function DashboardLayout({ children }: { children: React.ReactNode }) {
    return (
        <SidebarProvider className="bg-background"
            defaultOpen={false}
            style={{
                "--sidebar-width-icon": "4rem",
            } as React.CSSProperties}
        >
            <AppSidebar />
            <SidebarInset>
                {children}
            </SidebarInset>
        </SidebarProvider>
    )
}
```

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

```ts
export type Mail = {
  id: string
  name: string
  email: string
  to: string
  subject: string
  date: string
  body: string
  teaser: string
  avatar: string
  unread: boolean
}

export const pinnedUsers = [
  {
    name: "Stephen",
    avatar: "https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=100&h=100&fit=crop",
  },
  {
    name: "Yolanthe",
    avatar: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=100&h=100&fit=crop",
  },
  {
    name: "Lysander",
    avatar: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop",
  },
  {
    name: "Gerind",
    avatar: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop",
  },
  {
    name: "Lina",
    avatar: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=100&h=100&fit=crop",
  },
]

export const mails: Mail[] = [
  {
    id: "1",
    name: "Srotimi Stephen",
    email: "stephen@srotimi.design",
    to: "Yolanthe Einger",
    subject: "Action Required: Product Roadmap Discussion",
    date: "10:18",
    body: "Hi Team 👋,\n\nI hope this message finds you well. Following our productive meeting last week, I'd like to formally propose a follow-up meeting regarding the product roadmap.\n\nYour insights are invaluable, and I believe a focused session will help us align on key priorities and strategic initiatives. Please come prepared to discuss potential adjustments based on recent market trends and user feedback.\n\nLet's aim to finalize the roadmap by the end of this week to ensure we stay on track with our goals.\n\nBest regards,\nSrotimi Stephen",
    teaser: "Hi Team 👋, I hope this message finds you well. Following our productive meeting...",
    avatar: "https://images.unsplash.com/photo-1539571696357-5a69c17a67c6?w=100&h=100&fit=crop",
    unread: true,
  },
  {
    id: "2",
    name: "Emily Johnson",
    email: "emily@example.com",
    to: "Srotimi Stephen",
    subject: "Update Needed: User Feedback Analysis",
    date: "10:45",
    body: "Hi All, I've compiled the feedback from our most recent user testing session. There are some critical areas that need immediate attention before the next sprint.",
    teaser: "Hi All, I've compiled the feedback from our most recent user testing session...",
    avatar: "https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=100&h=100&fit=crop",
    unread: false,
  },
  {
    id: "3",
    name: "Marcus Lee",
    email: "marcus@example.com",
    to: "Srotimi Stephen",
    subject: "Follow-Up: Marketing Strategy Meeting",
    date: "11:00",
    body: "Hello Team, I'd like to revisit our marketing strategy for the upcoming Q3 launch. We need to align on the core messaging and channel prioritization.",
    teaser: "Hello Team, I'd like to revisit our marketing strategy meeting notes...",
    avatar: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&h=100&fit=crop",
    unread: true,
  },
  {
    id: "4",
    name: "Lina Chen",
    email: "lina@example.com",
    to: "Srotimi Stephen",
    subject: "Deadline Reminder: UI Design Submission",
    date: "11:30",
    body: "Hey Everyone, Just a reminder that the UI designs for the new dashboard modules are due this Friday. Please let me know if you hit any blockers.",
    teaser: "Hey Everyone, Just a reminder that UI design submission is due...",
    avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=100&h=100&fit=crop",
    unread: false,
  },
  {
    id: "5",
    name: "David Kim",
    email: "david@example.com",
    to: "Srotimi Stephen",
    subject: "New Task: Analyze Competitor Features",
    date: "12:05",
    body: "Hi Team, I've assigned a new task to analyze competitor features in the fintech space. This will help us refine our own feature prioritization.",
    teaser: "Hi Team, I've assigned a new task to analyze competitor features...",
    avatar: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=100&h=100&fit=crop",
    unread: false,
  },
  {
    id: "6",
    name: "Sophia Patel",
    email: "sophia@example.com",
    to: "Srotimi Stephen",
    subject: "Request for Information: User Experience...",
    date: "12:30",
    body: "Hi Everyone, Can someone share the latest user experience survey results? I need them for the presentation I'm preparing for the board meeting.",
    teaser: "Hi Everyone, Can someone share the latest user experience survey...",
    avatar: "https://images.unsplash.com/photo-1517841905240-472988babdf9?w=100&h=100&fit=crop",
    unread: false,
  },
  {
    id: "7",
    name: "James O'Connor",
    email: "james@example.com",
    to: "Srotimi Stephen",
    subject: "Planning Session: Next Sprint Goals",
    date: "13:00",
    body: "Hi Team, Let's schedule a session to outline our goals for the next sprint. I've prepared a draft of what I think we should focus on.",
    teaser: "Hi Team, Let's schedule a session to outline our goals for the next...",
    avatar: "https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=100&h=100&fit=crop",
    unread: false,
  },
]
```

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

```tsx
"use client";

import { useState } from "react";
import { DashboardLayout } from "./dashboardLayout";
import { WorkspaceLayout } from "./components/mail/workspace-layout";
import { MailList } from "./components/mail/mail-list";
import { mails } from "./data";
import { MailViewer } from "./components/mail/mail-viewer";
import { IconMail } from "@tabler/icons-react";

function EmptyState() {
    return (
        <div className="h-full w-full bg-background flex flex-col items-center justify-center p-8">
            <div className="relative mb-12">
                <div className="absolute inset-0 bg-orange-500/10 blur-[100px] rounded-full" />
                <div className="relative size-24 rounded-3xl bg-card border border-border flex items-center justify-center shadow-2xl">
                    <IconMail className="size-10 text-orange-500 drop-shadow-[0_0_15px_rgba(249,115,22,0.4)]" />
                </div>
            </div>
        </div>
    );
}

export default function MailDashboardDemo() {
    const [selectedMailId, setSelectedMailId] = useState<string | null>(null);

    return (
        <DashboardLayout>
            <WorkspaceLayout
                isMailDetail={!!selectedMailId}
                list={
                    <MailList
                        mails={mails}
                        selectedMailId={selectedMailId}
                        onSelectMail={setSelectedMailId}
                    />
                }
                content={
                    selectedMailId ? (
                        <MailViewer id={selectedMailId} />
                    ) : (
                        <EmptyState />
                    )
                }
            />
        </DashboardLayout>
    );
}
```

### `src/components/dashboards/mail-dashboard/inboxLayout.tsx`

```tsx
import { WorkspaceLayout } from "./components/mail/workspace-layout"
import { MailList } from "./components/mail/mail-list"
import { mails } from "./data"

export default function InboxLayout({ children }: { children: React.ReactNode }) {
  return (
    <WorkspaceLayout
      list={<MailList mails={mails} />}
      content={children}
    />
  )
}
```

### `src/components/dashboards/mail-dashboard/inboxView.tsx`

```tsx
import { IconMail } from "@tabler/icons-react"

export default function Page() {
  return (
    <div className="h-full w-full bg-background flex flex-col items-center justify-center p-8">
      <div className="relative mb-12">
        <div className="absolute inset-0 bg-orange-500/10 blur-[100px] rounded-full" />
        <div className="relative size-24 rounded-3xl bg-card border border-border flex items-center justify-center shadow-2xl">
          <IconMail className="size-10 text-orange-500 drop-shadow-[0_0_15px_rgba(249,115,22,0.4)]" />
        </div>
      </div>
    </div>
  )
}
```

### `src/components/dashboards/mail-dashboard/mailView.tsx`

```tsx
import { MailViewer } from "./components/mail/mail-viewer"

export default async function Page({ params }: { params: { id: string } }) {

   const { id } = await params
   return <MailViewer id={id} />
}
```
