From 8b6eb593d9a8b7ab5f26c6107c946c5562dc1851 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Sun, 21 Dec 2025 00:16:52 +0100 Subject: [PATCH] feature: Add shadcn Tooltips to AppHeader for better UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Migrated serial number tooltip from native title to shadcn Tooltip - Shows formatted machine details (serial, MAC, total stitches, service count) - Better multi-line formatting with proper spacing - Added tooltip to machine status badge - Shows state description explaining current status - Added tooltip to auto-refresh spinner - Shows "Auto-refreshing machine status" - Removed redundant title attributes - Disconnect button already has clear label - Error button has Popover for details Benefits: - Consistent tooltip styling across the app - Better accessibility with ARIA attributes - Improved readability with proper formatting - Better positioning and animations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/components/AppHeader.tsx | 302 +++++++++++++++++++---------------- 1 file changed, 167 insertions(+), 135 deletions(-) diff --git a/src/components/AppHeader.tsx b/src/components/AppHeader.tsx index 41b9036..2f1fe20 100644 --- a/src/components/AppHeader.tsx +++ b/src/components/AppHeader.tsx @@ -15,6 +15,12 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Popover, PopoverTrigger } from "@/components/ui/popover"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; export function AppHeader() { @@ -61,145 +67,171 @@ export function AppHeader() { const StatusIcon = stateIcons[stateVisual.iconName]; return ( -
-
- {/* Machine Connection Status - Responsive width column */} -
-
-
-
-
-

- Respira -

- {isConnected && machineInfo?.serialNumber && ( - - • {machineInfo.serialNumber} - - )} - {isPolling && ( - - )} -
-
- {isConnected ? ( - <> - - - - {machineStatusName} - - - ) : ( -

Not Connected

- )} - - {/* Error indicator - always render to prevent layout shift */} - - - - - - {/* Error popover content */} - {(machineErrorMessage || pyodideError) && ( - + +
+
+ {/* Machine Connection Status - Responsive width column */} +
+
+
+
+
+

+ Respira +

+ {isConnected && machineInfo?.serialNumber && ( + + + + • {machineInfo.serialNumber} + + + +
+

+ Serial: {machineInfo.serialNumber} +

+ {machineInfo.macAddress && ( +

+ MAC: {machineInfo.macAddress} +

+ )} + {machineInfo.totalCount !== undefined && ( +

+ Total stitches:{" "} + {machineInfo.totalCount.toLocaleString()} +

+ )} + {machineInfo.serviceCount !== undefined && ( +

+ Stitches since service:{" "} + {machineInfo.serviceCount.toLocaleString()} +

+ )} +
+
+
)} - + {isPolling && ( + + +
+ +
+
+ +

Auto-refreshing machine status

+
+
+ )} +
+
+ {isConnected ? ( + <> + + + + + + {machineStatusName} + + + +

{stateVisual.description}

+
+
+ + ) : ( +

Not Connected

+ )} + + {/* Error indicator - always render to prevent layout shift */} + + + + + + {/* Error popover content */} + {(machineErrorMessage || pyodideError) && ( + + )} + +
-
- {/* Workflow Stepper - Flexible width column */} -
- + {/* Workflow Stepper - Flexible width column */} +
+ +
-
-
+ + ); }