feat: Add animation for sidebar (#9768)

This commit is contained in:
RieN 7z 2025-09-02 09:26:56 +08:00 committed by GitHub
parent 1295d37ff6
commit 16b9f49cc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 93 additions and 46 deletions

View File

@ -13,6 +13,7 @@ import { Assistant, Topic } from '@renderer/types'
import { classNames } from '@renderer/utils'
import { Flex } from 'antd'
import { debounce } from 'lodash'
import { AnimatePresence, motion } from 'motion/react'
import React, { FC, useState } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import styled from 'styled-components'
@ -43,7 +44,6 @@ const Chat: FC<Props> = (props) => {
const contentSearchRef = React.useRef<ContentSearchRef>(null)
const [filterIncludeUser, setFilterIncludeUser] = useState(false)
const maxWidth = useChatMaxWidth()
const { setTimeoutTimer } = useTimer()
useHotkeys('esc', () => {
@ -131,7 +131,7 @@ const Chat: FC<Props> = (props) => {
vertical
flex={1}
justify="space-between"
style={{ maxWidth, height: mainHeight }}>
style={{ maxWidth: '100%', height: mainHeight }}>
<Messages
key={props.activeTopic.id}
assistant={assistant}
@ -153,15 +153,24 @@ const Chat: FC<Props> = (props) => {
{isMultiSelectMode && <MultiSelectActionPopup topic={props.activeTopic} />}
</QuickPanelProvider>
</Main>
{topicPosition === 'right' && showTopics && (
<Tabs
activeAssistant={assistant}
activeTopic={props.activeTopic}
setActiveAssistant={props.setActiveAssistant}
setActiveTopic={props.setActiveTopic}
position="right"
/>
)}
<AnimatePresence initial={false}>
{topicPosition === 'right' && showTopics && (
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 'auto', opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
style={{ overflow: 'hidden' }}>
<Tabs
activeAssistant={assistant}
activeTopic={props.activeTopic}
setActiveAssistant={props.setActiveAssistant}
setActiveTopic={props.setActiveTopic}
position="right"
/>
</motion.div>
)}
</AnimatePresence>
</HStack>
</Container>
)

View File

@ -13,6 +13,7 @@ import { Assistant, Topic } from '@renderer/types'
import { Tooltip } from 'antd'
import { t } from 'i18next'
import { Menu, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { FC } from 'react'
import styled from 'styled-components'
@ -80,11 +81,19 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
</NavbarIcon>
</Tooltip>
)}
{!showAssistants && (
<NavbarIcon onClick={onShowAssistantsDrawer} style={{ marginRight: 8 }}>
<Menu size={18} />
</NavbarIcon>
)}
<AnimatePresence initial={false}>
{!showAssistants && (
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 'auto', opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}>
<NavbarIcon onClick={onShowAssistantsDrawer} style={{ marginRight: 8 }}>
<Menu size={18} />
</NavbarIcon>
</motion.div>
)}
</AnimatePresence>
<SelectModelButton assistant={assistant} />
</HStack>
<HStack alignItems="center" gap={8}>

View File

@ -7,6 +7,7 @@ import NavigationService from '@renderer/services/NavigationService'
import { newMessagesActions } from '@renderer/store/newMessage'
import { Assistant, Topic } from '@renderer/types'
import { MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH, SECOND_MIN_WINDOW_WIDTH } from '@shared/config/constant'
import { AnimatePresence, motion } from 'motion/react'
import { FC, startTransition, useCallback, useEffect, useState } from 'react'
import { useDispatch } from 'react-redux'
import { useLocation, useNavigate } from 'react-router-dom'
@ -100,17 +101,26 @@ const HomePage: FC = () => {
/>
)}
<ContentContainer id={isLeftNavbar ? 'content-container' : undefined}>
{showAssistants && (
<ErrorBoundary>
<HomeTabs
activeAssistant={activeAssistant}
activeTopic={activeTopic}
setActiveAssistant={setActiveAssistant}
setActiveTopic={setActiveTopic}
position="left"
/>
</ErrorBoundary>
)}
<AnimatePresence initial={false}>
{showAssistants && (
<ErrorBoundary>
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 'var(--assistants-width)', opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
style={{ overflow: 'hidden' }}>
<HomeTabs
activeAssistant={activeAssistant}
activeTopic={activeTopic}
setActiveAssistant={setActiveAssistant}
setActiveTopic={setActiveTopic}
position="left"
/>
</motion.div>
</ErrorBoundary>
)}
</AnimatePresence>
<ErrorBoundary>
<Chat
assistant={activeAssistant}

View File

@ -15,6 +15,7 @@ import { Assistant, Topic } from '@renderer/types'
import { Tooltip } from 'antd'
import { t } from 'i18next'
import { Menu, MessageSquareDiff, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { FC } from 'react'
import styled from 'styled-components'
@ -68,20 +69,29 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
return (
<Navbar className="home-navbar">
{showAssistants && (
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: 0 }}>
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={0.8}>
<NavbarIcon onClick={toggleShowAssistants} style={{ marginLeft: isMac && !isFullscreen ? 16 : 0 }}>
<PanelLeftClose size={18} />
</NavbarIcon>
</Tooltip>
<Tooltip title={t('settings.shortcuts.new_topic')} mouseEnterDelay={0.8}>
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
<MessageSquareDiff size={18} />
</NavbarIcon>
</Tooltip>
</NavbarLeft>
)}
<AnimatePresence initial={false}>
{showAssistants && (
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 'auto', opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
style={{ overflow: 'hidden', display: 'flex', flexDirection: 'row' }}>
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: 0 }}>
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={0.8}>
<NavbarIcon onClick={toggleShowAssistants} style={{ marginLeft: isMac && !isFullscreen ? 16 : 0 }}>
<PanelLeftClose size={18} />
</NavbarIcon>
</Tooltip>
<Tooltip title={t('settings.shortcuts.new_topic')} mouseEnterDelay={0.8}>
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
<MessageSquareDiff size={18} />
</NavbarIcon>
</Tooltip>
</NavbarLeft>
</motion.div>
)}
</AnimatePresence>
<NavbarRight style={{ justifyContent: 'space-between', flex: 1 }} className="home-navbar-right">
<HStack alignItems="center">
{!showAssistants && (
@ -93,11 +103,20 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
</NavbarIcon>
</Tooltip>
)}
{!showAssistants && (
<NavbarIcon onClick={onShowAssistantsDrawer} style={{ marginRight: 8 }}>
<Menu size={18} />
</NavbarIcon>
)}
<AnimatePresence initial={false}>
{!showAssistants && (
<motion.div
initial={{ width: 0, opacity: 0 }}
animate={{ width: 'auto', opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
style={{ overflow: 'hidden' }}>
<NavbarIcon onClick={onShowAssistantsDrawer} style={{ marginRight: 8 }}>
<Menu size={18} />
</NavbarIcon>
</motion.div>
)}
</AnimatePresence>
<SelectModelButton assistant={assistant} />
</HStack>
<HStack alignItems="center" gap={8}>