diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4d192fe..881ba8e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -54,7 +54,13 @@ const CrackerPanel = lazy(() => const SearchView = lazy(() => import('./components/SearchView').then((m) => ({ default: m.SearchView })) ); -import { Sheet, SheetContent, SheetHeader, SheetTitle } from './components/ui/sheet'; +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from './components/ui/sheet'; import { Toaster, toast } from './components/ui/sonner'; import { getStateKey } from './utils/conversationState'; import { appendRawPacketUnique } from './utils/rawPacketIdentity'; @@ -637,6 +643,12 @@ export function App() { return (
+ + Skip to content + {localLabel.text && (
Navigation + Sidebar navigation
{activeSidebarContent}
-
+
-
+

Node Map -

+
) : activeConversation.type === 'raw' ? ( <> -
+

Raw Packet Feed -

+
@@ -820,12 +833,12 @@ export function App() { {showSettings && (
-
+

Radio & Settings {SETTINGS_SECTION_LABELS[settingsSection]} -

+
{ + // Focus the panel when it becomes visible + if (showCracker && el) { + const focusable = el.querySelector('input, button:not([disabled])'); + if (focusable) setTimeout(() => focusable.focus(), 210); + } + }} className={cn( 'border-t border-border bg-background transition-all duration-200 overflow-hidden', showCracker ? 'h-[275px]' : 'h-0' diff --git a/frontend/src/components/BotCodeEditor.tsx b/frontend/src/components/BotCodeEditor.tsx index 33e716b..486f603 100644 --- a/frontend/src/components/BotCodeEditor.tsx +++ b/frontend/src/components/BotCodeEditor.tsx @@ -25,6 +25,7 @@ export function BotCodeEditor({ value, onChange, id, height = '256px' }: BotCode }} className="text-sm" id={id} + aria-label="Bot code editor" />
); diff --git a/frontend/src/components/ChannelInfoPane.tsx b/frontend/src/components/ChannelInfoPane.tsx index 2614de1..26eeb6d 100644 --- a/frontend/src/components/ChannelInfoPane.tsx +++ b/frontend/src/components/ChannelInfoPane.tsx @@ -3,7 +3,7 @@ import { api } from '../api'; import { formatTime } from '../utils/messageParser'; import { isFavorite } from '../utils/favorites'; import { handleKeyboardActivate } from '../utils/a11y'; -import { Sheet, SheetContent, SheetHeader, SheetTitle } from './ui/sheet'; +import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from './ui/sheet'; import { toast } from './ui/sonner'; import type { Channel, ChannelDetail, Favorite } from '../types'; @@ -65,6 +65,7 @@ export function ChannelInfoPane({ Channel Info + Channel details and statistics {loading && !detail ? ( diff --git a/frontend/src/components/ChatHeader.tsx b/frontend/src/components/ChatHeader.tsx index fbfebd4..414264b 100644 --- a/frontend/src/components/ChatHeader.tsx +++ b/frontend/src/components/ChatHeader.tsx @@ -117,6 +117,7 @@ export function ChatHeader({ ); }} title="Click to copy" + aria-label={conversation.type === 'channel' ? 'Copy channel key' : 'Copy contact key'} > {conversation.type === 'channel' ? conversation.id.toLowerCase() : conversation.id} diff --git a/frontend/src/components/ContactInfoPane.tsx b/frontend/src/components/ContactInfoPane.tsx index c071b78..d89e078 100644 --- a/frontend/src/components/ContactInfoPane.tsx +++ b/frontend/src/components/ContactInfoPane.tsx @@ -6,7 +6,7 @@ import { getMapFocusHash } from '../utils/urlHash'; import { isFavorite } from '../utils/favorites'; import { handleKeyboardActivate } from '../utils/a11y'; import { ContactAvatar } from './ContactAvatar'; -import { Sheet, SheetContent, SheetHeader, SheetTitle } from './ui/sheet'; +import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from './ui/sheet'; import { toast } from './ui/sonner'; import type { Contact, ContactDetail, Favorite, RadioConfig } from '../types'; @@ -98,6 +98,7 @@ export function ContactInfoPane({ Contact Info + Contact details and actions {isNameOnly && nameOnlyValue ? ( diff --git a/frontend/src/components/CrackerPanel.tsx b/frontend/src/components/CrackerPanel.tsx index 4342f5e..73e0110 100644 --- a/frontend/src/components/CrackerPanel.tsx +++ b/frontend/src/components/CrackerPanel.tsx @@ -586,7 +586,14 @@ export function CrackerPanel({ : `${Math.round(progress.etaSeconds / 60)}m`}
-
+
+
WebGPU not available. Cracking requires Chrome 113+ or Edge 113+.
)} {!wordlistLoaded && gpuAvailable !== false && ( -
Loading wordlist...
+
+ Loading wordlist... +
)} {/* Cracked rooms list */} diff --git a/frontend/src/components/MapView.tsx b/frontend/src/components/MapView.tsx index 2c6dea7..388e9eb 100644 --- a/frontend/src/components/MapView.tsx +++ b/frontend/src/components/MapView.tsx @@ -140,22 +140,27 @@ export function MapView({ contacts, focusedKey }: MapViewProps) {
- <1h + - <1d + - <3d + - older +
{/* Map - z-index constrained to stay below modals/sheets */} -
+
{label} @@ -462,8 +463,6 @@ export function MessageList({ className="h-full overflow-y-auto p-4 flex flex-col gap-0.5" ref={listRef} onScroll={handleScroll} - aria-live="polite" - aria-relevant="additions" > {loadingOlder && (
@@ -629,6 +628,7 @@ export function MessageList({ }); }} title="View echo paths" + aria-label={`Acknowledged, ${msg.acked} echo${msg.acked !== 1 ? 's' : ''} — view paths`} >{` ✓${msg.acked > 1 ? msg.acked : ''}`} ) : ( {` ✓${msg.acked > 1 ? msg.acked : ''}`} @@ -649,6 +649,7 @@ export function MessageList({ }); }} title="Message status" + aria-label="No echoes yet — view message status" > {' '} ? diff --git a/frontend/src/components/NeighborsMiniMap.tsx b/frontend/src/components/NeighborsMiniMap.tsx index e878845..c26a297 100644 --- a/frontend/src/components/NeighborsMiniMap.tsx +++ b/frontend/src/components/NeighborsMiniMap.tsx @@ -29,7 +29,11 @@ export function NeighborsMiniMap({ neighbors, radioLat, radioLon, radioName }: P const center: [number, number] = hasRadio ? [radioLat!, radioLon!] : [valid[0].lat, valid[0].lon]; return ( -
+
{pruneStaleNodes && (
- Window: + - min +
)}
{mapExpanded ? 'Hide map' : 'Map route'} diff --git a/frontend/src/components/PathRouteMap.tsx b/frontend/src/components/PathRouteMap.tsx index b778d82..331665b 100644 --- a/frontend/src/components/PathRouteMap.tsx +++ b/frontend/src/components/PathRouteMap.tsx @@ -113,7 +113,12 @@ export function PathRouteMap({ resolved, senderInfo }: PathRouteMapProps) { return (
-
+
+
{sortedPackets.map(({ packet, decoded }) => (