From 1820bcde7774534f784e838a8a7266c30d20e044 Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Sat, 20 Dec 2025 23:13:09 +0100 Subject: [PATCH] feature: Migrate ConfirmDialog and BluetoothDevicePicker to shadcn dialogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Migrated ConfirmDialog to use shadcn AlertDialog component - Replaced custom modal structure with AlertDialogContent, AlertDialogHeader, AlertDialogFooter - Used AlertDialogAction and AlertDialogCancel for buttons - Maintained danger/warning variant support with border-top styling - Simplified code by removing manual escape key handling (built into AlertDialog) - Migrated BluetoothDevicePicker to use shadcn Dialog component - Replaced custom modal structure with DialogContent, DialogHeader, DialogFooter - Used shadcn Button components with outline variant for device selection - Maintained scanning state UI with loading spinner in DialogDescription - Simplified code by removing manual escape key handling (built into Dialog) - Disabled close button for better UX during device selection Both migrations maintain the same external API and functionality while significantly reducing code complexity. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/components/BluetoothDevicePicker.tsx | 173 ++++++++++------------- src/components/ConfirmDialog.tsx | 99 +++++-------- 2 files changed, 104 insertions(+), 168 deletions(-) diff --git a/src/components/BluetoothDevicePicker.tsx b/src/components/BluetoothDevicePicker.tsx index b828d03..c89c5e8 100644 --- a/src/components/BluetoothDevicePicker.tsx +++ b/src/components/BluetoothDevicePicker.tsx @@ -1,5 +1,14 @@ import { useEffect, useState, useCallback } from "react"; import type { BluetoothDevice } from "../types/electron"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; export function BluetoothDevicePicker() { const [devices, setDevices] = useState([]); @@ -40,111 +49,71 @@ export function BluetoothDevicePicker() { setIsScanning(false); }, []); - // Handle escape key - const handleEscape = useCallback( - (e: KeyboardEvent) => { - if (e.key === "Escape") { - handleCancel(); - } - }, - [handleCancel], - ); - - useEffect(() => { - if (isOpen) { - document.addEventListener("keydown", handleEscape); - return () => document.removeEventListener("keydown", handleEscape); - } - }, [isOpen, handleEscape]); - - if (!isOpen) return null; - return ( -
-
e.stopPropagation()} - role="dialog" - aria-labelledby="bluetooth-picker-title" - aria-describedby="bluetooth-picker-message" + !open && handleCancel()}> + -
-

- Select Bluetooth Device -

-
-
- {isScanning && devices.length === 0 ? ( -
- - - - - - Scanning for Bluetooth devices... - -
- ) : ( - <> -

- {devices.length} device{devices.length !== 1 ? "s" : ""} found. - Select a device to connect: -

-
- {devices.map((device) => ( - - ))} + + Select Bluetooth Device + + {isScanning && devices.length === 0 ? ( +
+ + + + + Scanning for Bluetooth devices...
- - )} -
-
- + ))} +
+ )} + + + -
-
-
+ + + + ); } diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index d984cdc..02498a2 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -1,4 +1,14 @@ -import { useEffect, useCallback } from "react"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "@/components/ui/alert-dialog"; +import { cn } from "@/lib/utils"; interface ConfirmDialogProps { isOpen: boolean; @@ -21,75 +31,32 @@ export function ConfirmDialog({ onCancel, variant = "warning", }: ConfirmDialogProps) { - // Handle escape key - const handleEscape = useCallback( - (e: KeyboardEvent) => { - if (e.key === "Escape") { - onCancel(); - } - }, - [onCancel], - ); - - useEffect(() => { - if (isOpen) { - document.addEventListener("keydown", handleEscape); - return () => document.removeEventListener("keydown", handleEscape); - } - }, [isOpen, handleEscape]); - - if (!isOpen) return null; - return ( -
-
e.stopPropagation()} - role="dialog" - aria-labelledby="dialog-title" - aria-describedby="dialog-message" + !open && onCancel()}> + -
-

- {title} -

-
-
-

- {message} -

-
-
- - -
-
-
+ + + + ); }