diff --git a/src/app/components/offline/OfflineStatusIndicator.tsx b/src/app/components/offline/OfflineStatusIndicator.tsx index 8e4d3721..5c7fdc91 100644 --- a/src/app/components/offline/OfflineStatusIndicator.tsx +++ b/src/app/components/offline/OfflineStatusIndicator.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useState } from 'react'; +import React, { useState, useRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Wifi, @@ -29,11 +29,51 @@ export const OfflineStatusIndicator: React.FC = ({ const [showTooltip, setShowTooltip] = useState(false); const [showSettings, setShowSettings] = useState(false); const [isMounted, setIsMounted] = useState(false); + const [announcement, setAnnouncement] = useState(''); + + const triggerRef = useRef(null); + const panelRef = useRef(null); + const prevOnlineRef = useRef(true); + const prevSyncRef = useRef('idle'); React.useEffect(() => { setIsMounted(true); }, []); + React.useEffect(() => { + if (prevOnlineRef.current !== isOnline) { + setAnnouncement(isOnline ? 'You are back online.' : 'Connection lost. You are offline.'); + prevOnlineRef.current = isOnline; + } + }, [isOnline]); + + React.useEffect(() => { + if (prevSyncRef.current !== syncStatus) { + if (syncStatus === 'error') { + setAnnouncement('Sync failed. Please try again.'); + } else if (syncStatus === 'synced') { + setAnnouncement('Sync complete.'); + } + prevSyncRef.current = syncStatus; + } + }, [syncStatus]); + + React.useEffect(() => { + if (announcement) { + const timer = setTimeout(() => setAnnouncement(''), 7000); + return () => clearTimeout(timer); + } + }, [announcement]); + + React.useEffect(() => { + if (showTooltip && panelRef.current) { + const focusable = panelRef.current.querySelector( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + focusable?.focus(); + } + }, [showTooltip]); + const { isOnline, isOfflineModeEnabled, @@ -146,10 +186,29 @@ export const OfflineStatusIndicator: React.FC = ({ } }; + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Escape' && showTooltip) { + setShowTooltip(false); + e.stopPropagation(); + triggerRef.current?.focus(); + } + }; + return ( -
+
+ {/* Announcements for screen readers */} + + {announcement} + + {/* Main Status Indicator */}