From fda5a0b6d82fb7b9c4a3fd4ca9f1dcc6aa616dc3 Mon Sep 17 00:00:00 2001
From: Adam Shiervani <adam.shiervani@gmail.com>
Date: Tue, 20 May 2025 13:58:57 +0200
Subject: [PATCH] style(ui): enhance checkbox and radio button styling

- Update Checkbox component to use form-checkbox class
- Refactor radio button classes for consistency across components
---
 ui/src/components/Checkbox.tsx       |  2 +-
 ui/src/routes/devices.$id.mount.tsx  | 59 +++++++++++++---------------
 ui/src/routes/welcome-local.mode.tsx |  2 +-
 3 files changed, 30 insertions(+), 33 deletions(-)

diff --git a/ui/src/components/Checkbox.tsx b/ui/src/components/Checkbox.tsx
index cdf29c5..cf9855d 100644
--- a/ui/src/components/Checkbox.tsx
+++ b/ui/src/components/Checkbox.tsx
@@ -12,7 +12,7 @@ const sizes = {
 
 const checkboxVariants = cva({
   base: cx(
-    "block rounded",
+    "form-checkbox block rounded",
 
     // Colors
     "border-slate-300 dark:border-slate-600 bg-slate-50 dark:bg-slate-800 checked:accent-blue-700 checked:dark:accent-blue-500 transition-colors",
diff --git a/ui/src/routes/devices.$id.mount.tsx b/ui/src/routes/devices.$id.mount.tsx
index 475b57b..6f925bf 100644
--- a/ui/src/routes/devices.$id.mount.tsx
+++ b/ui/src/routes/devices.$id.mount.tsx
@@ -7,7 +7,7 @@ import {
   LuCheck,
   LuUpload,
 } from "react-icons/lu";
-import { PlusCircleIcon , ExclamationTriangleIcon } from "@heroicons/react/20/solid";
+import { PlusCircleIcon, ExclamationTriangleIcon } from "@heroicons/react/20/solid";
 import { TrashIcon } from "@heroicons/react/16/solid";
 import { useNavigate } from "react-router-dom";
 
@@ -38,7 +38,6 @@ import {
   useRTCStore,
 } from "../hooks/stores";
 
-
 export default function MountRoute() {
   const navigate = useNavigate();
   {
@@ -284,7 +283,7 @@ function ModeSelectionView({
   return (
     <div className="w-full space-y-4">
       <div className="animate-fadeIn space-y-0">
-        <h2 className="text-lg font-bold leading-tight dark:text-white">
+        <h2 className="text-lg leading-tight font-bold dark:text-white">
           Virtual Media Source
         </h2>
         <div className="text-sm leading-snug text-slate-600 dark:text-slate-400">
@@ -320,7 +319,7 @@ function ModeSelectionView({
         ].map(({ label, description, value: mode, icon: Icon, tag, disabled }, index) => (
           <div
             key={label}
-            className={cx("animate-fadeIn")}
+            className="animate-fadeIn"
             style={{
               animationDuration: "0.7s",
               animationDelay: `${25 * (index * 5)}ms`,
@@ -337,7 +336,7 @@ function ModeSelectionView({
               )}
             >
               <div
-                className="relative z-50 flex select-none flex-col items-start p-4"
+                className="relative z-50 flex flex-col items-start p-4 select-none"
                 onClick={() =>
                   disabled ? null : setSelectedMode(mode as "browser" | "url" | "device")
                 }
@@ -365,7 +364,7 @@ function ModeSelectionView({
                   value={mode}
                   disabled={disabled}
                   checked={selectedMode === mode}
-                  className="absolute right-4 top-4 h-4 w-4 text-blue-700"
+                  className="absolute top-4 right-4 form-radio h-4 w-4 rounded-full text-blue-700"
                 />
               </div>
             </Card>
@@ -442,14 +441,14 @@ function BrowserFileView({
               animationDuration: "0.7s",
             }}
           >
-            <Card className="outline-dashed transition-all duration-300 hover:bg-blue-50/50">
+            <Card className="transition-all duration-300 outline-dashed">
               <div className="w-full px-4 py-12">
                 <div className="flex h-full flex-col items-center justify-center text-center">
                   {selectedFile ? (
                     <>
                       <div className="space-y-1">
                         <LuHardDrive className="mx-auto h-6 w-6 text-blue-700" />
-                        <h3 className="text-sm font-semibold leading-none">
+                        <h3 className="text-sm leading-none font-semibold">
                           {formatters.truncateMiddle(selectedFile.name, 40)}
                         </h3>
                         <p className="text-xs leading-none text-slate-700">
@@ -460,7 +459,7 @@ function BrowserFileView({
                   ) : (
                     <div className="space-y-1">
                       <PlusCircleIcon className="mx-auto h-6 w-6 text-blue-700" />
-                      <h3 className="text-sm font-semibold leading-none">
+                      <h3 className="text-sm leading-none font-semibold">
                         Click to select a file
                       </h3>
                       <p className="text-xs leading-none text-slate-700">
@@ -483,7 +482,7 @@ function BrowserFileView({
       </div>
 
       <div
-        className="flex w-full animate-fadeIn items-end justify-between"
+        className="flex w-full animate-fadeIn items-end justify-between opacity-0"
         style={{
           animationDuration: "0.7s",
           animationDelay: "0.1s",
@@ -628,13 +627,13 @@ function UrlView({
         <h2 className="mb-2 text-sm font-semibold text-black dark:text-white">
           Popular images
         </h2>
-        <Card className="divide-y-slate-800/30 w-full divide-y dark:divide-slate-300/20">
+        <Card className="w-full divide-y divide-slate-800/20 dark:divide-slate-300/20">
           {popularImages.map((image, index) => (
             <div key={index} className="flex items-center justify-between gap-x-4 p-3.5">
               <div className="flex items-center gap-x-4">
                 <img src={image.icon} alt={`${image.name} Icon`} className="w-6" />
                 <div className="flex flex-col gap-y-1">
-                  <h3 className="text-sm font-semibold leading-none dark:text-white">
+                  <h3 className="text-sm leading-none font-semibold dark:text-white">
                     {formatters.truncateMiddle(image.name, 40)}
                   </h3>
                   {image.description && (
@@ -809,7 +808,7 @@ function DeviceFileView({
               <div className="space-y-3">
                 <div className="space-y-1">
                   <PlusCircleIcon className="mx-auto h-6 w-6 text-blue-700 dark:text-blue-500" />
-                  <h3 className="text-sm font-semibold leading-none text-black dark:text-white">
+                  <h3 className="text-sm leading-none font-semibold text-black dark:text-white">
                     No images available
                   </h3>
                   <p className="text-xs leading-none text-slate-700 dark:text-slate-300">
@@ -827,7 +826,7 @@ function DeviceFileView({
               </div>
             </div>
           ) : (
-            <div className="divide-y-slate-800/30 w-full divide-y dark:divide-slate-300/20">
+            <div className="w-full divide-y divide-slate-800/20 dark:divide-slate-300/20">
               {currentFiles.map((file, index) => (
                 <PreUploadedImageItem
                   key={index}
@@ -1267,7 +1266,7 @@ function UploadFileView({
           <div className="group">
             <Card
               className={cx("transition-all duration-300", {
-                "cursor-pointer hover:bg-blue-900/50 dark:hover:bg-blue-900/50":
+                "cursor-pointer hover:bg-blue-50/50 dark:hover:bg-blue-900/50":
                   uploadState === "idle",
               })}
             >
@@ -1282,7 +1281,7 @@ function UploadFileView({
                           </div>
                         </Card>
                       </div>
-                      <h3 className="text-sm font-semibold leading-none text-black dark:text-white">
+                      <h3 className="text-sm leading-none font-semibold text-black dark:text-white">
                         {incompleteFileName
                           ? `Click to select "${incompleteFileName.replace(".incomplete", "")}"`
                           : "Click to select a file"}
@@ -1336,7 +1335,7 @@ function UploadFileView({
                           </div>
                         </Card>
                       </div>
-                      <h3 className="text-sm font-semibold leading-none text-black dark:text-white">
+                      <h3 className="text-sm leading-none font-semibold text-black dark:text-white">
                         Upload successful
                       </h3>
                       <p className="text-xs leading-none text-slate-700 dark:text-slate-300">
@@ -1422,7 +1421,7 @@ function ErrorView({
       <div className="space-y-2">
         <div className="flex items-center space-x-2 text-red-600">
           <ExclamationTriangleIcon className="h-6 w-6" />
-          <h2 className="text-lg font-bold leading-tight">Mount Error</h2>
+          <h2 className="text-lg leading-tight font-bold">Mount Error</h2>
         </div>
         <p className="text-sm leading-snug text-slate-600">
           An error occurred while attempting to mount the media. Please try again.
@@ -1481,8 +1480,8 @@ function PreUploadedImageItem({
       }}
     >
       <div className="flex items-center gap-x-4">
-        <div className="select-none space-y-0.5">
-          <div className="text-sm font-semibold leading-none dark:text-white">
+        <div className="space-y-0.5 select-none">
+          <div className="text-sm leading-none font-semibold dark:text-white">
             {formatters.truncateMiddle(name, 45)}
           </div>
           <div className="flex items-center text-sm">
@@ -1494,7 +1493,7 @@ function PreUploadedImageItem({
           </div>
         </div>
       </div>
-      <div className="relative flex select-none items-center gap-x-3">
+      <div className="relative flex items-center gap-x-3 select-none">
         <div
           className={cx("opacity-0 transition-opacity duration-200", {
             "w-auto opacity-100": isHovering,
@@ -1518,7 +1517,7 @@ function PreUploadedImageItem({
             checked={isSelected}
             onChange={onSelect}
             name={name}
-            className="h-3 w-3 border-slate-800/30 bg-white text-blue-700 focus:ring-blue-500 disabled:opacity-30 dark:border-slate-300/20 dark:bg-slate-800"
+            className="form-radio h-3 w-3 border-slate-800/30 bg-white text-blue-700 focus:ring-blue-500 disabled:opacity-30 dark:border-slate-300/20 dark:bg-slate-800"
             onClick={e => e.stopPropagation()} // Prevent double-firing of onSelect
           />
         ) : (
@@ -1540,7 +1539,7 @@ function PreUploadedImageItem({
 function ViewHeader({ title, description }: { title: string; description: string }) {
   return (
     <div className="space-y-0">
-      <h2 className="text-lg font-bold leading-tight text-black dark:text-white">
+      <h2 className="text-lg leading-tight font-bold text-black dark:text-white">
         {title}
       </h2>
       <div className="text-sm leading-snug text-slate-600 dark:text-slate-400">
@@ -1558,7 +1557,7 @@ function UsbModeSelector({
   setUsbMode: (mode: RemoteVirtualMediaState["mode"]) => void;
 }) {
   return (
-    <div className="flex select-none flex-col items-start space-y-1">
+    <div className="flex flex-col items-start space-y-1 select-none">
       <label className="text-sm font-semibold text-black dark:text-white">Mount as</label>
       <div className="flex space-x-4">
         <label htmlFor="cdrom" className="flex items-center">
@@ -1568,7 +1567,7 @@ function UsbModeSelector({
             name="mountType"
             onChange={() => setUsbMode("CDROM")}
             checked={usbMode === "CDROM"}
-            className="h-3 w-3 border-slate-800/30 bg-white text-blue-700 transition-opacity focus:ring-blue-500 disabled:opacity-30 dark:bg-slate-800"
+            className="form-radio h-3 w-3 rounded-full border-slate-800/30 bg-white text-blue-700 transition-opacity focus:ring-blue-500 disabled:opacity-30 dark:bg-slate-800"
           />
           <span className="ml-2 text-sm font-medium text-slate-900 dark:text-white">
             CD/DVD
@@ -1581,13 +1580,11 @@ function UsbModeSelector({
             name="mountType"
             checked={usbMode === "Disk"}
             onChange={() => setUsbMode("Disk")}
-            className="h-3 w-3 border-slate-800/30 bg-white text-blue-700 transition-opacity focus:ring-blue-500 disabled:opacity-30 dark:bg-slate-800"
+            className="form-radio h-3 w-3 rounded-full border-slate-800/30 bg-white text-blue-700 transition-opacity focus:ring-blue-500 disabled:opacity-30 dark:bg-slate-800"
           />
-          <div className="ml-2 flex flex-col gap-y-0">
-            <span className="text-sm font-medium leading-none text-slate-900 opacity-50 dark:text-white">
-              Disk
-            </span>
-          </div>
+          <span className="ml-2 text-sm font-medium text-slate-900 dark:text-white">
+            Disk
+          </span>
         </label>
       </div>
     </div>
diff --git a/ui/src/routes/welcome-local.mode.tsx b/ui/src/routes/welcome-local.mode.tsx
index a29ee94..06ca62a 100644
--- a/ui/src/routes/welcome-local.mode.tsx
+++ b/ui/src/routes/welcome-local.mode.tsx
@@ -116,7 +116,7 @@ export default function WelcomeLocalModeRoute() {
                           onChange={() => {
                             setSelectedMode(mode as "password" | "noPassword");
                           }}
-                          className="absolute top-2 right-2 h-4 w-4 text-blue-600"
+                          className="form-radio absolute top-2 right-2 h-4 w-4 text-blue-600"
                         />
                       </div>
                     </GridCard>