From 3b06818614998fcbe6a4c36f61dcc8ee74bd71e1 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Sun, 22 Mar 2026 02:15:27 +0100 Subject: [PATCH] feat: rebuild UserSettings with expanded layout and grouped sidebar --- .../src/components/modals/UserSettings.tsx | 158 ++++++++++++++---- 1 file changed, 124 insertions(+), 34 deletions(-) diff --git a/packages/web/src/components/modals/UserSettings.tsx b/packages/web/src/components/modals/UserSettings.tsx index 25a296b3..549b7075 100644 --- a/packages/web/src/components/modals/UserSettings.tsx +++ b/packages/web/src/components/modals/UserSettings.tsx @@ -1,5 +1,6 @@ import { useState, useEffect } from 'react'; import { Modal } from '../ui/Modal'; +import { Avatar } from '../ui/Avatar'; import { useUIStore } from '../../stores/uiStore'; import { useAuthStore } from '../../stores/authStore'; import { AccountPanel } from './settingsPanels/AccountPanel'; @@ -14,10 +15,13 @@ export function UserSettingsModal() { const activeModal = useUIStore((s) => s.activeModal); const modalData = useUIStore((s) => s.modalData); const closeModal = useUIStore((s) => s.closeModal); + const isMobile = useUIStore((s) => s.isMobile); const isAdmin = useAuthStore((s) => s.user?.isAdmin); + const user = useAuthStore((s) => s.user); const logout = useAuthStore((s) => s.logout); const [tab, setTab] = useState('account'); + const [mobileView, setMobileView] = useState<'tabs' | 'content'>('content'); const isOpen = activeModal === 'userSettings'; @@ -35,6 +39,8 @@ export function UserSettingsModal() { } else { setTab('account'); } + // On mobile, if deep-linking to a tab, show content directly + setMobileView(requested ? 'content' : 'tabs'); } }, [isOpen, modalData.tab, isAdmin]); @@ -44,52 +50,136 @@ export function UserSettingsModal() { }; const tabClass = (t: SettingsTab) => - `w-full text-left px-2.5 py-1.5 rounded text-sm transition-colors ${ - tab === t ? 'bg-interactive-selected text-txt-primary' : 'text-txt-tertiary hover:text-txt-secondary hover:bg-interactive-hover' + `w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${ + tab === t ? 'bg-interactive-selected text-txt-primary font-medium' : 'text-txt-tertiary hover:text-txt-secondary hover:bg-interactive-hover' }`; + const handleTabClick = (t: SettingsTab) => { + setTab(t); + if (isMobile) setMobileView('content'); + }; + return ( - -
- {/* Sidebar */} -
-
- - - - - {isAdmin && ( - - )} + +
+ {/* Desktop Sidebar */} +
+ {/* User card */} +
+ +
+
{user?.displayName || user?.username}
+
@{user?.username}
+
-
+ + {/* Nav list */} +
+
User Settings
+ + + + +
+
App Settings
+ + + {isAdmin && ( + <> +
+
Administration
+ + + )} + +
+ +
- {/* Content */} -
- {tab === 'account' && } - {tab === 'voice' && } - {tab === 'privacy' && } - {tab === 'connections' && } - {tab === 'instance' && isAdmin && } -
+ {/* Mobile: Tab list */} + {isMobile && mobileView === 'tabs' && ( +
+ {/* Mobile user card */} +
+ +
+
{user?.displayName || user?.username}
+
@{user?.username}
+
+
+ +
+
User Settings
+ + + + +
+
App Settings
+ + + {isAdmin && ( + <> +
+
Administration
+ + + )} + +
+ +
+
+ )} + + {/* Content area (desktop always, mobile only when viewing content) */} + {(!isMobile || mobileView === 'content') && ( +
+
+ {/* Mobile back button */} + {isMobile && ( + + )} + {tab === 'account' && } + {tab === 'voice' && } + {tab === 'privacy' && } + {tab === 'connections' && } + {tab === 'instance' && isAdmin && } +
+
+ )}
);