From ff4c1404a6e4c9f381e618a4f27538aa3641c3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Tr=C3=A1vn=C3=ADk?= Date: Wed, 3 Dec 2025 17:31:44 +0100 Subject: [PATCH] feat: add icons to buttons and alerts for improved UI clarity --- .../components/create-repository-form.tsx | 19 ++++++++++++++++--- app/client/components/create-volume-form.tsx | 5 ++++- app/client/components/restore-form.tsx | 4 +++- app/client/components/snapshots-table.tsx | 8 ++++++-- .../schedule-notifications-config.tsx | 5 ++++- .../backups/components/schedule-summary.tsx | 18 ++++++++++++++---- .../components/snapshot-file-browser.tsx | 4 +++- .../modules/backups/routes/backup-details.tsx | 9 ++++++++- .../modules/backups/routes/create-backup.tsx | 3 ++- .../routes/create-notification.tsx | 4 +++- .../routes/notification-details.tsx | 14 +++++++++++--- .../repositories/routes/create-repository.tsx | 4 +++- .../routes/repository-details.tsx | 19 +++++++++++++++---- app/client/modules/repositories/tabs/info.tsx | 12 ++++++++++-- .../modules/repositories/tabs/snapshots.tsx | 3 ++- .../modules/settings/routes/settings.tsx | 5 ++++- .../volumes/components/healthchecks-card.tsx | 3 ++- .../modules/volumes/routes/create-volume.tsx | 4 +++- .../modules/volumes/routes/volume-details.tsx | 10 +++++++++- app/client/modules/volumes/tabs/info.tsx | 11 +++++++++-- 20 files changed, 131 insertions(+), 33 deletions(-) diff --git a/app/client/components/create-repository-form.tsx b/app/client/components/create-repository-form.tsx index 255dd7a..98827f6 100644 --- a/app/client/components/create-repository-form.tsx +++ b/app/client/components/create-repository-form.tsx @@ -2,6 +2,7 @@ import { arktypeResolver } from "@hookform/resolvers/arktype"; import { type } from "arktype"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; +import { Check, Pencil, Save, X } from "lucide-react"; import { cn, slugify } from "~/client/lib/utils"; import { deepClean } from "~/utils/object"; import { Button } from "./ui/button"; @@ -267,6 +268,7 @@ export const CreateRepositoryForm = ({ {form.watch("path") || "/var/lib/zerobyte/repositories"} @@ -292,13 +294,17 @@ export const CreateRepositoryForm = ({ - Cancel + + + Cancel + { setShowPathBrowser(true); setShowPathWarning(false); }} > + I Understand, Continue @@ -320,8 +326,14 @@ export const CreateRepositoryForm = ({ /> - Cancel - setShowPathBrowser(false)}>Done + + + Cancel + + setShowPathBrowser(false)}> + + Done + @@ -775,6 +787,7 @@ export const CreateRepositoryForm = ({ {mode === "update" && ( )} diff --git a/app/client/components/create-volume-form.tsx b/app/client/components/create-volume-form.tsx index a4fa692..a497526 100644 --- a/app/client/components/create-volume-form.tsx +++ b/app/client/components/create-volume-form.tsx @@ -1,7 +1,7 @@ import { arktypeResolver } from "@hookform/resolvers/arktype"; import { useMutation } from "@tanstack/react-query"; import { type } from "arktype"; -import { CheckCircle, Loader2, XCircle } from "lucide-react"; +import { CheckCircle, Loader2, Pencil, Plug, Save, XCircle } from "lucide-react"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { cn, slugify } from "~/client/lib/utils"; @@ -152,6 +152,7 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for
{field.value}
@@ -561,6 +562,7 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for {!testBackendConnection.isPending && testMessage && !testMessage.success && ( )} + {!testBackendConnection.isPending && !testMessage && } {testBackendConnection.isPending ? "Testing..." : testMessage @@ -584,6 +586,7 @@ export const CreateVolumeForm = ({ onSubmit, mode = "create", initialValues, for )} {mode === "update" && ( )} diff --git a/app/client/components/restore-form.tsx b/app/client/components/restore-form.tsx index 4e4f779..b76721e 100644 --- a/app/client/components/restore-form.tsx +++ b/app/client/components/restore-form.tsx @@ -2,7 +2,7 @@ import { useCallback, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "react-router"; import { toast } from "sonner"; -import { ChevronDown, FileIcon, FolderOpen, RotateCcw } from "lucide-react"; +import { ChevronDown, FileIcon, FolderOpen, RotateCcw, X } from "lucide-react"; import { Button } from "~/client/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card"; import { Checkbox } from "~/client/components/ui/checkbox"; @@ -161,9 +161,11 @@ export function RestoreForm({ snapshot, repositoryName, snapshotId, returnPath }
@@ -254,9 +255,11 @@ export const ScheduleNotificationsConfig = ({ scheduleId, destinations }: Props) {hasChanges && (
diff --git a/app/client/modules/backups/components/schedule-summary.tsx b/app/client/modules/backups/components/schedule-summary.tsx index 4422c77..426285f 100644 --- a/app/client/modules/backups/components/schedule-summary.tsx +++ b/app/client/modules/backups/components/schedule-summary.tsx @@ -1,4 +1,4 @@ -import { Eraser, Pencil, Play, Square, Trash2 } from "lucide-react"; +import { Check, Eraser, Pencil, Play, Square, Trash2, X } from "lucide-react"; import { useMemo, useState } from "react"; import { OnOff } from "~/client/components/onoff"; import { Button } from "~/client/components/ui/button"; @@ -199,11 +199,15 @@ export const ScheduleSummary = (props: Props) => {
- Cancel + + + Cancel + + Delete schedule
@@ -220,8 +224,14 @@ export const ScheduleSummary = (props: Props) => {
- Cancel - Run cleanup + + + Cancel + + + + Run cleanup +
diff --git a/app/client/modules/backups/components/snapshot-file-browser.tsx b/app/client/modules/backups/components/snapshot-file-browser.tsx index 8ace50b..94f9555 100644 --- a/app/client/modules/backups/components/snapshot-file-browser.tsx +++ b/app/client/modules/backups/components/snapshot-file-browser.tsx @@ -1,6 +1,6 @@ import { useCallback } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { FileIcon } from "lucide-react"; +import { FileIcon, RotateCcw, Trash2 } from "lucide-react"; import { Link } from "react-router"; import { FileTree } from "~/client/components/file-tree"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/client/components/ui/card"; @@ -98,6 +98,7 @@ export const SnapshotFileBrowser = (props: Props) => { } className={buttonVariants({ variant: "primary", size: "sm" })} > + Restore {onDeleteSnapshot && ( @@ -108,6 +109,7 @@ export const SnapshotFileBrowser = (props: Props) => { disabled={isDeletingSnapshot} loading={isDeletingSnapshot} > + {isDeletingSnapshot ? "Deleting..." : "Delete Snapshot"} )} diff --git a/app/client/modules/backups/routes/backup-details.tsx b/app/client/modules/backups/routes/backup-details.tsx index 727e939..4318599 100644 --- a/app/client/modules/backups/routes/backup-details.tsx +++ b/app/client/modules/backups/routes/backup-details.tsx @@ -2,6 +2,7 @@ import { useId, useState } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { redirect, useNavigate } from "react-router"; import { toast } from "sonner"; +import { Save, Trash2, X } from "lucide-react"; import { Button } from "~/client/components/ui/button"; import { AlertDialog, @@ -201,9 +202,11 @@ export default function ScheduleDetailsPage({ params, loaderData }: Route.Compon
@@ -254,12 +257,16 @@ export default function ScheduleDetailsPage({ params, loaderData }: Route.Compon - Cancel + + + Cancel + + Delete snapshot diff --git a/app/client/modules/backups/routes/create-backup.tsx b/app/client/modules/backups/routes/create-backup.tsx index f982086..f19d7b9 100644 --- a/app/client/modules/backups/routes/create-backup.tsx +++ b/app/client/modules/backups/routes/create-backup.tsx @@ -1,6 +1,6 @@ import { useId, useState } from "react"; import { useMutation, useQuery } from "@tanstack/react-query"; -import { Database, HardDrive } from "lucide-react"; +import { Database, HardDrive, Plus } from "lucide-react"; import { Link, useNavigate } from "react-router"; import { toast } from "sonner"; import { @@ -160,6 +160,7 @@ export default function CreateBackup({ loaderData }: Route.ComponentProps) {
diff --git a/app/client/modules/notifications/routes/create-notification.tsx b/app/client/modules/notifications/routes/create-notification.tsx index 7990d65..1e206d9 100644 --- a/app/client/modules/notifications/routes/create-notification.tsx +++ b/app/client/modules/notifications/routes/create-notification.tsx @@ -1,5 +1,5 @@ import { useMutation } from "@tanstack/react-query"; -import { Bell } from "lucide-react"; +import { Bell, Plus, X } from "lucide-react"; import { useId } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; @@ -65,9 +65,11 @@ export default function CreateNotification() {
diff --git a/app/client/modules/notifications/routes/notification-details.tsx b/app/client/modules/notifications/routes/notification-details.tsx index 082f475..c667536 100644 --- a/app/client/modules/notifications/routes/notification-details.tsx +++ b/app/client/modules/notifications/routes/notification-details.tsx @@ -24,7 +24,7 @@ import { getNotificationDestination } from "~/client/api-client/sdk.gen"; import type { Route } from "./+types/notification-details"; import { cn } from "~/client/lib/utils"; import { Card, CardContent, CardHeader, CardTitle } from "~/client/components/ui/card"; -import { Bell, TestTube2 } from "lucide-react"; +import { Bell, Save, TestTube2, Trash2, X } from "lucide-react"; import { Alert, AlertDescription } from "~/client/components/ui/alert"; import { CreateNotificationForm, type NotificationFormValues } from "../components/create-notification-form"; @@ -147,6 +147,7 @@ export default function NotificationDetailsPage({ loaderData }: Route.ComponentP variant="destructive" loading={deleteDestination.isPending} > + Delete @@ -174,6 +175,7 @@ export default function NotificationDetailsPage({ loaderData }: Route.ComponentP
@@ -190,8 +192,14 @@ export default function NotificationDetailsPage({ loaderData }: Route.ComponentP - Cancel - Delete + + + Cancel + + + + Delete + diff --git a/app/client/modules/repositories/routes/create-repository.tsx b/app/client/modules/repositories/routes/create-repository.tsx index 288e4ea..b4df970 100644 --- a/app/client/modules/repositories/routes/create-repository.tsx +++ b/app/client/modules/repositories/routes/create-repository.tsx @@ -1,5 +1,5 @@ import { useMutation } from "@tanstack/react-query"; -import { Database } from "lucide-react"; +import { Database, Plus, X } from "lucide-react"; import { useId } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; @@ -76,9 +76,11 @@ export default function CreateRepository() { />
diff --git a/app/client/modules/repositories/routes/repository-details.tsx b/app/client/modules/repositories/routes/repository-details.tsx index 6acdbdd..cd1f233 100644 --- a/app/client/modules/repositories/routes/repository-details.tsx +++ b/app/client/modules/repositories/routes/repository-details.tsx @@ -25,7 +25,7 @@ import { cn } from "~/client/lib/utils"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs"; import { RepositoryInfoTabContent } from "../tabs/info"; import { RepositorySnapshotsTabContent } from "../tabs/snapshots"; -import { Loader2 } from "lucide-react"; +import { Loader2, Stethoscope, Trash2, X } from "lucide-react"; export const handle = { breadcrumb: (match: Route.MetaArgs) => [ @@ -152,10 +152,14 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro Running Doctor... ) : ( - "Run Doctor" + <> + + Run Doctor + )} @@ -184,11 +188,15 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro
- Cancel + + + Cancel + + Delete repository
@@ -230,7 +238,10 @@ export default function RepositoryDetailsPage({ loaderData }: Route.ComponentPro )}
- +
diff --git a/app/client/modules/repositories/tabs/info.tsx b/app/client/modules/repositories/tabs/info.tsx index 585a5a1..0f63c19 100644 --- a/app/client/modules/repositories/tabs/info.tsx +++ b/app/client/modules/repositories/tabs/info.tsx @@ -2,6 +2,7 @@ import { useMutation } from "@tanstack/react-query"; import { useState } from "react"; import { toast } from "sonner"; import { useNavigate } from "react-router"; +import { Check, Save, X } from "lucide-react"; import { Card } from "~/client/components/ui/card"; import { Button } from "~/client/components/ui/button"; import { Input } from "~/client/components/ui/input"; @@ -146,6 +147,7 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => {
@@ -159,8 +161,14 @@ export const RepositoryInfoTabContent = ({ repository }: Props) => { Are you sure you want to update the repository settings? - Cancel - Update + + + Cancel + + + + Update + diff --git a/app/client/modules/repositories/tabs/snapshots.tsx b/app/client/modules/repositories/tabs/snapshots.tsx index c0a26ff..17c430c 100644 --- a/app/client/modules/repositories/tabs/snapshots.tsx +++ b/app/client/modules/repositories/tabs/snapshots.tsx @@ -1,5 +1,5 @@ import { useQuery } from "@tanstack/react-query"; -import { Database } from "lucide-react"; +import { Database, X } from "lucide-react"; import { useState } from "react"; import { listSnapshotsOptions } from "~/client/api-client/@tanstack/react-query.gen"; import { SnapshotsTable } from "~/client/components/snapshots-table"; @@ -124,6 +124,7 @@ export const RepositorySnapshotsTabContent = ({ repository }: Props) => {

No snapshots match your search.

diff --git a/app/client/modules/settings/routes/settings.tsx b/app/client/modules/settings/routes/settings.tsx index a539712..7bbd0df 100644 --- a/app/client/modules/settings/routes/settings.tsx +++ b/app/client/modules/settings/routes/settings.tsx @@ -1,5 +1,5 @@ import { useMutation } from "@tanstack/react-query"; -import { Download, KeyRound, User } from "lucide-react"; +import { Download, KeyRound, User, X } from "lucide-react"; import { useState } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; @@ -195,6 +195,7 @@ export default function Settings({ loaderData }: Route.ComponentProps) { /> @@ -252,9 +253,11 @@ export default function Settings({ loaderData }: Route.ComponentProps) { setDownloadPassword(""); }} > + Cancel diff --git a/app/client/modules/volumes/components/healthchecks-card.tsx b/app/client/modules/volumes/components/healthchecks-card.tsx index 49c2e19..198efc4 100644 --- a/app/client/modules/volumes/components/healthchecks-card.tsx +++ b/app/client/modules/volumes/components/healthchecks-card.tsx @@ -1,6 +1,6 @@ import { useMutation } from "@tanstack/react-query"; import { formatDistanceToNow } from "date-fns"; -import { HeartIcon } from "lucide-react"; +import { Activity, HeartIcon } from "lucide-react"; import { toast } from "sonner"; import { healthCheckVolumeMutation, updateVolumeMutation } from "~/client/api-client/@tanstack/react-query.gen"; import { OnOff } from "~/client/components/onoff"; @@ -80,6 +80,7 @@ export const HealthchecksCard = ({ volume }: Props) => { loading={healthcheck.isPending} onClick={() => healthcheck.mutate({ path: { name: volume.name } })} > + Run Health Check diff --git a/app/client/modules/volumes/routes/create-volume.tsx b/app/client/modules/volumes/routes/create-volume.tsx index 15218ac..545cb03 100644 --- a/app/client/modules/volumes/routes/create-volume.tsx +++ b/app/client/modules/volumes/routes/create-volume.tsx @@ -1,5 +1,5 @@ import { useMutation } from "@tanstack/react-query"; -import { HardDrive } from "lucide-react"; +import { HardDrive, Plus, X } from "lucide-react"; import { useId } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; @@ -70,9 +70,11 @@ export default function CreateVolume() {
diff --git a/app/client/modules/volumes/routes/volume-details.tsx b/app/client/modules/volumes/routes/volume-details.tsx index f6802ab..1df9304 100644 --- a/app/client/modules/volumes/routes/volume-details.tsx +++ b/app/client/modules/volumes/routes/volume-details.tsx @@ -2,6 +2,7 @@ import { useMutation, useQuery } from "@tanstack/react-query"; import { useNavigate, useParams, useSearchParams } from "react-router"; import { toast } from "sonner"; import { useState } from "react"; +import { CircleStop, Play, Trash2, X } from "lucide-react"; import { StatusDot } from "~/client/components/status-dot"; import { Button } from "~/client/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/client/components/ui/tabs"; @@ -148,6 +149,7 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) { loading={mountVol.isPending} className={cn({ hidden: volume.status === "mounted" })} > + Mount @@ -200,11 +204,15 @@ export default function VolumeDetails({ loaderData }: Route.ComponentProps) {
- Cancel + + + Cancel + + Delete volume
diff --git a/app/client/modules/volumes/tabs/info.tsx b/app/client/modules/volumes/tabs/info.tsx index 2b21307..5e0d5fe 100644 --- a/app/client/modules/volumes/tabs/info.tsx +++ b/app/client/modules/volumes/tabs/info.tsx @@ -2,6 +2,7 @@ import { useMutation } from "@tanstack/react-query"; import { useState } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; +import { Check, X } from "lucide-react"; import { CreateVolumeForm, type FormValues } from "~/client/components/create-volume-form"; import { AlertDialog, @@ -93,8 +94,14 @@ export const VolumeInfoTabContent = ({ volume, statfs }: Props) => { - Cancel - Update + + + Cancel + + + + Update +