Polish toast actions and extend delete confirm timeout
- Toast: snooze/dismiss buttons side-by-side on the right, dismiss uses X icon, snooze shows clock icon + 'Snooze' label - SnoozeDropdown trigger now shows text label alongside icon - Delete confirm 'Sure?' lingers 4 seconds instead of 2 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c609e374e7
commit
38bce21ac3
@ -70,7 +70,7 @@ export default function ReminderItem({ reminder, onEdit }: ReminderItemProps) {
|
|||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
if (!confirmingDelete) {
|
if (!confirmingDelete) {
|
||||||
setConfirmingDelete(true);
|
setConfirmingDelete(true);
|
||||||
setTimeout(() => setConfirmingDelete(false), 2000);
|
setTimeout(() => setConfirmingDelete(false), 4000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deleteMutation.mutate();
|
deleteMutation.mutate();
|
||||||
|
|||||||
@ -32,9 +32,10 @@ export default function SnoozeDropdown({ onSnooze, label }: SnoozeDropdownProps)
|
|||||||
<button
|
<button
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => setOpen(!open)}
|
||||||
aria-label={`Snooze "${label}"`}
|
aria-label={`Snooze "${label}"`}
|
||||||
className="p-1 rounded hover:bg-accent/10 hover:text-accent text-muted-foreground transition-colors"
|
className="flex items-center gap-1 px-1.5 py-1 rounded hover:bg-accent/10 hover:text-accent text-muted-foreground transition-colors"
|
||||||
>
|
>
|
||||||
<Clock className="h-3.5 w-3.5" />
|
<Clock className="h-3.5 w-3.5" />
|
||||||
|
<span className="text-[11px] font-medium">Snooze</span>
|
||||||
</button>
|
</button>
|
||||||
{open && (
|
{open && (
|
||||||
<div className="absolute right-0 bottom-full mb-1 w-32 rounded-md border bg-popover shadow-lg z-50 py-1 animate-fade-in">
|
<div className="absolute right-0 bottom-full mb-1 w-32 rounded-md border bg-popover shadow-lg z-50 py-1 animate-fade-in">
|
||||||
|
|||||||
@ -77,7 +77,7 @@ export default function TodoItem({ todo, onEdit }: TodoItemProps) {
|
|||||||
if (!confirmingDelete) {
|
if (!confirmingDelete) {
|
||||||
setConfirmingDelete(true);
|
setConfirmingDelete(true);
|
||||||
// Auto-reset after 2 seconds if not confirmed
|
// Auto-reset after 2 seconds if not confirmed
|
||||||
setTimeout(() => setConfirmingDelete(false), 2000);
|
setTimeout(() => setConfirmingDelete(false), 4000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deleteMutation.mutate();
|
deleteMutation.mutate();
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { createContext, useContext, useRef, useEffect, useCallback, type ReactNo
|
|||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Bell } from 'lucide-react';
|
import { Bell, X } from 'lucide-react';
|
||||||
import api from '@/lib/api';
|
import api from '@/lib/api';
|
||||||
import { getRelativeTime, toLocalDatetime } from '@/lib/date-utils';
|
import { getRelativeTime, toLocalDatetime } from '@/lib/date-utils';
|
||||||
import SnoozeDropdown from '@/components/reminders/SnoozeDropdown';
|
import SnoozeDropdown from '@/components/reminders/SnoozeDropdown';
|
||||||
@ -98,14 +98,15 @@ export function AlertsProvider({ children }: { children: ReactNode }) {
|
|||||||
function renderToast(_t: string | number, reminder: Reminder) {
|
function renderToast(_t: string | number, reminder: Reminder) {
|
||||||
const timeAgo = reminder.remind_at ? getRelativeTime(reminder.remind_at) : '';
|
const timeAgo = reminder.remind_at ? getRelativeTime(reminder.remind_at) : '';
|
||||||
return (
|
return (
|
||||||
<div className="flex items-start gap-3 bg-card border border-border rounded-lg p-3 shadow-lg w-[356px]">
|
<div className="flex items-center gap-3 bg-card border border-border rounded-lg p-3 shadow-lg w-[356px]">
|
||||||
<div className="p-1.5 rounded-md bg-orange-500/10 shrink-0 mt-0.5">
|
<div className="p-1.5 rounded-md bg-orange-500/10 shrink-0">
|
||||||
<Bell className="h-4 w-4 text-orange-400" />
|
<Bell className="h-4 w-4 text-orange-400" />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<p className="text-sm font-medium text-foreground truncate">{reminder.title}</p>
|
<p className="text-sm font-medium text-foreground truncate">{reminder.title}</p>
|
||||||
<p className="text-xs text-muted-foreground mt-0.5">{timeAgo}</p>
|
<p className="text-xs text-muted-foreground mt-0.5">{timeAgo}</p>
|
||||||
<div className="flex items-center gap-1 mt-2">
|
</div>
|
||||||
|
<div className="flex items-center gap-1 shrink-0">
|
||||||
<SnoozeDropdown
|
<SnoozeDropdown
|
||||||
onSnooze={(m) => snoozeRef.current(reminder.id, m)}
|
onSnooze={(m) => snoozeRef.current(reminder.id, m)}
|
||||||
label={reminder.title}
|
label={reminder.title}
|
||||||
@ -113,13 +114,12 @@ export function AlertsProvider({ children }: { children: ReactNode }) {
|
|||||||
<button
|
<button
|
||||||
onClick={() => dismissRef.current(reminder.id)}
|
onClick={() => dismissRef.current(reminder.id)}
|
||||||
aria-label={`Dismiss "${reminder.title}"`}
|
aria-label={`Dismiss "${reminder.title}"`}
|
||||||
className="ml-auto px-2 py-0.5 rounded text-[11px] bg-secondary hover:bg-card-elevated text-muted-foreground hover:text-foreground transition-colors"
|
className="p-1 rounded hover:bg-accent/10 hover:text-accent text-muted-foreground transition-colors"
|
||||||
>
|
>
|
||||||
Dismiss
|
<X className="h-3.5 w-3.5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user