Skip to content

Commit 31bdf17

Browse files
committed
feat(Dashboard addon feature customisable and dynamic navlist) ✨ : Designed 'MailDisplay' component for detailed mail rendering with comprehensive action buttons, tooltips, popovers, and dropdown menus. Utilized enhanced UI elements like buttons, avatars, labels, and switches for a polished and intuitive mail viewing experience on any page of dashboard.
1 parent 3b62074 commit 31bdf17

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

components/mails/mail-display.tsx

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import { format, addDays, addHours, nextSaturday } from 'date-fns';
2+
3+
import { Archive, Clock, Forward, MoreVertical, Reply, ReplyAll, Trash2 } from 'lucide-react';
4+
5+
import { Mail } from '@/lib/data';
6+
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
7+
import { Button } from '../ui/button';
8+
import { Separator } from '../ui/separator';
9+
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
10+
import { Calendar } from '../ui/calendar';
11+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../ui/dropdown-menu';
12+
import { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar';
13+
import { Label } from '../ui/label';
14+
import { Switch } from '../ui/switch';
15+
16+
interface MailDisplayProps {
17+
mail: Mail | null;
18+
}
19+
20+
export function MailDisplay({ mail }: MailDisplayProps) {
21+
const today = new Date();
22+
23+
return (
24+
<div className="flex h-full flex-col">
25+
<div className="flex items-center p-2">
26+
<div className="flex items-center gap-2">
27+
<Tooltip>
28+
<TooltipTrigger asChild>
29+
<Button variant="ghost" size="icon" disabled={!mail}>
30+
<Archive className="h-4 w-4" />
31+
<span className="sr-only">Archive</span>
32+
</Button>
33+
</TooltipTrigger>
34+
<TooltipContent>Archive</TooltipContent>
35+
</Tooltip>
36+
<Tooltip>
37+
<TooltipTrigger asChild>
38+
<Button variant="ghost" size="icon" disabled={!mail}>
39+
{/* <ArchiveX className="h-4 w-4" /> */}
40+
<span className="sr-only">Move to junk</span>
41+
</Button>
42+
</TooltipTrigger>
43+
<TooltipContent>Move to junk</TooltipContent>
44+
</Tooltip>
45+
<Tooltip>
46+
<TooltipTrigger asChild>
47+
<Button variant="ghost" size="icon" disabled={!mail}>
48+
<Trash2 className="h-4 w-4" />
49+
<span className="sr-only">Move to trash</span>
50+
</Button>
51+
</TooltipTrigger>
52+
<TooltipContent>Move to trash</TooltipContent>
53+
</Tooltip>
54+
<Separator orientation="vertical" className="mx-1 h-6" />
55+
<Tooltip>
56+
<Popover>
57+
<PopoverTrigger asChild>
58+
<TooltipTrigger asChild>
59+
<Button variant="ghost" size="icon" disabled={!mail}>
60+
<Clock className="h-4 w-4" />
61+
<span className="sr-only">Snooze</span>
62+
</Button>
63+
</TooltipTrigger>
64+
</PopoverTrigger>
65+
<PopoverContent className="flex w-[535px] p-0">
66+
<div className="flex flex-col gap-2 border-r px-2 py-4">
67+
<div className="px-4 text-sm font-medium">Snooze until</div>
68+
<div className="grid min-w-[250px] gap-1">
69+
<Button variant="ghost" className="justify-start font-normal">
70+
Later today{' '}
71+
<span className="ml-auto text-muted-foreground">{format(addHours(today, 4), 'E, h:m b')}</span>
72+
</Button>
73+
<Button variant="ghost" className="justify-start font-normal">
74+
Tomorrow
75+
<span className="ml-auto text-muted-foreground">{format(addDays(today, 1), 'E, h:m b')}</span>
76+
</Button>
77+
<Button variant="ghost" className="justify-start font-normal">
78+
This weekend
79+
<span className="ml-auto text-muted-foreground">{format(nextSaturday(today), 'E, h:m b')}</span>
80+
</Button>
81+
<Button variant="ghost" className="justify-start font-normal">
82+
Next week
83+
<span className="ml-auto text-muted-foreground">{format(addDays(today, 7), 'E, h:m b')}</span>
84+
</Button>
85+
</div>
86+
</div>
87+
<div className="p-2">
88+
<Calendar />
89+
</div>
90+
</PopoverContent>
91+
</Popover>
92+
<TooltipContent>Snooze</TooltipContent>
93+
</Tooltip>
94+
</div>
95+
<div className="ml-auto flex items-center gap-2">
96+
<Tooltip>
97+
<TooltipTrigger asChild>
98+
<Button variant="ghost" size="icon" disabled={!mail}>
99+
<Reply className="h-4 w-4" />
100+
<span className="sr-only">Reply</span>
101+
</Button>
102+
</TooltipTrigger>
103+
<TooltipContent>Reply</TooltipContent>
104+
</Tooltip>
105+
<Tooltip>
106+
<TooltipTrigger asChild>
107+
<Button variant="ghost" size="icon" disabled={!mail}>
108+
<ReplyAll className="h-4 w-4" />
109+
<span className="sr-only">Reply all</span>
110+
</Button>
111+
</TooltipTrigger>
112+
<TooltipContent>Reply all</TooltipContent>
113+
</Tooltip>
114+
<Tooltip>
115+
<TooltipTrigger asChild>
116+
<Button variant="ghost" size="icon" disabled={!mail}>
117+
<Forward className="h-4 w-4" />
118+
<span className="sr-only">Forward</span>
119+
</Button>
120+
</TooltipTrigger>
121+
<TooltipContent>Forward</TooltipContent>
122+
</Tooltip>
123+
</div>
124+
<Separator orientation="vertical" className="mx-2 h-6" />
125+
<DropdownMenu>
126+
<DropdownMenuTrigger asChild>
127+
<Button variant="ghost" size="icon" disabled={!mail}>
128+
<MoreVertical className="h-4 w-4" />
129+
<span className="sr-only">More</span>
130+
</Button>
131+
</DropdownMenuTrigger>
132+
<DropdownMenuContent align="end">
133+
<DropdownMenuItem>Mark as unread</DropdownMenuItem>
134+
<DropdownMenuItem>Star thread</DropdownMenuItem>
135+
<DropdownMenuItem>Add label</DropdownMenuItem>
136+
<DropdownMenuItem>Mute thread</DropdownMenuItem>
137+
</DropdownMenuContent>
138+
</DropdownMenu>
139+
</div>
140+
<Separator />
141+
{mail ? (
142+
<div className="flex flex-1 flex-col">
143+
<div className="flex items-start p-4">
144+
<div className="flex items-start gap-4 text-sm">
145+
<Avatar>
146+
<AvatarImage alt={mail.name} />
147+
<AvatarFallback>
148+
{mail.name
149+
.split(' ')
150+
.map((chunk) => chunk[0])
151+
.join('')}
152+
</AvatarFallback>
153+
</Avatar>
154+
<div className="grid gap-1">
155+
<div className="font-semibold">{mail.name}</div>
156+
<div className="line-clamp-1 text-xs">{mail.subject}</div>
157+
<div className="line-clamp-1 text-xs">
158+
<span className="font-medium">Reply-To:</span> {mail.email}
159+
</div>
160+
</div>
161+
</div>
162+
{mail.date && (
163+
<div className="ml-auto text-xs text-muted-foreground">{format(new Date(mail.date), 'PPpp')}</div>
164+
)}
165+
</div>
166+
<Separator />
167+
<div className="flex-1 whitespace-pre-wrap p-4 text-sm">{mail.text}</div>
168+
<Separator className="mt-auto" />
169+
<div className="p-4">
170+
<form>
171+
<div className="grid gap-4">
172+
<textarea className="p-4" placeholder={`Reply ${mail.name}...`} />
173+
<div className="flex items-center">
174+
<Label htmlFor="mute" className="flex items-center gap-2 text-xs font-normal">
175+
<Switch id="mute" aria-label="Mute thread" /> Mute this thread
176+
</Label>
177+
<Button onClick={(e) => e.preventDefault()} size="sm" className="ml-auto">
178+
Send
179+
</Button>
180+
</div>
181+
</div>
182+
</form>
183+
</div>
184+
</div>
185+
) : (
186+
<div className="p-8 text-center text-muted-foreground">No message selected</div>
187+
)}
188+
</div>
189+
);
190+
}

0 commit comments

Comments
 (0)