mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-02-06 02:51:07 +08:00
refactor(ui): enhance component interactions and layout adjustments
- Updated ChatNavbar to remove unnecessary padding for a cleaner look. - Added min-height to AddButton for consistent button sizing. - Introduced hover state management in AgentItem and AssistantItem for improved user experience. - Refactored dropdown menu handling in AgentItem and AssistantItem to enhance interaction. - Adjusted margin in HeaderRow for better spacing. - Modified SessionWorkspaceMeta to display folder names more clearly with tooltips. These changes aim to improve the overall UI responsiveness and clarity in component interactions.
This commit is contained in:
parent
78c6f97248
commit
bd798284df
@ -67,7 +67,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
}
|
||||
|
||||
return (
|
||||
<NavbarHeader className="home-navbar" style={{ height: 'var(--navbar-height)', paddingRight: 16 }}>
|
||||
<NavbarHeader className="home-navbar" style={{ height: 'var(--navbar-height)' }}>
|
||||
<div className="flex h-full min-w-0 flex-1 shrink items-center overflow-auto">
|
||||
{isTopNavbar && showAssistants && (
|
||||
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={0.8}>
|
||||
|
||||
@ -6,6 +6,7 @@ import styled from 'styled-components'
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
height: 36px;
|
||||
min-height: 36px;
|
||||
width: calc(var(--assistants-width) - 20px);
|
||||
justify-content: flex-start;
|
||||
border-radius: var(--list-item-border-radius);
|
||||
|
||||
@ -9,7 +9,7 @@ import type { MenuProps } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import { Bot, MoreVertical } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback, useMemo } from 'react'
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
// const logger = loggerService.withContext('AgentItem')
|
||||
@ -24,6 +24,7 @@ interface AgentItemProps {
|
||||
const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) => {
|
||||
const { t } = useTranslation()
|
||||
const { clickAssistantToShowTopic, topicPosition, assistantIconType } = useSettings()
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
// Show session sidebar if setting is enabled (reusing the assistant setting for consistency)
|
||||
@ -35,13 +36,9 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
||||
onPress()
|
||||
}, [clickAssistantToShowTopic, topicPosition, onPress])
|
||||
|
||||
const handleMoreClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
agent.id && AgentSettingsPopup.show({ agentId: agent.id })
|
||||
},
|
||||
[agent.id]
|
||||
)
|
||||
const handleMenuButtonClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
}, [])
|
||||
|
||||
const menuItems: MenuProps['items'] = useMemo(
|
||||
() => [
|
||||
@ -75,17 +72,26 @@ const AgentItem: FC<AgentItemProps> = ({ agent, isActive, onDelete, onPress }) =
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['contextMenu']}
|
||||
popupRender={(menu) => <div onPointerDown={(e) => e.stopPropagation()}>{menu}</div>}>
|
||||
<Container onClick={handlePress} isActive={isActive}>
|
||||
<Container
|
||||
onClick={handlePress}
|
||||
isActive={isActive}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}>
|
||||
<AssistantNameRow className="name" title={agent.name ?? agent.id}>
|
||||
<AgentNameWrapper>
|
||||
<AgentLabel agent={agent} hideIcon={assistantIconType === 'none'} />
|
||||
</AgentNameWrapper>
|
||||
{isActive && (
|
||||
<MenuButton onClick={handleMoreClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
{(isActive || isHovered) && (
|
||||
<Dropdown
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['click']}
|
||||
popupRender={(menu) => <div onPointerDown={(e) => e.stopPropagation()}>{menu}</div>}>
|
||||
<MenuButton onClick={handleMenuButtonClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
</Dropdown>
|
||||
)}
|
||||
{!isActive && assistantIconType !== 'none' && <BotIcon />}
|
||||
{!isActive && !isHovered && assistantIconType !== 'none' && <BotIcon />}
|
||||
</AssistantNameRow>
|
||||
</Container>
|
||||
</Dropdown>
|
||||
|
||||
@ -69,6 +69,7 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
const { assistants, updateAssistants } = useAssistants()
|
||||
|
||||
const [isPending, setIsPending] = useState(false)
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
useEffect(() => {
|
||||
@ -148,20 +149,20 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
[assistant.emoji, assistantName]
|
||||
)
|
||||
|
||||
const handleMoreClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
AssistantSettingsPopup.show({ assistant })
|
||||
},
|
||||
[assistant]
|
||||
)
|
||||
const handleMenuButtonClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['contextMenu']}
|
||||
popupRender={(menu) => <div onPointerDown={(e) => e.stopPropagation()}>{menu}</div>}>
|
||||
<Container onClick={handleSwitch} isActive={isActive}>
|
||||
<Container
|
||||
onClick={handleSwitch}
|
||||
isActive={isActive}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}>
|
||||
<AssistantNameRow className="name" title={fullAssistantName}>
|
||||
<AssistantAvatar
|
||||
assistant={assistant}
|
||||
@ -170,10 +171,15 @@ const AssistantItem: FC<AssistantItemProps> = ({
|
||||
/>
|
||||
<AssistantName className="text-nowrap">{assistantName}</AssistantName>
|
||||
</AssistantNameRow>
|
||||
{isActive && (
|
||||
<MenuButton onClick={handleMoreClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
{(isActive || isHovered) && (
|
||||
<Dropdown
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['click']}
|
||||
popupRender={(menu) => <div onPointerDown={(e) => e.stopPropagation()}>{menu}</div>}>
|
||||
<MenuButton onClick={handleMenuButtonClick}>
|
||||
<MoreVertical size={14} className="text-[var(--color-text-secondary)]" />
|
||||
</MenuButton>
|
||||
</Dropdown>
|
||||
)}
|
||||
</Container>
|
||||
</Dropdown>
|
||||
|
||||
@ -104,9 +104,11 @@ const Sessions: React.FC<SessionsProps> = ({ agentId }) => {
|
||||
scrollerStyle={{ overflowX: 'hidden' }}
|
||||
autoHideScrollbar
|
||||
header={
|
||||
<AddButton onClick={createDefaultSession} disabled={creatingSession} className="-mt-[4px] mb-[6px]">
|
||||
{t('agent.session.add.title')}
|
||||
</AddButton>
|
||||
<div className="mt-[2px]">
|
||||
<AddButton onClick={createDefaultSession} disabled={creatingSession} className="-mt-[4px] mb-[6px]">
|
||||
{t('agent.session.add.title')}
|
||||
</AddButton>
|
||||
</div>
|
||||
}>
|
||||
{(session) => (
|
||||
<SessionItem
|
||||
|
||||
@ -911,7 +911,7 @@ const HeaderRow = styled.div`
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding-right: 10px;
|
||||
margin-bottom: 6px;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 2px;
|
||||
`
|
||||
|
||||
|
||||
@ -130,14 +130,22 @@ const SessionWorkspaceMeta: FC<{ agent: AgentEntity; session: AgentSessionEntity
|
||||
// ? t(permissionModeCard.titleKey, permissionModeCard.titleFallback)
|
||||
// : permissionMode
|
||||
|
||||
const getLastFolderName = (path: string): string => {
|
||||
const trimmedPath = path.replace(/[/\\]+$/, '')
|
||||
const parts = trimmedPath.split(/[/\\]/)
|
||||
return parts[parts.length - 1] || path
|
||||
}
|
||||
|
||||
const infoItems: ReactNode[] = []
|
||||
|
||||
const InfoTag = ({
|
||||
text,
|
||||
tooltip,
|
||||
className,
|
||||
onClick
|
||||
}: {
|
||||
text: string
|
||||
tooltip?: string
|
||||
className?: string
|
||||
classNames?: {}
|
||||
onClick?: (e: React.MouseEvent) => void
|
||||
@ -148,7 +156,7 @@ const SessionWorkspaceMeta: FC<{ agent: AgentEntity; session: AgentSessionEntity
|
||||
onClick !== undefined ? 'cursor-pointer' : undefined,
|
||||
className
|
||||
)}
|
||||
title={text}
|
||||
title={tooltip ?? text}
|
||||
onClick={onClick}>
|
||||
<Folder className="h-3.5 w-3.5 shrink-0" />
|
||||
<span className="block truncate">{text}</span>
|
||||
@ -161,7 +169,8 @@ const SessionWorkspaceMeta: FC<{ agent: AgentEntity; session: AgentSessionEntity
|
||||
infoItems.push(
|
||||
<InfoTag
|
||||
key="path"
|
||||
text={firstAccessiblePath}
|
||||
text={getLastFolderName(firstAccessiblePath)}
|
||||
tooltip={firstAccessiblePath}
|
||||
className="max-w-60 transition-colors hover:border-primary hover:text-primary"
|
||||
onClick={() => {
|
||||
window.api.file
|
||||
|
||||
Loading…
Reference in New Issue
Block a user