feat: improved ui effects and rendering for components

- Added smooth all property transition effect to Icon component.
- Added hover effect and conditional rendering for Switch Topic Sidebar button on current assistant.
- Updated the existing conditional options array to consistently include both topic and settings options.
- Improved hover effects on topic list items.
This commit is contained in:
kangfenmao 2024-09-20 15:38:52 +08:00
parent 1ec7df9a7e
commit 6bb7b2ca5d
8 changed files with 69 additions and 66 deletions

View File

@ -22,7 +22,7 @@
--color-background: #181818;
--color-background-soft: var(--color-black-soft);
--color-background-mute: var(--color-black-mute);
--color-background-mute: var(--color-black-soft);
--color-primary: #00b96b;
--color-primary-soft: #00b96b99;

View File

@ -48,12 +48,12 @@ const Sidebar: FC = () => {
<Menus onClick={MinApp.onClose}>
<StyledLink onClick={() => to('/')}>
<Icon className={isRoute('/')}>
<i className="iconfont icon-chat"></i>
<i className="iconfont icon-chat" />
</Icon>
</StyledLink>
<StyledLink onClick={() => to('/agents')}>
<Icon className={isRoute('/agents')}>
<i className="iconfont icon-business-smart-assistant"></i>
<i className="iconfont icon-business-smart-assistant" />
</Icon>
</StyledLink>
<StyledLink onClick={() => to('/translate')}>
@ -63,7 +63,7 @@ const Sidebar: FC = () => {
</StyledLink>
<StyledLink onClick={() => to('/apps')}>
<Icon className={isRoute('/apps')}>
<i className="iconfont icon-appstore"></i>
<i className="iconfont icon-appstore" />
</Icon>
</StyledLink>
<StyledLink onClick={() => to('/files')}>
@ -76,7 +76,7 @@ const Sidebar: FC = () => {
<Menus onClick={MinApp.onClose}>
<StyledLink onClick={() => to(isLocalAi ? '/settings/assistant' : '/settings/provider')}>
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
<i className="iconfont icon-setting"></i>
<i className="iconfont icon-setting" />
</Icon>
</StyledLink>
</Menus>
@ -128,6 +128,7 @@ const Icon = styled.div`
margin-bottom: 5px;
transition: background-color 0.2s ease;
-webkit-app-region: none;
transition: all 0.2s ease;
.iconfont,
.anticon {
color: var(--color-icon);
@ -139,7 +140,7 @@ const Icon = styled.div`
font-size: 17px;
}
&:hover {
background-color: var(--color-background-mute);
background-color: var(--color-background-soft);
cursor: pointer;
.iconfont,
.anticon {
@ -147,7 +148,7 @@ const Icon = styled.div`
}
}
&.active {
background-color: var(--color-background-soft);
background-color: var(--color-background-mute);
.iconfont,
.anticon {
color: var(--color-icon-white);

View File

@ -66,7 +66,7 @@ const resources = {
},
chat: {
save: 'Save',
'default.name': 'Default Assistant',
'default.name': '⭐️ Default Assistant',
'default.description': "Hello, I'm Default Assistant. You can start chatting with me right away",
'default.topic.name': 'Default Topic',
'topics.title': 'Topics',
@ -344,7 +344,7 @@ const resources = {
},
chat: {
save: '保存',
'default.name': '默认助手',
'default.name': '⭐️ 默认助手',
'default.description': '你好,我是默认助手。你可以立刻开始跟我聊天。',
'default.topic.name': '默认话题',
'topics.title': '话题',

View File

@ -186,6 +186,7 @@ const Assistants: FC<Props> = ({
list={list}
onUpdate={updateAssistants}
droppableProps={{ isDropDisabled: !isEmpty(search) }}
style={{ paddingBottom: dragging ? '34px' : 0 }}
onDragStart={() => setDragging(true)}
onDragEnd={() => setDragging(false)}>
{(assistant) => {
@ -194,11 +195,11 @@ const Assistants: FC<Props> = ({
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
<AssistantItem onClick={() => onSwitchAssistant(assistant)} className={isCurrent ? 'active' : ''}>
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
<ArrowRightButton
className={`arrow-button ${isCurrent ? 'active' : ''}`}
onClick={() => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)}>
<i className="iconfont icon-gridlines" />
</ArrowRightButton>
{isCurrent && (
<ArrowRightButton onClick={() => EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)}>
<i className="iconfont icon-gridlines" />
</ArrowRightButton>
)}
{false && <TopicCount className="topics-count">{assistant.topics.length}</TopicCount>}
</AssistantItem>
</Dropdown>
@ -206,10 +207,12 @@ const Assistants: FC<Props> = ({
}}
</DragableList>
{!dragging && (
<AddButton onClick={onCreateAssistant}>
<AddButtonText>{t('chat.add.assistant.title')}</AddButtonText>
<PlusOutlined />
</AddButton>
<AssistantItem onClick={onCreateAssistant}>
<AssistantName>
<PlusOutlined style={{ color: 'var(--color-text-2)', marginRight: 4 }} />
{t('chat.add.assistant.title')}
</AssistantName>
</AssistantItem>
)}
</Container>
)
@ -230,15 +233,18 @@ const AssistantItem = styled.div`
justify-content: space-between;
padding: 7px 10px;
position: relative;
border-radius: 6px;
border-radius: 4px;
margin: 0 10px;
padding-right: 35px;
cursor: pointer;
font-family: Ubuntu;
cursor: pointer;
.iconfont {
opacity: 0;
color: var(--color-text-3);
}
&:hover {
background-color: var(--color-background-soft);
}
&.active {
background-color: var(--color-background-mute);
.name {
@ -311,29 +317,4 @@ const CommandKey = styled.div`
margin-right: -4px;
`
const AddButton = styled.div`
height: 34px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 6px 10px;
margin: 0 10px;
margin-top: -2px;
color: var(--color-text-2);
transition: all 0.2s ease-in-out;
font-size: 13px;
cursor: pointer;
border-radius: 8px;
.anticon {
margin: 0 4px;
}
&:hover {
color: var(--color-text-1);
background-color: var(--color-background-soft);
}
`
const AddButtonText = styled.span``
export default Assistants

View File

@ -1,6 +1,7 @@
import {
ClearOutlined,
ControlOutlined,
FormOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
PauseCircleOutlined,
@ -256,11 +257,6 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
textareaRef.current?.focus()
}, [assistant])
useEffect(() => {
document.addEventListener('paste', onPaste)
return () => document.removeEventListener('paste', onPaste)
}, [onPaste])
return (
<Container>
<AttachmentPreview files={files} setFiles={setFiles} />
@ -281,13 +277,14 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
onBlur={() => setInputFocus(false)}
onInput={onInput}
disabled={searching}
onPaste={(e) => onPaste(e.nativeEvent)}
onClick={() => searching && dispatch(setSearching(false))}
/>
<Toolbar>
<ToolbarMenu>
<Tooltip placement="top" title={t('chat.input.new_topic')} arrow>
<ToolbarButton type="text" onClick={addNewTopic}>
<i className="iconfont icon-a-addchat" />
<FormOutlined />
</ToolbarButton>
</Tooltip>
<Tooltip placement="top" title={t('chat.input.clear')} arrow>

View File

@ -1,3 +1,4 @@
import { FormOutlined } from '@ant-design/icons'
import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingPopup'
@ -8,6 +9,7 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
import { useSettings } from '@renderer/hooks/useSettings'
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
import { Assistant, Topic } from '@renderer/types'
import { Switch } from 'antd'
import { FC, useCallback } from 'react'
@ -41,7 +43,8 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveTopic }) => {
addTopic(topic)
setActiveTopic(topic)
db.topics.add({ id: topic.id, messages: [] })
window.message.success({ content: t('message.topic.added') })
window.message.success({ content: t('message.topic.added'), key: 'topic-added' })
setTimeout(() => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR), 0)
}, [addTopic, setActiveTopic, t])
return (
@ -52,7 +55,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveTopic }) => {
<i className="iconfont icon-hide-sidebar" />
</NewButton>
<NewButton onClick={addNewTopic}>
<i className="iconfont icon-a-addchat" />
<FormOutlined />
</NewButton>
</NavbarLeft>
)}

