From 090c0d1c3c1b6bf2f569eb4c9e1164523f048319 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sat, 7 Jun 2025 15:11:29 +0000
Subject: feat(web): Redesign the user settings page

---
 apps/web/components/settings/UserOptions.tsx | 192 ++++++++++++++-------------
 1 file changed, 102 insertions(+), 90 deletions(-)

(limited to 'apps/web/components/settings/UserOptions.tsx')

diff --git a/apps/web/components/settings/UserOptions.tsx b/apps/web/components/settings/UserOptions.tsx
index 3918ceed..483c3f2b 100644
--- a/apps/web/components/settings/UserOptions.tsx
+++ b/apps/web/components/settings/UserOptions.tsx
@@ -7,6 +7,7 @@ import { useInterfaceLang } from "@/lib/userLocalSettings/bookmarksLayout";
 import { updateInterfaceLang } from "@/lib/userLocalSettings/userLocalSettings";
 import { useUserSettings } from "@/lib/userSettings";
 import { zodResolver } from "@hookform/resolvers/zod";
+import { Archive, Bookmark, Globe } from "lucide-react";
 import { useForm } from "react-hook-form";
 import { z } from "zod";
 
@@ -17,6 +18,7 @@ import {
   zUserSettingsSchema,
 } from "@karakeep/shared/types/users";
 
+import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
 import { Form, FormField } from "../ui/form";
 import { Label } from "../ui/label";
 import {
@@ -26,6 +28,7 @@ import {
   SelectTrigger,
   SelectValue,
 } from "../ui/select";
+import { Separator } from "../ui/separator";
 import { toast } from "../ui/use-toast";
 
 const LanguageSelect = () => {
@@ -37,7 +40,7 @@ const LanguageSelect = () => {
         await updateInterfaceLang(val);
       }}
     >
-      <SelectTrigger>
+      <SelectTrigger className="h-11">
         <SelectValue />
       </SelectTrigger>
       <SelectContent>
@@ -51,7 +54,7 @@ const LanguageSelect = () => {
   );
 };
 
