refactor: update theme handling in TabContainer and Sidebar components (#8816)

* refactor: update theme handling in TabContainer and Sidebar components

* refactor: replace setTheme with toggleTheme and update theme state management
* feat: add Monitor icon for additional theme state in both components

* feat(DisplaySettings): replace theme icons with lucide icons for improved visual representation

* updated light and dark theme icons to use Sun and Moon from lucide
* replaced SyncOutlined with Monitor icon for system theme option

* format code

* feat(TabContainer): add tooltip for theme toggle button with translation support

* integrated Tooltip component to provide contextual information for the theme toggle button
* utilized useTranslation hook for internationalization of tooltip text
* imported getThemeModeLabel to enhance theme description
This commit is contained in:
beyondkmp 2025-08-04 16:50:34 +08:00 committed by GitHub
parent 90c1fff54a
commit e8b3d44400
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 14 deletions

View File

@ -3,19 +3,21 @@ import { isLinux, isMac, isWin } from '@renderer/config/constant'
import { useTheme } from '@renderer/context/ThemeProvider' import { useTheme } from '@renderer/context/ThemeProvider'
import { useFullscreen } from '@renderer/hooks/useFullscreen' import { useFullscreen } from '@renderer/hooks/useFullscreen'
import { useMinappPopup } from '@renderer/hooks/useMinappPopup' import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
import { getTitleLabel } from '@renderer/i18n/label' import { getThemeModeLabel, getTitleLabel } from '@renderer/i18n/label'
import tabsService from '@renderer/services/TabsService' import tabsService from '@renderer/services/TabsService'
import { useAppDispatch, useAppSelector } from '@renderer/store' import { useAppDispatch, useAppSelector } from '@renderer/store'
import type { Tab } from '@renderer/store/tabs' import type { Tab } from '@renderer/store/tabs'
import { addTab, removeTab, setActiveTab } from '@renderer/store/tabs' import { addTab, removeTab, setActiveTab } from '@renderer/store/tabs'
import { ThemeMode } from '@renderer/types' import { ThemeMode } from '@renderer/types'
import { classNames } from '@renderer/utils' import { classNames } from '@renderer/utils'
import { Tooltip } from 'antd'
import { import {
FileSearch, FileSearch,
Folder, Folder,
Home, Home,
Languages, Languages,
LayoutGrid, LayoutGrid,
Monitor,
Moon, Moon,
Palette, Palette,
Settings, Settings,
@ -25,6 +27,7 @@ import {
X X
} from 'lucide-react' } from 'lucide-react'
import { useCallback, useEffect } from 'react' import { useCallback, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router-dom' import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components' import styled from 'styled-components'
@ -69,8 +72,9 @@ const TabsContainer: React.FC<TabsContainerProps> = ({ children }) => {
const tabs = useAppSelector((state) => state.tabs.tabs) const tabs = useAppSelector((state) => state.tabs.tabs)
const activeTabId = useAppSelector((state) => state.tabs.activeTabId) const activeTabId = useAppSelector((state) => state.tabs.activeTabId)
const isFullscreen = useFullscreen() const isFullscreen = useFullscreen()
const { theme, setTheme } = useTheme() const { settedTheme, toggleTheme } = useTheme()
const { hideMinappPopup } = useMinappPopup() const { hideMinappPopup } = useMinappPopup()
const { t } = useTranslation()
const getTabId = (path: string): string => { const getTabId = (path: string): string => {
if (path === '/') return 'home' if (path === '/') return 'home'
@ -162,9 +166,20 @@ const TabsContainer: React.FC<TabsContainerProps> = ({ children }) => {
</AddTabButton> </AddTabButton>
<RightButtonsContainer> <RightButtonsContainer>
<TopNavbarOpenedMinappTabs /> <TopNavbarOpenedMinappTabs />
<ThemeButton onClick={() => setTheme(theme === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark)}> <Tooltip
{theme === ThemeMode.dark ? <Moon size={16} /> : <Sun size={16} />} title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
</ThemeButton> mouseEnterDelay={0.8}
placement="bottom">
<ThemeButton onClick={toggleTheme}>
{settedTheme === ThemeMode.dark ? (
<Moon size={16} />
) : settedTheme === ThemeMode.light ? (
<Sun size={16} />
) : (
<Monitor size={16} />
)}
</ThemeButton>
</Tooltip>
<SettingsButton onClick={handleSettingsClick} $active={activeTabId === 'settings'}> <SettingsButton onClick={handleSettingsClick} $active={activeTabId === 'settings'}>
<Settings size={16} /> <Settings size={16} />
</SettingsButton> </SettingsButton>

View File

@ -21,6 +21,7 @@ import {
Languages, Languages,
LayoutGrid, LayoutGrid,
MessageSquare, MessageSquare,
Monitor,
Moon, Moon,
Palette, Palette,
Settings, Settings,
@ -44,7 +45,7 @@ const Sidebar: FC = () => {
const { pathname } = useLocation() const { pathname } = useLocation()
const navigate = useNavigate() const navigate = useNavigate()
const { theme, setTheme } = useTheme() const { theme, settedTheme, toggleTheme } = useTheme()
const avatar = useAvatar() const avatar = useAvatar()
const { t } = useTranslation() const { t } = useTranslation()
@ -105,11 +106,17 @@ const Sidebar: FC = () => {
</Icon> </Icon>
</Tooltip> </Tooltip>
<Tooltip <Tooltip
title={t('settings.theme.title') + ': ' + getThemeModeLabel(theme)} title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
mouseEnterDelay={0.8} mouseEnterDelay={0.8}
placement="right"> placement="right">
<Icon theme={theme} onClick={() => setTheme(theme === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark)}> <Icon theme={theme} onClick={toggleTheme}>
{theme === ThemeMode.dark ? <Moon size={20} className="icon" /> : <Sun size={20} className="icon" />} {settedTheme === ThemeMode.dark ? (
<Moon size={20} className="icon" />
) : settedTheme === ThemeMode.light ? (
<Sun size={20} className="icon" />
) : (
<Monitor size={20} className="icon" />
)}
</Icon> </Icon>
</Tooltip> </Tooltip>
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right"> <Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right">

View File

@ -1,4 +1,3 @@
import { SyncOutlined } from '@ant-design/icons'
import CodeEditor from '@renderer/components/CodeEditor' import CodeEditor from '@renderer/components/CodeEditor'
import { HStack } from '@renderer/components/Layout' import { HStack } from '@renderer/components/Layout'
import TextBadge from '@renderer/components/TextBadge' import TextBadge from '@renderer/components/TextBadge'
@ -19,7 +18,7 @@ import {
} from '@renderer/store/settings' } from '@renderer/store/settings'
import { ThemeMode } from '@renderer/types' import { ThemeMode } from '@renderer/types'
import { Button, ColorPicker, Segmented, Switch } from 'antd' import { Button, ColorPicker, Segmented, Switch } from 'antd'
import { Minus, Plus, RotateCcw } from 'lucide-react' import { Minus, Monitor, Moon, Plus, RotateCcw, Sun } from 'lucide-react'
import { FC, useCallback, useEffect, useMemo, useState } from 'react' import { FC, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
@ -108,7 +107,7 @@ const DisplaySettings: FC = () => {
value: ThemeMode.light, value: ThemeMode.light,
label: ( label: (
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}> <div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
<i className="iconfont icon-theme icon-theme-light" /> <Sun size={16} />
<span>{t('settings.theme.light')}</span> <span>{t('settings.theme.light')}</span>
</div> </div>
) )
@ -117,7 +116,7 @@ const DisplaySettings: FC = () => {
value: ThemeMode.dark, value: ThemeMode.dark,
label: ( label: (
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}> <div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
<i className="iconfont icon-theme icon-dark1" /> <Moon size={16} />
<span>{t('settings.theme.dark')}</span> <span>{t('settings.theme.dark')}</span>
</div> </div>
) )
@ -126,7 +125,7 @@ const DisplaySettings: FC = () => {
value: ThemeMode.system, value: ThemeMode.system,
label: ( label: (
<div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}> <div style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
<SyncOutlined /> <Monitor size={16} />
<span>{t('settings.theme.system')}</span> <span>{t('settings.theme.system')}</span>
</div> </div>
) )