From 6cb006cc136f1fc5c83537cc30c64d223d1755e4 Mon Sep 17 00:00:00 2001 From: Solstice Date: Tue, 9 Jun 2026 00:22:18 -0700 Subject: feat: frontend view, state management, and user interface --- src/components/NotificationOverlay.tsx | 117 +++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/components/NotificationOverlay.tsx (limited to 'src/components/NotificationOverlay.tsx') diff --git a/src/components/NotificationOverlay.tsx b/src/components/NotificationOverlay.tsx new file mode 100644 index 0000000..965f19d --- /dev/null +++ b/src/components/NotificationOverlay.tsx @@ -0,0 +1,117 @@ +import { useEffect, useRef } from 'react'; +import { sendNotification } from '@tauri-apps/plugin-notification'; +import { useTaskStore } from '../store/taskStore'; + +interface NotificationOverlayProps { + visible: boolean; + taskId: string | null; + onDismiss: () => void; +} + +export function NotificationOverlay({ visible, taskId, onDismiss }: NotificationOverlayProps) { + const tasks = useTaskStore((s) => s.tasks); + const timerRef = useRef | null>(null); + + const task = tasks.find((t) => t.id === taskId) ?? null; + + useEffect(() => { + if (!visible) return; + + // OS notification + const body = task ? `"${task.name}" session complete.` : 'Session complete. Time for a break.'; + try { + sendNotification({ title: 'Solstice', body }); + } catch { + // Notifications may not be permitted in dev; ignore errors + } + + // Auto-dismiss after 4 seconds + timerRef.current = setTimeout(() => { + onDismiss(); + }, 4000); + + return () => { + if (timerRef.current) { + clearTimeout(timerRef.current); + } + }; + }, [visible, task, onDismiss]); + + if (!visible) return null; + + return ( +
+
e.stopPropagation()} + style={{ + background: 'var(--ink-2)', + border: '1px solid var(--line-2)', + borderRadius: 'var(--r-3)', + boxShadow: 'var(--shadow-3)', + padding: '24px 32px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '8px', + animation: 'slideDown 0.2s ease', + minWidth: '280px', + }} + > + + Session complete + + {task && ( + + {task.name} + + )} + + Click to dismiss + +
+ + +
+ ); +} -- cgit v1.3-2-g0d8e