-export default function UserSettings() {
+export default function UserOptions() {
   const { t } = useTranslation();
   const clientConfig = useClientConfig();
   const data = useUserSettings();
@@ -101,97 +104,106 @@ export default function UserSettings() {
 
   return (
     <Form {...form}>
-      <FormField
-        control={form.control}
-        name="bookmarkClickAction"
-        render={({ field }) => (
-          <div className="flex w-full flex-col gap-2">
-            <Label>
-              {t("settings.info.user_settings.bookmark_click_action.title")}
+      <Card>
+        <CardHeader>
+          <CardTitle className="flex items-center gap-2">
+            <Globe className="h-5 w-5" />
+            {t("settings.info.options")}
+          </CardTitle>
+        </CardHeader>
+        <CardContent className="space-y-6">
+          <div className="space-y-2">
+            <Label className="text-sm font-medium">
+              {t("settings.info.interface_lang")}
             </Label>
-            <Select
-              disabled={!!clientConfig.demoMode}
-              value={field.value}
-              onValueChange={(value) => {
-                mutate({
-                  bookmarkClickAction:
-                    value as ZUserSettings["bookmarkClickAction"],
-                });
-              }}
-            >
-              <SelectTrigger>
-                <SelectValue>
-                  {bookmarkClickActionTranslation[field.value]}
-                </SelectValue>
-              </SelectTrigger>
-              <SelectContent>
-                {Object.entries(bookmarkClickActionTranslation).map(
-                  ([value, label]) => (
-                    <SelectItem key={value} value={value}>
-                      {label}
-                    </SelectItem>
-                  ),
-                )}
-              </SelectContent>
-            </Select>
+            <LanguageSelect />
           </div>
-        )}
-      />
-      <FormField
-        control={form.control}
-        name="archiveDisplayBehaviour"
-        render={({ field }) => (
-          <div className="flex w-full flex-col gap-2">
-            <Label>
-              {t("settings.info.user_settings.archive_display_behaviour.title")}
-            </Label>
-            <Select
-              disabled={!!clientConfig.demoMode}
-              value={field.value}
-              onValueChange={(value) => {
-                mutate({
-                  archiveDisplayBehaviour:
-                    value as ZUserSettings["archiveDisplayBehaviour"],
-                });
-              }}
-            >
-              <SelectTrigger>
-                <SelectValue>
-                  {archiveDisplayBehaviourTranslation[field.value]}
-                </SelectValue>
-              </SelectTrigger>
-              <SelectContent>
-                {Object.entries(archiveDisplayBehaviourTranslation).map(
-                  ([value, label]) => (
-                    <SelectItem key={value} value={value}>
-                      {label}
-                    </SelectItem>
-                  ),
-                )}
-              </SelectContent>
-            </Select>
-          </div>
-        )}
-      />
-    </Form>
-  );
-}
 
-export function UserOptions() {
-  const { t } = useTranslation();
+          <Separator />
 
-  return (
-    <div className="flex flex-col sm:flex-row">
-      <div className="mb-4 w-full text-lg font-medium sm:w-1/3">
-        {t("settings.info.options")}
-      </div>
-      <div className="flex w-full flex-col gap-3">
-        <div className="flex w-full flex-col gap-2">
-          <Label>{t("settings.info.interface_lang")}</Label>
-          <LanguageSelect />
-        </div>
-        <UserSettings />
-      </div>
-    </div>
+          <div className="grid gap-6 md:grid-cols-2">
+            <FormField
+              control={form.control}
+              name="bookmarkClickAction"
+              render={({ field }) => (
+                <div className="space-y-2">
+                  <Label className="flex items-center gap-2 text-sm font-medium">
+                    <Bookmark className="h-4 w-4" />
+                    {t(
+                      "settings.info.user_settings.bookmark_click_action.title",
+                    )}
+                  </Label>
+                  <Select
+                    disabled={!!clientConfig.demoMode}
+                    value={field.value}
+                    onValueChange={(value) => {
+                      mutate({
+                        bookmarkClickAction:
+                          value as ZUserSettings["bookmarkClickAction"],
+                      });
+                    }}
+                  >
+                    <SelectTrigger className="h-11">
+                      <SelectValue>
+                        {bookmarkClickActionTranslation[field.value]}
+                      </SelectValue>
+                    </SelectTrigger>
+                    <SelectContent>
+                      {Object.entries(bookmarkClickActionTranslation).map(
+                        ([value, label]) => (
+                          <SelectItem key={value} value={value}>
+                            {label}
+                          </SelectItem>
+                        ),
+                      )}
+                    </SelectContent>
+                  </Select>
+                </div>
+              )}
+            />
+
+            <FormField
+              control={form.control}
+              name="archiveDisplayBehaviour"
+              render={({ field }) => (
+                <div className="space-y-2">
+                  <Label className="flex items-center gap-2 text-sm font-medium">
+                    <Archive className="h-4 w-4" />
+                    {t(
+                      "settings.info.user_settings.archive_display_behaviour.title",
+                    )}
+                  </Label>
+                  <Select
+                    disabled={!!clientConfig.demoMode}
+                    value={field.value}
+                    onValueChange={(value) => {
+                      mutate({
+                        archiveDisplayBehaviour:
+                          value as ZUserSettings["archiveDisplayBehaviour"],
+                      });
+                    }}
+                  >
+                    <SelectTrigger className="h-11">
+                      <SelectValue>
+                        {archiveDisplayBehaviourTranslation[field.value]}
+                      </SelectValue>
+                    </SelectTrigger>
+                    <SelectContent>
+                      {Object.entries(archiveDisplayBehaviourTranslation).map(
+                        ([value, label]) => (
+                          <SelectItem key={value} value={value}>
+                            {label}
+                          </SelectItem>
+                        ),
+                      )}
+                    </SelectContent>
+                  </Select>
+                </div>
+              )}
+            />
+          </div>
+        </CardContent>
+      </Card>
+    </Form>
   );
 }
-- 
cgit v1.2.3-70-g09d2

