mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-27 17:56:25 +02:00
feat: add language selection feature to user profile sidebar, fixed some hover color logic for both model selector and language selection
This commit is contained in:
parent
a41b75463f
commit
24049345a2
9 changed files with 87 additions and 24 deletions
|
|
@ -7,7 +7,6 @@ import { NotificationButton } from "@/components/notifications/NotificationButto
|
|||
|
||||
interface HeaderProps {
|
||||
breadcrumb?: React.ReactNode;
|
||||
languageSwitcher?: React.ReactNode;
|
||||
theme?: string;
|
||||
onToggleTheme?: () => void;
|
||||
mobileMenuTrigger?: React.ReactNode;
|
||||
|
|
@ -15,7 +14,6 @@ interface HeaderProps {
|
|||
|
||||
export function Header({
|
||||
breadcrumb,
|
||||
languageSwitcher,
|
||||
theme,
|
||||
onToggleTheme,
|
||||
mobileMenuTrigger,
|
||||
|
|
@ -45,8 +43,6 @@ export function Header({
|
|||
<TooltipContent>{theme === "dark" ? "Light mode" : "Dark mode"}</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{languageSwitcher}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ interface LayoutShellProps {
|
|||
onLogout?: () => void;
|
||||
pageUsage?: PageUsage;
|
||||
breadcrumb?: React.ReactNode;
|
||||
languageSwitcher?: React.ReactNode;
|
||||
theme?: string;
|
||||
onToggleTheme?: () => void;
|
||||
defaultCollapsed?: boolean;
|
||||
|
|
@ -69,7 +68,6 @@ export function LayoutShell({
|
|||
onLogout,
|
||||
pageUsage,
|
||||
breadcrumb,
|
||||
languageSwitcher,
|
||||
theme,
|
||||
onToggleTheme,
|
||||
defaultCollapsed = false,
|
||||
|
|
@ -88,7 +86,6 @@ export function LayoutShell({
|
|||
<div className={cn("flex h-screen w-full flex-col bg-background", className)}>
|
||||
<Header
|
||||
breadcrumb={breadcrumb}
|
||||
languageSwitcher={languageSwitcher}
|
||||
theme={theme}
|
||||
onToggleTheme={onToggleTheme}
|
||||
mobileMenuTrigger={<MobileSidebarTrigger onClick={() => setMobileMenuOpen(true)} />}
|
||||
|
|
@ -172,7 +169,6 @@ export function LayoutShell({
|
|||
<main className="flex-1 flex flex-col min-w-0">
|
||||
<Header
|
||||
breadcrumb={breadcrumb}
|
||||
languageSwitcher={languageSwitcher}
|
||||
theme={theme}
|
||||
onToggleTheme={onToggleTheme}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,30 @@
|
|||
"use client";
|
||||
|
||||
import { ChevronUp, LogOut, Settings } from "lucide-react";
|
||||
import { ChevronUp, Languages, LogOut, Settings } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { useLocaleContext } from "@/contexts/LocaleContext";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { User } from "../../types/layout.types";
|
||||
|
||||
// Supported languages configuration
|
||||
const LANGUAGES = [
|
||||
{ code: "en" as const, name: "English", flag: "🇺🇸" },
|
||||
{ code: "zh" as const, name: "简体中文", flag: "🇨🇳" },
|
||||
];
|
||||
|
||||
interface SidebarUserProfileProps {
|
||||
user: User;
|
||||
onUserSettings?: () => void;
|
||||
|
|
@ -101,10 +112,15 @@ export function SidebarUserProfile({
|
|||
isCollapsed = false,
|
||||
}: SidebarUserProfileProps) {
|
||||
const t = useTranslations("sidebar");
|
||||
const { locale, setLocale } = useLocaleContext();
|
||||
const bgColor = stringToColor(user.email);
|
||||
const initials = getInitials(user.email);
|
||||
const displayName = user.name || user.email.split("@")[0];
|
||||
|
||||
const handleLanguageChange = (newLocale: "en" | "zh") => {
|
||||
setLocale(newLocale);
|
||||
};
|
||||
|
||||
// Collapsed view - just show avatar with dropdown
|
||||
if (isCollapsed) {
|
||||
return (
|
||||
|
|
@ -118,7 +134,8 @@ export function SidebarUserProfile({
|
|||
className={cn(
|
||||
"flex h-10 w-full items-center justify-center rounded-md",
|
||||
"hover:bg-accent transition-colors",
|
||||
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
"focus:outline-none focus-visible:outline-none",
|
||||
"data-[state=open]:bg-transparent"
|
||||
)}
|
||||
>
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
|
|
@ -129,7 +146,7 @@ export function SidebarUserProfile({
|
|||
<TooltipContent side="right">{displayName}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<DropdownMenuContent className="w-56" side="right" align="end" sideOffset={8}>
|
||||
<DropdownMenuContent className="w-56" side="right" align="center" sideOffset={8}>
|
||||
<DropdownMenuLabel className="font-normal">
|
||||
<div className="flex items-center gap-2">
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
|
|
@ -147,6 +164,34 @@ export function SidebarUserProfile({
|
|||
{t("user_settings")}
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
<Languages className="mr-2 h-4 w-4" />
|
||||
{t("language")}
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent className="gap-1">
|
||||
{LANGUAGES.map((language) => {
|
||||
const isSelected = locale === language.code;
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={language.code}
|
||||
onClick={() => handleLanguageChange(language.code)}
|
||||
className={cn(
|
||||
"mb-1 last:mb-0",
|
||||
!isSelected && "focus:bg-transparent hover:bg-transparent",
|
||||
isSelected && "bg-accent focus:!bg-accent hover:!bg-accent"
|
||||
)}
|
||||
>
|
||||
<span className="mr-2">{language.flag}</span>
|
||||
<span className="flex-1">{language.name}</span>
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem onClick={onLogout}>
|
||||
|
|
@ -169,7 +214,8 @@ export function SidebarUserProfile({
|
|||
className={cn(
|
||||
"flex w-full items-center gap-2 px-2 py-3 text-left",
|
||||
"hover:bg-accent transition-colors",
|
||||
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
||||
"focus:outline-none focus-visible:outline-none",
|
||||
"data-[state=open]:bg-transparent"
|
||||
)}
|
||||
>
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
|
|
@ -185,7 +231,7 @@ export function SidebarUserProfile({
|
|||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent className="w-56" side="top" align="start" sideOffset={4}>
|
||||
<DropdownMenuContent className="w-56" side="top" align="center" sideOffset={4}>
|
||||
<DropdownMenuLabel className="font-normal">
|
||||
<div className="flex items-center gap-2">
|
||||
<UserAvatar avatarUrl={user.avatarUrl} initials={initials} bgColor={bgColor} />
|
||||
|
|
@ -203,6 +249,34 @@ export function SidebarUserProfile({
|
|||
{t("user_settings")}
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger>
|
||||
<Languages className="mr-2 h-4 w-4" />
|
||||
{t("language")}
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent className="gap-1">
|
||||
{LANGUAGES.map((language) => {
|
||||
const isSelected = locale === language.code;
|
||||
return (
|
||||
<DropdownMenuItem
|
||||
key={language.code}
|
||||
onClick={() => handleLanguageChange(language.code)}
|
||||
className={cn(
|
||||
"mb-1 last:mb-0",
|
||||
!isSelected && "focus:bg-transparent hover:bg-transparent",
|
||||
isSelected && "bg-accent focus:!bg-accent hover:!bg-accent"
|
||||
)}
|
||||
>
|
||||
<span className="mr-2">{language.flag}</span>
|
||||
<span className="flex-1">{language.name}</span>
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuSub>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem onClick={onLogout}>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue