mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-11 22:38:58 +08:00
### What problem does this PR solve? Feat: Bind event to the theme Switch #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
000cd6d615
commit
e8b4e8b3d7
@ -1,6 +1,6 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
|
||||
type Theme = 'dark' | 'light';
|
||||
type Theme = 'dark' | 'light' | 'system';
|
||||
|
||||
type ThemeProviderProps = {
|
||||
children: React.ReactNode;
|
||||
|
@ -17,5 +17,14 @@ export const useNavigatePage = () => {
|
||||
navigate(Routes.Home);
|
||||
}, [navigate]);
|
||||
|
||||
return { navigateToDatasetList, navigateToDataset, navigateToHome };
|
||||
const navigateToProfile = useCallback(() => {
|
||||
navigate(Routes.ProfileSetting);
|
||||
}, [navigate]);
|
||||
|
||||
return {
|
||||
navigateToDatasetList,
|
||||
navigateToDataset,
|
||||
navigateToHome,
|
||||
navigateToProfile,
|
||||
};
|
||||
};
|
||||
|
@ -25,8 +25,7 @@ export function Header() {
|
||||
const { t } = useTranslate('header');
|
||||
const { pathname } = useLocation();
|
||||
const navigate = useNavigateWithFromState();
|
||||
// const [currentPath, setCurrentPath] = useState(Routes.Home);
|
||||
const { navigateToHome } = useNavigatePage();
|
||||
const { navigateToHome, navigateToProfile } = useNavigatePage();
|
||||
|
||||
const tagsData = useMemo(
|
||||
() => [
|
||||
@ -65,7 +64,6 @@ export function Header() {
|
||||
|
||||
const handleChange = (path: SegmentedValue) => {
|
||||
navigate(path as Routes);
|
||||
// setCurrentPath(path as Routes);
|
||||
};
|
||||
|
||||
const handleLogoClick = useCallback(() => {
|
||||
@ -121,7 +119,10 @@ export function Header() {
|
||||
</Button>
|
||||
</Container>
|
||||
<Container className="px-3 py-2 bg-colors-background-inverse-standard">
|
||||
<Avatar className="w-[30px] h-[30px]">
|
||||
<Avatar
|
||||
className="w-[30px] h-[30px] cursor-pointer"
|
||||
onClick={navigateToProfile}
|
||||
>
|
||||
<AvatarImage src="https://github.com/shadcn.png" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
|
@ -1,49 +0,0 @@
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { Moon, Sun } from 'lucide-react';
|
||||
|
||||
export function ModeToggle() {
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="icon">
|
||||
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
|
||||
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
|
||||
<span className="sr-only">Toggle theme</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => setTheme('light')}>
|
||||
Light
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
||||
Dark
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('system')}>
|
||||
System
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
|
||||
const Demo = () => {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<ModeToggle></ModeToggle>
|
||||
</div>
|
||||
<Button>Destructive</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Demo;
|
@ -1,14 +1,17 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { ArrowLeft } from 'lucide-react';
|
||||
import { Outlet } from 'umi';
|
||||
import { SideBar } from './sidebar';
|
||||
|
||||
export default function ProfileSetting() {
|
||||
const { navigateToHome } = useNavigatePage();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col w-full h-screen bg-background text-foreground">
|
||||
<header className="flex items-center border-b">
|
||||
<div className="flex items-center border-r p-1.5">
|
||||
<Button variant="ghost" size="icon">
|
||||
<Button variant="ghost" size="icon" onClick={navigateToHome}>
|
||||
<ArrowLeft className="w-5 h-5" />
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
@ -13,6 +14,7 @@ import {
|
||||
LogOut,
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useHandleMenuClick } from './hooks';
|
||||
|
||||
const menuItems = [
|
||||
@ -49,35 +51,45 @@ const menuItems = [
|
||||
export function SideBar() {
|
||||
const pathName = useSecondPathName();
|
||||
const { handleMenuClick } = useHandleMenuClick();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
const handleThemeChange = useCallback(
|
||||
(checked: boolean) => {
|
||||
setTheme(checked ? 'dark' : 'light');
|
||||
},
|
||||
[setTheme],
|
||||
);
|
||||
|
||||
return (
|
||||
<aside className="w-[303px] bg-background border-r">
|
||||
{menuItems.map((section, idx) => (
|
||||
<div key={idx}>
|
||||
<h2 className="p-6 text-sm font-semibold">{section.section}</h2>
|
||||
{section.items.map((item, itemIdx) => {
|
||||
const active = pathName === item.key;
|
||||
return (
|
||||
<Button
|
||||
key={itemIdx}
|
||||
variant={active ? 'secondary' : 'ghost'}
|
||||
className={cn('w-full justify-start gap-2.5 p-6 relative')}
|
||||
onClick={handleMenuClick(item.key)}
|
||||
>
|
||||
<item.icon className="w-6 h-6" />
|
||||
<span>{item.label}</span>
|
||||
{active && (
|
||||
<div className="absolute right-0 w-[5px] h-[66px] bg-primary rounded-l-xl shadow-[0_0_5.94px_#7561ff,0_0_11.88px_#7561ff,0_0_41.58px_#7561ff,0_0_83.16px_#7561ff,0_0_142.56px_#7561ff,0_0_249.48px_#7561ff]" />
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
<aside className="w-[303px] bg-background border-r flex flex-col">
|
||||
<div className="flex-1 overflow-auto">
|
||||
{menuItems.map((section, idx) => (
|
||||
<div key={idx}>
|
||||
<h2 className="p-6 text-sm font-semibold">{section.section}</h2>
|
||||
{section.items.map((item, itemIdx) => {
|
||||
const active = pathName === item.key;
|
||||
return (
|
||||
<Button
|
||||
key={itemIdx}
|
||||
variant={active ? 'secondary' : 'ghost'}
|
||||
className={cn('w-full justify-start gap-2.5 p-6 relative')}
|
||||
onClick={handleMenuClick(item.key)}
|
||||
>
|
||||
<item.icon className="w-6 h-6" />
|
||||
<span>{item.label}</span>
|
||||
{active && (
|
||||
<div className="absolute right-0 w-[5px] h-[66px] bg-primary rounded-l-xl shadow-[0_0_5.94px_#7561ff,0_0_11.88px_#7561ff,0_0_41.58px_#7561ff,0_0_83.16px_#7561ff,0_0_142.56px_#7561ff,0_0_249.48px_#7561ff]" />
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="p-6 mt-auto border-t">
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<Switch id="dark-mode" />
|
||||
<Switch id="dark-mode" onCheckedChange={handleThemeChange} />
|
||||
<Label htmlFor="dark-mode" className="text-sm">
|
||||
Dark
|
||||
</Label>
|
||||
|
@ -7,6 +7,7 @@ export enum Routes {
|
||||
Agent = '/agent',
|
||||
Search = '/next-search',
|
||||
Chat = '/next-chat',
|
||||
ProfileSetting = '/profile-setting',
|
||||
}
|
||||
|
||||
const routes = [
|
||||
@ -136,11 +137,6 @@ const routes = [
|
||||
component: '@/pages/404',
|
||||
layout: false,
|
||||
},
|
||||
{
|
||||
path: '/demo',
|
||||
component: '@/pages/demo',
|
||||
layout: false,
|
||||
},
|
||||
{
|
||||
path: Routes.Home,
|
||||
layout: false,
|
||||
@ -223,30 +219,33 @@ const routes = [
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/profile-setting',
|
||||
path: Routes.ProfileSetting,
|
||||
layout: false,
|
||||
component: '@/pages/profile-setting',
|
||||
component: `@/pages${Routes.ProfileSetting}`,
|
||||
routes: [
|
||||
{ path: '/profile-setting', redirect: '/profile-setting/profile' },
|
||||
{
|
||||
path: '/profile-setting/profile',
|
||||
component: '@/pages/profile-setting/profile',
|
||||
path: Routes.ProfileSetting,
|
||||
redirect: `${Routes.ProfileSetting}/profile`,
|
||||
},
|
||||
{
|
||||
path: '/profile-setting/team',
|
||||
component: '@/pages/profile-setting/team',
|
||||
path: `${Routes.ProfileSetting}/profile`,
|
||||
component: `@/pages${Routes.ProfileSetting}/profile`,
|
||||
},
|
||||
{
|
||||
path: '/profile-setting/plan',
|
||||
component: '@/pages/profile-setting/plan',
|
||||
path: `${Routes.ProfileSetting}/team`,
|
||||
component: `@/pages${Routes.ProfileSetting}/team`,
|
||||
},
|
||||
{
|
||||
path: '/profile-setting/model',
|
||||
component: '@/pages/profile-setting/model',
|
||||
path: `${Routes.ProfileSetting}/plan`,
|
||||
component: `@/pages${Routes.ProfileSetting}/plan`,
|
||||
},
|
||||
{
|
||||
path: '/profile-setting/prompt',
|
||||
component: '@/pages/profile-setting/prompt',
|
||||
path: `${Routes.ProfileSetting}/model`,
|
||||
component: `@/pages${Routes.ProfileSetting}/model`,
|
||||
},
|
||||
{
|
||||
path: `${Routes.ProfileSetting}/prompt`,
|
||||
component: `@/pages${Routes.ProfileSetting}/prompt`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user