View File

@ -102,8 +102,16 @@ const RightSidebar: FC<Props> = ({ activeAssistant, activeTopic, setActiveAssist
options={
[
position === 'left' && topicPosition === 'left' ? assistantTab : undefined,
{ label: t('common.topics'), value: 'topic', icon: <BarsOutlined /> },
{ label: t('settings.title'), value: 'settings', icon: <SettingOutlined /> }
{
label: t('common.topics'),
value: 'topic',
icon: <BarsOutlined />
},
{
label: t('settings.title'),
value: 'settings',
icon: <SettingOutlined />
}
].filter(Boolean) as SegmentedProps['options']
}
onChange={(value) => setTab(value as 'topic' | 'settings')}

View File

@ -136,8 +136,11 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
return (
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
<TopicListItem className={isActive ? 'active' : ''} onClick={() => onSwitchTopic(topic)}>
<TopicName className="name">{topic.name}</TopicName>
{assistant.topics.length > 1 && (
<TopicName className="name">
<TopicHash>#</TopicHash>
{topic.name.replace('`', '')}
</TopicName>
{assistant.topics.length > 1 && isActive && (
<MenuButton
className="menu"
onClick={(e) => {
@ -171,8 +174,7 @@ const Container = styled.div`
const TopicListItem = styled.div`
padding: 7px 10px;
margin: 0 10px;
cursor: pointer;
border-radius: 6px;
border-radius: 4px;
font-family: Ubuntu;
font-size: 13px;
display: flex;
@ -180,10 +182,18 @@ const TopicListItem = styled.div`
justify-content: space-between;
align-items: center;
position: relative;
font-family: Ubuntu;
cursor: pointer;
.menu {
opacity: 0;
color: var(--color-text-3);
}
&:hover {
background-color: var(--color-background-soft);
.name {
opacity: 1;
}
}
&.active {
background-color: var(--color-background-mute);
.name {
@ -214,17 +224,20 @@ const MenuButton = styled.div`
flex-direction: row;
justify-content: center;
align-items: center;
width: 30px;
height: 24px;
min-width: 24px;
min-height: 24px;
border-radius: 4px;
min-width: 22px;
min-height: 22px;
position: absolute;
right: 10px;
top: 5px;
right: 8px;
top: 6px;
.anticon {
font-size: 12px;
}
`
const TopicHash = styled.span`
font-size: 13px;
color: var(--color-text-3);
margin-right: 2px;
`
export default Topics