Commit f229ff56 by HoMeTown

feat: 添加navbar的展开收起

parent 50f70b21
...@@ -17,12 +17,18 @@ interface MainLayoutProps { ...@@ -17,12 +17,18 @@ interface MainLayoutProps {
} }
const contentVariants = { const contentVariants = {
hidden: {
x: '-100%', // 向左移出屏幕
transition: { type: 'tween', duration: 0.3 },
},
expanded: { expanded: {
width: '90px', width: '90px',
x: 0, // 恢复原位
transition: { type: 'spring', stiffness: 300, damping: 30 }, transition: { type: 'spring', stiffness: 300, damping: 30 },
}, },
shrunk: { shrunk: {
width: isMobile() ? '90px' : '340px', width: isMobile() ? '90px' : '340px',
x: 0, // 恢复原位
transition: { type: 'spring', stiffness: 300, damping: 30 }, transition: { type: 'spring', stiffness: 300, damping: 30 },
}, },
} }
...@@ -30,6 +36,7 @@ const contentVariants = { ...@@ -30,6 +36,7 @@ const contentVariants = {
export const MainLayout: React.FC<MainLayoutProps> = ({ children }) => { export const MainLayout: React.FC<MainLayoutProps> = ({ children }) => {
const { showLoginModal, toggleLoginModal } = useAuth() const { showLoginModal, toggleLoginModal } = useAuth()
const [isHistoryVisible, setHistoryVisible] = useState(false) const [isHistoryVisible, setHistoryVisible] = useState(false)
const [isNavBarVisible, setNavBarvisible] = useState(true)
const location = useLocation() const location = useLocation()
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const token = window.localStorage.getItem('__TOKEN__') const token = window.localStorage.getItem('__TOKEN__')
...@@ -50,12 +57,17 @@ export const MainLayout: React.FC<MainLayoutProps> = ({ children }) => { ...@@ -50,12 +57,17 @@ export const MainLayout: React.FC<MainLayoutProps> = ({ children }) => {
<motion.main className={styles.layoutMain}> <motion.main className={styles.layoutMain}>
{/* hidden */} {/* hidden */}
<motion.div <motion.div
animate={isHistoryVisible ? 'shrunk' : 'expanded'} animate={isNavBarVisible ? isHistoryVisible ? 'shrunk' : 'expanded' : 'hidden'}
variants={contentVariants} variants={contentVariants}
className={`fixed right-[-12px] top-[10px] z-[49] h-auto sm:relative flex sm:h-full pl-[12px] items-center ${isHistoryVisible && !isMobile() ? 'w-[340px]' : 'w-[90px]'} box-border`} className={`fixed right-[-12px] top-[10px] z-[49] h-auto sm:relative flex sm:h-full pl-[12px] items-center ${isHistoryVisible && !isMobile() ? 'w-[340px]' : 'w-[90px]'} box-border`}
> >
<Navbar isHistoryVisible={isHistoryVisible} onSetHistoryVisible={setHistoryVisible} /> <Navbar
isHistoryVisible={isHistoryVisible}
onSetHistoryVisible={setHistoryVisible}
isNavBarVisible={isNavBarVisible}
onSetNavBarVisible={setNavBarvisible}
/>
<HistoryBar isVisible={isHistoryVisible} onSetHistoryVisible={setHistoryVisible} /> <HistoryBar isVisible={isHistoryVisible} onSetHistoryVisible={setHistoryVisible} />
{!isHistoryVisible && ( {!isHistoryVisible && (
......
...@@ -7,3 +7,79 @@ ...@@ -7,3 +7,79 @@
align-items: center; align-items: center;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
.sidebarAction {
width: 24px;
height: 36px;
position: absolute;
top: 50%;
right: -26px;
transform: translateY(-50%);
cursor: pointer;
transition: opacity .2s ease;
&.open {
&:hover {
&::before {
background-color: #29B6FD;
border-radius: 10px !important;
transform: rotate(17deg) scaleY(1.2) !important;
}
&::after {
background-color: #29B6FD;
border-radius: 10px !important;
transform: rotate(-17deg) scaleY(1.2) !important;
}
}
&::before {
transform: none;
}
&::after {
transform: none;
}
}
&:hover {
&::before {
background-color: #29B6FD;
border-radius: 10px !important;
transform: rotate(-17deg) scaleY(1.2) !important;
}
&::after {
background-color: #29B6FD;
border-radius: 10px !important;
transform: rotate(17deg) scaleY(1.2) !important;
}
}
&::before {
content: "";
display: block;
width: 4px;
height: 16px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
background-color: #c3c4c5;
left: 12px;
top: 0;
position: absolute;
transition: background-color, transform .2s ease;
// transform-origin: 50% 0;
transform-origin: right top;
}
&::after {
content: "";
display: block;
width: 4px;
height: 16px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
background-color: #c3c4c5;
left: 12px;
top: 16px;
position: absolute;
transition: background-color, transform .2s ease;
transform-origin: 50% 0;
transform-origin: 100% 100%; /* 右下角 */
}
}
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Please do not change this file! // Please do not change this file!
interface CssExports { interface CssExports {
layoutNavBarAgent: string layoutNavBarAgent: string
open: string
sidebarAction: string
} }
declare const cssExports: CssExports declare const cssExports: CssExports
export default cssExports export default cssExports
...@@ -18,9 +18,11 @@ import JoyrideStep from '@/components/JoyrideStep' ...@@ -18,9 +18,11 @@ import JoyrideStep from '@/components/JoyrideStep'
interface NavbarProps { interface NavbarProps {
isHistoryVisible: boolean isHistoryVisible: boolean
onSetHistoryVisible: (visible: boolean) => void onSetHistoryVisible: (visible: boolean) => void
isNavBarVisible: boolean
onSetNavBarVisible: (visible: boolean) => void
} }
const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, checkAuth, onSetHistoryVisible }) => { const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, checkAuth, onSetHistoryVisible, isNavBarVisible, onSetNavBarVisible }) => {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const navigate = useNavigate() const navigate = useNavigate()
...@@ -73,6 +75,10 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c ...@@ -73,6 +75,10 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c
navigate('/') navigate('/')
} }
const toggleNavBarVisible = () => {
onSetNavBarVisible(!isNavBarVisible)
}
useEffect(() => { useEffect(() => {
if (shouldNavigateToNewConversation && currentConversationId) { if (shouldNavigateToNewConversation && currentConversationId) {
navigate(`/chat/${currentConversationId}`) navigate(`/chat/${currentConversationId}`)
...@@ -87,9 +93,13 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c ...@@ -87,9 +93,13 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c
return ( return (
<> <>
<motion.nav ref={navRef} className="h-full flex-shrink-0 flex flex-col items-center justify-center"> <motion.nav
ref={navRef}
animate={isNavBarVisible ? '' : 'hidden'}
className="h-full flex-shrink-0 flex flex-col items-center justify-center relative"
>
{/* hidden */} {/* hidden */}
<motion.div className={`layoutNavBarJoyride ${styles.layoutNavBarAgent} rounded-full ${isH5NavVisible ? 'h-[55px] bg-white/40' : 'h-[380px]'} w-[54px] overflow-hidden py-[8px] sm:w-[64px] sm:bg-white gap-[24px] sm:h-auto sm:rounded-3xl sm:flex sm:py-[24px] sm:px-[8px]`}> <motion.div className={`layoutNavBarJoyride ${styles.layoutNavBarAgent} rounded-full ${isH5NavVisible ? 'h-[55px] bg-white/70 shadow-md' : 'h-[380px]'} w-[54px] overflow-hidden py-[8px] sm:w-[64px] sm:bg-white gap-[24px] sm:h-auto sm:rounded-3xl sm:flex sm:py-[24px] sm:px-[8px]`}>
<NavBarItem isHistoryVisible={isHistoryVisible} onClick={handleClick} icon={Logo} label="" key="logo" type={isMobile() ? 'logo3' : 'logo'} /> <NavBarItem isHistoryVisible={isHistoryVisible} onClick={handleClick} icon={Logo} label="" key="logo" type={isMobile() ? 'logo3' : 'logo'} />
{NAV_BAR_ITEMS.map((item) => { {NAV_BAR_ITEMS.map((item) => {
...@@ -99,6 +109,7 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c ...@@ -99,6 +109,7 @@ const NavbarBase: React.FC<NavbarProps & WithAuthProps> = ({ isHistoryVisible, c
})} })}
<User onLogout={handleLogout} /> <User onLogout={handleLogout} />
</motion.div> </motion.div>
<div onClick={toggleNavBarVisible} className={`${styles.sidebarAction} ${isNavBarVisible ? 'open' : ''}`}></div>
</motion.nav> </motion.nav>
<JoyrideStep /> <JoyrideStep />
</> </>
......
...@@ -60,11 +60,11 @@ export const Home: React.FC = () => { ...@@ -60,11 +60,11 @@ export const Home: React.FC = () => {
<Slogan /> <Slogan />
{/* 欢迎语 */} {/* 欢迎语 */}
<div className="gap-[20px] flex justify-center flex-row flex-wrap mt-[42px] sm:mt-[62px] lg:mt-[112px]"> <div className="gap-[20px] flex justify-center flex-row flex-wrap mt-[32px] sm:mt-[62px] lg:mt-[112px]">
<motion.div className="w-full hidden sm:block sm:w-auto" {...getAnimationProps(1)}><WelcomeWord /></motion.div> <motion.div className="w-full mb-[32px] sm:mb-[0px] sm:w-auto" {...getAnimationProps(1)}><WelcomeWord /></motion.div>
<motion.div className="w-full sm:w-auto" {...getAnimationProps(2)}><QuestionList questions={RECOMMEND_QUESTIONS_PRODUCT} dotColor="#D4CCFF" title="产品问答" iconImg={HomeIcon1} /></motion.div> <motion.div className="w-full hidden sm:block sm:w-auto" {...getAnimationProps(2)}><QuestionList questions={RECOMMEND_QUESTIONS_PRODUCT} dotColor="#D4CCFF" title="产品问答" iconImg={HomeIcon1} /></motion.div>
<motion.div className="w-full sm:w-auto" {...getAnimationProps(3)}><QuestionList questions={RECOMMEND_QUESTIONS_OTHER} dotColor="#CBECFF" title="其他问答" iconImg={HomeIcon2} /></motion.div> <motion.div className="w-full sm:w-auto" {...getAnimationProps(3)}><QuestionList questions={RECOMMEND_QUESTIONS_OTHER} dotColor="#CBECFF" title="您可以试着问我" iconImg={HomeIcon2} /></motion.div>
</div> </div>
</div> </div>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment