mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-21 18:55:16 +02:00
feat(icon-rail): integrate user profile component and enhance layout with user settings options
This commit is contained in:
parent
282510f93c
commit
e60c5399af
4 changed files with 62 additions and 20 deletions
|
|
@ -6,6 +6,8 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
|||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { SearchSpace } from "../../types/layout.types";
|
||||
import type { User } from "../../types/layout.types";
|
||||
import { SidebarUserProfile } from "../sidebar/SidebarUserProfile";
|
||||
import { SearchSpaceAvatar } from "./SearchSpaceAvatar";
|
||||
|
||||
interface IconRailProps {
|
||||
|
|
@ -15,6 +17,11 @@ interface IconRailProps {
|
|||
onSearchSpaceDelete?: (searchSpace: SearchSpace) => void;
|
||||
onSearchSpaceSettings?: (searchSpace: SearchSpace) => void;
|
||||
onAddSearchSpace: () => void;
|
||||
user: User;
|
||||
onUserSettings?: () => void;
|
||||
onLogout?: () => void;
|
||||
theme?: string;
|
||||
setTheme?: (theme: "light" | "dark" | "system") => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
|
|
@ -25,11 +32,16 @@ export function IconRail({
|
|||
onSearchSpaceDelete,
|
||||
onSearchSpaceSettings,
|
||||
onAddSearchSpace,
|
||||
user,
|
||||
onUserSettings,
|
||||
onLogout,
|
||||
theme,
|
||||
setTheme,
|
||||
className,
|
||||
}: IconRailProps) {
|
||||
return (
|
||||
<div className={cn("flex h-full w-14 flex-col items-center", className)}>
|
||||
<ScrollArea className="w-full">
|
||||
<div className={cn("flex h-full w-14 min-h-0 flex-col items-center", className)}>
|
||||
<ScrollArea className="w-full min-h-0 flex-1">
|
||||
<div className="flex flex-col items-center gap-2 px-1.5 py-3">
|
||||
{searchSpaces.map((searchSpace) => (
|
||||
<SearchSpaceAvatar
|
||||
|
|
@ -65,6 +77,14 @@ export function IconRail({
|
|||
</Tooltip>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
<SidebarUserProfile
|
||||
user={user}
|
||||
onUserSettings={onUserSettings}
|
||||
onLogout={onLogout}
|
||||
isCollapsed
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -387,6 +387,11 @@ export function LayoutShell({
|
|||
onSearchSpaceDelete={onSearchSpaceDelete}
|
||||
onSearchSpaceSettings={onSearchSpaceSettings}
|
||||
onAddSearchSpace={onAddSearchSpace}
|
||||
user={user}
|
||||
onUserSettings={onUserSettings}
|
||||
onLogout={onLogout}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -423,6 +428,7 @@ export function LayoutShell({
|
|||
pageUsage={pageUsage}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
renderUserProfile={false}
|
||||
className={cn(
|
||||
"flex shrink-0 transition-[border-radius] duration-200",
|
||||
anySlideOutOpen ? "rounded-l-xl delay-0" : "rounded-xl delay-150"
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ interface SidebarProps {
|
|||
disableTooltips?: boolean;
|
||||
sidebarWidth?: number;
|
||||
isResizing?: boolean;
|
||||
renderUserProfile?: boolean;
|
||||
}
|
||||
|
||||
export function Sidebar({
|
||||
|
|
@ -95,6 +96,7 @@ export function Sidebar({
|
|||
disableTooltips = false,
|
||||
sidebarWidth = SIDEBAR_MIN_WIDTH,
|
||||
isResizing = false,
|
||||
renderUserProfile = true,
|
||||
}: SidebarProps) {
|
||||
const t = useTranslations("sidebar");
|
||||
const [openDropdownChatId, setOpenDropdownChatId] = useState<number | null>(null);
|
||||
|
|
@ -275,14 +277,16 @@ export function Sidebar({
|
|||
|
||||
<SidebarUsageFooter pageUsage={pageUsage} isCollapsed={isCollapsed} />
|
||||
|
||||
<SidebarUserProfile
|
||||
user={user}
|
||||
onUserSettings={onUserSettings}
|
||||
onLogout={onLogout}
|
||||
isCollapsed={isCollapsed}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
/>
|
||||
{renderUserProfile && (
|
||||
<SidebarUserProfile
|
||||
user={user}
|
||||
onUserSettings={onUserSettings}
|
||||
onLogout={onLogout}
|
||||
isCollapsed={isCollapsed}
|
||||
theme={theme}
|
||||
setTheme={setTheme}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -113,19 +113,23 @@ function UserAvatar({
|
|||
avatarUrl,
|
||||
initials,
|
||||
bgColor,
|
||||
size = "sm",
|
||||
}: {
|
||||
avatarUrl?: string;
|
||||
initials: string;
|
||||
bgColor: string;
|
||||
size?: "sm" | "md";
|
||||
}) {
|
||||
const sizeClass = size === "md" ? "h-9 w-9" : "h-8 w-8";
|
||||
|
||||
if (avatarUrl) {
|
||||
return (
|
||||
<Image
|
||||
src={avatarUrl}
|
||||
alt="User avatar"
|
||||
width={32}
|
||||
height={32}
|
||||
className="h-8 w-8 shrink-0 rounded-lg object-cover select-none"
|
||||
width={size === "md" ? 36 : 32}
|
||||
height={size === "md" ? 36 : 32}
|
||||
className={cn(sizeClass, "shrink-0 rounded-full object-cover select-none")}
|
||||
referrerPolicy="no-referrer"
|
||||
unoptimized
|
||||
/>
|
||||
|
|
@ -134,7 +138,10 @@ function UserAvatar({
|
|||
|
||||
return (
|
||||
<div
|
||||
className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-xs font-semibold text-white select-none"
|
||||
className={cn(
|
||||
sizeClass,
|
||||
"flex shrink-0 items-center justify-center rounded-full text-xs font-semibold text-white select-none"
|
||||
)}
|
||||
style={{ backgroundColor: bgColor }}
|
||||
>
|
||||
{initials}
|
||||
|
|
@ -181,24 +188,29 @@ export function SidebarUserProfile({
|
|||
// Collapsed view - just show avatar with dropdown
|
||||
if (isCollapsed) {
|
||||
return (
|
||||
<div className="border-t p-2">
|
||||
<div className="border-t px-1.5 py-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"flex h-10 w-full items-center justify-center rounded-md",
|
||||
"hover:bg-accent transition-colors",
|
||||
"mx-auto flex h-9 w-9 items-center justify-center rounded-full",
|
||||
"transition-opacity hover:opacity-90",
|
||||
"focus:outline-none focus-visible:outline-none",
|
||||
"data-[state=open]:bg-transparent"
|
||||
"data-[state=open]:opacity-90"
|
||||
)}
|
||||
>
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
<UserAvatar
|
||||
avatarUrl={user.avatarUrl}
|
||||
initials={initials}
|
||||
bgColor={bgColor}
|
||||
size="md"
|
||||
/>
|
||||
<span className="sr-only">{displayName}</span>
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent className="w-48" side="right" align="center" sideOffset={8}>
|
||||
<DropdownMenuContent className="w-48" side="right" align="end" sideOffset={8}>
|
||||
<DropdownMenuLabel className="font-normal">
|
||||
<div className="flex items-center gap-2">
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue