feat: close #1394
Some checks are pending
Build NapCat Artifacts / Build-Framework (push) Waiting to run
Build NapCat Artifacts / Build-Shell (push) Waiting to run

This commit is contained in:
时瑾 2025-11-24 12:47:04 +08:00
parent f27db01145
commit 3c612e03ff
No known key found for this signature in database
GPG Key ID: 023F70A1B8F8C196
2 changed files with 75 additions and 55 deletions

View File

@ -1,7 +1,7 @@
import { Button } from '@heroui/button'; import { Button } from '@heroui/button';
import { Image } from '@heroui/image'; import { Image } from '@heroui/image';
import clsx from 'clsx'; import clsx from 'clsx';
import { motion } from 'motion/react'; import { AnimatePresence, motion } from 'motion/react';
import React from 'react'; import React from 'react';
import { IoMdLogOut } from 'react-icons/io'; import { IoMdLogOut } from 'react-icons/io';
import { MdDarkMode, MdLightMode } from 'react-icons/md'; import { MdDarkMode, MdLightMode } from 'react-icons/md';
@ -18,10 +18,11 @@ import Menus from './menus';
interface SideBarProps { interface SideBarProps {
open: boolean open: boolean
items: MenuItem[] items: MenuItem[]
onClose?: () => void
} }
const SideBar: React.FC<SideBarProps> = (props) => { const SideBar: React.FC<SideBarProps> = (props) => {
const { open, items } = props; const { open, items, onClose } = props;
const { toggleTheme, isDark } = useTheme(); const { toggleTheme, isDark } = useTheme();
const { revokeAuth } = useAuth(); const { revokeAuth } = useAuth();
const dialog = useDialog(); const dialog = useDialog();
@ -33,60 +34,75 @@ const SideBar: React.FC<SideBarProps> = (props) => {
}); });
}; };
return ( return (
<motion.div <>
className={clsx( <AnimatePresence initial={false}>
'overflow-hidden fixed top-0 left-0 h-full z-50 bg-background md:bg-transparent md:static shadow-md md:shadow-none rounded-r-md md:rounded-none' {open && (
)} <motion.div
initial={{ width: 0 }} className='fixed inset-y-0 left-64 right-0 bg-black/20 backdrop-blur-[1px] z-40 md:hidden'
animate={{ width: open ? '16rem' : 0 }} aria-hidden='true'
transition={{ onClick={onClose}
type: open ? 'spring' : 'tween', initial={{ opacity: 0 }}
stiffness: 150, animate={{ opacity: 1 }}
damping: open ? 15 : 10, exit={{ opacity: 0, transition: { duration: 0.15 } }}
}} transition={{ duration: 0.2, delay: 0.15 }}
style={{ overflow: 'hidden' }} />
> )}
<motion.div className='w-64 flex flex-col items-stretch h-full transition-transform duration-300 ease-in-out z-30 relative float-right'> </AnimatePresence>
<div className='flex justify-center items-center my-2 gap-2'> <motion.div
<Image radius='none' height={40} src={logo} className='mb-2' /> className={clsx(
<div 'overflow-hidden fixed top-0 left-0 h-full z-50 bg-background md:bg-transparent md:static shadow-md md:shadow-none rounded-r-md md:rounded-none'
className={clsx( )}
'flex items-center font-bold', initial={{ width: 0 }}
'!text-2xl shiny-text' animate={{ width: open ? '16rem' : 0 }}
)} transition={{
> type: open ? 'spring' : 'tween',
NapCat stiffness: 150,
</div> damping: open ? 15 : 10,
</div> }}
<div className='overflow-y-auto flex flex-col flex-1 px-4'> style={{ overflow: 'hidden' }}
<Menus items={items} /> >
<div className='mt-auto mb-10 md:mb-0'> <motion.div className='w-64 flex flex-col items-stretch h-full transition-transform duration-300 ease-in-out z-30 relative float-right'>
<Button <div className='flex justify-center items-center my-2 gap-2'>
className='w-full' <Image radius='none' height={40} src={logo} className='mb-2' />
color='primary' <div
radius='full' className={clsx(
variant='light' 'flex items-center font-bold',
onPress={toggleTheme} '!text-2xl shiny-text'
startContent={ )}
!isDark ? <MdLightMode size={16} /> : <MdDarkMode size={16} />
}
> >
NapCat
</Button> </div>
<Button
className='w-full mb-2'
color='primary'
radius='full'
variant='light'
onPress={onRevokeAuth}
startContent={<IoMdLogOut size={16} />}
>
退
</Button>
</div> </div>
</div> <div className='overflow-y-auto flex flex-col flex-1 px-4'>
<Menus items={items} />
<div className='mt-auto mb-10 md:mb-0'>
<Button
className='w-full'
color='primary'
radius='full'
variant='light'
onPress={toggleTheme}
startContent={
!isDark ? <MdLightMode size={16} /> : <MdDarkMode size={16} />
}
>
</Button>
<Button
className='w-full mb-2'
color='primary'
radius='full'
variant='light'
onPress={onRevokeAuth}
startContent={<IoMdLogOut size={16} />}
>
退
</Button>
</div>
</div>
</motion.div>
</motion.div> </motion.div>
</motion.div> </>
); );
}; };

View File

@ -85,7 +85,11 @@ const Layout: React.FC<{ children: React.ReactNode; }> = ({ children }) => {
backgroundSize: 'cover', backgroundSize: 'cover',
}} }}
> >
<SideBar items={menus} open={openSideBar} /> <SideBar
items={menus}
open={openSideBar}
onClose={() => setOpenSideBar(false)}
/>
<div <div
ref={contentRef} ref={contentRef}
className={clsx( className={clsx(
@ -107,7 +111,7 @@ const Layout: React.FC<{ children: React.ReactNode; }> = ({ children }) => {
> >
<motion.div <motion.div
className={clsx( className={clsx(
'mr-1 ease-in-out ml-0 md:relative', 'mr-1 ease-in-out ml-0 md:relative z-50 md:z-auto',
openSideBar && 'pl-2 absolute', openSideBar && 'pl-2 absolute',
'md:!ml-0 md:pl-0' 'md:!ml-0 md:pl-0'
)} )}