feat(web): dedicated Delete card per account on the list

Replace the corner trash icon with a separate destructive-themed card
stacked beneath each account card. Whole card is the confirm-dialog
trigger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
yiekheng 2026-05-10 01:02:51 +08:00
parent 2b738383e4
commit b453555a3d

View File

@ -41,7 +41,7 @@ export default async function AccountsPage() {
{accounts.length > 0 ? ( {accounts.length > 0 ? (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3"> <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{accounts.map((account) => ( {accounts.map((account) => (
<div key={account.id} className="relative"> <div key={account.id} className="flex flex-col gap-2">
<Link <Link
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
href={`/accounts/${account.id}` as any} href={`/accounts/${account.id}` as any}
@ -50,7 +50,7 @@ export default async function AccountsPage() {
<Card className="h-full transition-all hover:shadow-md hover:ring-primary/30 cursor-pointer"> <Card className="h-full transition-all hover:shadow-md hover:ring-primary/30 cursor-pointer">
<CardHeader> <CardHeader>
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<CardTitle className="text-base leading-snug pr-8"> <CardTitle className="text-base leading-snug">
{account.label} {account.label}
</CardTitle> </CardTitle>
<AccountStatusBadge status={account.status} /> <AccountStatusBadge status={account.status} />
@ -83,16 +83,28 @@ export default async function AccountsPage() {
</Card> </Card>
</Link> </Link>
{/* Floating delete trigger sits over the card without {/* Dedicated Delete card — entire card is the dialog trigger. */}
blocking the link target on the rest of the surface. */}
<Dialog> <Dialog>
<DialogTrigger asChild> <DialogTrigger asChild>
<button <button
type="button" type="button"
aria-label={`Delete ${account.label}`} className="block w-full text-left rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-destructive focus-visible:ring-offset-2"
className="absolute right-2 top-2 z-10 flex size-7 items-center justify-center rounded-full bg-background/80 text-muted-foreground hover:bg-destructive/10 hover:text-destructive backdrop-blur-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-destructive"
> >
<Trash2Icon className="size-3.5" /> <Card className="transition-all hover:shadow-md hover:ring-destructive/30 cursor-pointer">
<CardContent className="flex items-center gap-3 py-3 px-4">
<div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-destructive/10">
<Trash2Icon className="size-4 text-destructive" />
</div>
<div className="min-w-0 flex-1">
<p className="text-sm font-medium text-destructive">
Delete account
</p>
<p className="text-xs text-muted-foreground truncate">
Remove {account.label} and its reminders & groups
</p>
</div>
</CardContent>
</Card>
</button> </button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>