refactor(MainSidebar): enhance dropdown menu with theme toggle and documentation link; update styles for dropdown menu

This commit is contained in:
Teo 2025-06-12 15:46:10 +08:00
parent 13fdfc58b6
commit a92fa1b1ba
3 changed files with 79 additions and 30 deletions

View File

@ -203,6 +203,20 @@
overflow-x: hidden; overflow-x: hidden;
} }
.ant-dropdown-menu {
max-height: 40vh;
overflow-y: auto;
border: 0.5px solid var(--color-border);
border-radius: 16px;
.ant-dropdown-menu-item {
padding: 5px;
}
}
.ant-dropdown-arrow + .ant-dropdown-menu {
border: none;
}
.ant-collapse { .ant-collapse {
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
.ant-color-picker & { .ant-color-picker & {

View File

@ -102,6 +102,7 @@ const SelectorStyle = createGlobalStyle`
.ant-dropdown-menu { .ant-dropdown-menu {
max-height: 40vh; max-height: 40vh;
overflow-y: auto; overflow-y: auto;
border: 0.5px solid var(--color-border);
} }
` `

View File

@ -1,23 +1,27 @@
import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar' import EmojiAvatar from '@renderer/components/Avatar/EmojiAvatar'
import UserPopup from '@renderer/components/Popups/UserPopup' import UserPopup from '@renderer/components/Popups/UserPopup'
import { UserAvatar } from '@renderer/config/env' import { AppLogo, UserAvatar } from '@renderer/config/env'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
import { useAssistants } from '@renderer/hooks/useAssistant' import { useAssistants } from '@renderer/hooks/useAssistant'
import useAvatar from '@renderer/hooks/useAvatar' import useAvatar from '@renderer/hooks/useAvatar'
import { useChat } from '@renderer/hooks/useChat' import { useChat } from '@renderer/hooks/useChat'
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
import { useSettings } from '@renderer/hooks/useSettings' import { useSettings } from '@renderer/hooks/useSettings'
import { useShortcut } from '@renderer/hooks/useShortcuts' import { useShortcut } from '@renderer/hooks/useShortcuts'
import { useShowAssistants } from '@renderer/hooks/useStore' import { useShowAssistants } from '@renderer/hooks/useStore'
import i18n from '@renderer/i18n'
import AssistantItem from '@renderer/pages/home/Tabs/components/AssistantItem' import AssistantItem from '@renderer/pages/home/Tabs/components/AssistantItem'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService' import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { ThemeMode } from '@renderer/types' import { ThemeMode } from '@renderer/types'
import { isEmoji } from '@renderer/utils' import { isEmoji } from '@renderer/utils'
import { Avatar, Tooltip } from 'antd' import { Avatar, Dropdown } from 'antd'
import { AnimatePresence, motion } from 'framer-motion' import { AnimatePresence, motion } from 'framer-motion'
import { import {
Blocks, Blocks,
ChevronDown, ChevronDown,
ChevronRight, ChevronRight,
CircleHelp,
EllipsisVertical,
FileSearch, FileSearch,
Folder, Folder,
Languages, Languages,
@ -59,7 +63,7 @@ const MainSidebar: FC = () => {
const avatar = useAvatar() const avatar = useAvatar()
const { userName, defaultPaintingProvider } = useSettings() const { userName, defaultPaintingProvider } = useSettings()
const { t } = useTranslation() const { t } = useTranslation()
const { theme } = useTheme() const { theme, settedTheme, toggleTheme } = useTheme()
const [isAppMenuExpanded, setIsAppMenuExpanded] = useState(false) const [isAppMenuExpanded, setIsAppMenuExpanded] = useState(false)
const { showAssistants, toggleShowAssistants } = useShowAssistants() const { showAssistants, toggleShowAssistants } = useShowAssistants()
@ -69,6 +73,8 @@ const MainSidebar: FC = () => {
const { activeAssistant, activeTopic, setActiveAssistant, setActiveTopic } = useChat() const { activeAssistant, activeTopic, setActiveAssistant, setActiveTopic } = useChat()
const { showTopics } = useSettings() const { showTopics } = useSettings()
const { openMinapp } = useMinappPopup()
useShortcut('toggle_show_assistants', toggleShowAssistants) useShortcut('toggle_show_assistants', toggleShowAssistants)
useShortcut('toggle_show_topics', () => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)) useShortcut('toggle_show_topics', () => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR))
@ -129,6 +135,17 @@ const MainSidebar: FC = () => {
const isRoutes = (path: string): boolean => pathname.startsWith(path) const isRoutes = (path: string): boolean => pathname.startsWith(path)
const docsId = 'cherrystudio-docs'
const onOpenDocs = () => {
const isChinese = i18n.language.startsWith('zh')
openMinapp({
id: docsId,
name: t('docs.title'),
url: isChinese ? 'https://docs.cherry-ai.com/' : 'https://docs.cherry-ai.com/cherry-studio-wen-dang/en-us',
logo: AppLogo
})
}
return ( return (
<Container <Container
id="main-sidebar" id="main-sidebar"
@ -214,40 +231,57 @@ const MainSidebar: FC = () => {
)} )}
{userName && <UserMenuText>{userName}</UserMenuText>} {userName && <UserMenuText>{userName}</UserMenuText>}
</UserMenuLeft> </UserMenuLeft>
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right">
<Icon theme={theme} onClick={() => navigate('/settings/provider')} className="settings-icon"> <Dropdown
<Settings size={18} className="icon" /> placement="topRight"
trigger={['click']}
menu={{
items: [
{
key: 'theme',
label: (
<span
onClick={(e) => {
e.stopPropagation()
toggleTheme()
}}>
{t('settings.theme.title')}: {t(`settings.theme.${settedTheme}`)}
</span>
),
icon: ThemeIcon()
},
{
key: 'about',
label: t('docs.title'),
icon: <CircleHelp size={16} className="icon" />,
onClick: onOpenDocs
},
{
key: 'settings',
label: t('settings.title'),
icon: <Settings size={16} className="icon" />,
onClick: () => navigate('/settings/provider')
}
]
}}>
<Icon theme={theme} className="settings-icon">
<EllipsisVertical size={16} />
</Icon> </Icon>
</Tooltip> </Dropdown>
</UserMenu> </UserMenu>
</Container> </Container>
) )
} }
export const ThemeIcon = () => { const ThemeIcon = () => {
const { t } = useTranslation() const { settedTheme } = useTheme()
const { theme, settedTheme, toggleTheme } = useTheme()
const onChageTheme = (e: React.MouseEvent<HTMLDivElement>) => { return settedTheme === ThemeMode.dark ? (
e.stopPropagation() <Moon size={16} className="icon" />
toggleTheme() ) : settedTheme === ThemeMode.light ? (
} <Sun size={16} className="icon" />
) : (
return ( <SunMoon size={16} className="icon" />
<Tooltip
title={t('settings.theme.title') + ': ' + t(`settings.theme.${settedTheme}`)}
mouseEnterDelay={0.8}
placement="right">
<Icon theme={theme} onClick={onChageTheme}>
{settedTheme === ThemeMode.dark ? (
<Moon size={18} className="icon" />
) : settedTheme === ThemeMode.light ? (
<Sun size={18} className="icon" />
) : (
<SunMoon size={18} className="icon" />
)}
</Icon>
</Tooltip>
) )
} }