refactor: migrate all antd Tooltip components to HeroUI Tooltip (#10295)
* refactor: migrate tooltip components to @cherrystudio/ui - Replace all antd Tooltip + InfoCircleOutlined patterns with InfoTooltip component - Replace all antd Tooltip + QuestionCircleOutlined patterns with HelpTooltip component - Migrate all WarnTooltip imports to @cherrystudio/ui - Add onClick support to InfoTooltip and HelpTooltip components - Remove local tooltip components from renderer - Update eslint config to restrict antd Tooltip imports - Clean up unused imports and styled components 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: replace tooltip * fix: yarn format * fix: type check * Update QuickModelPopup.tsx * fix: yarn test * fix: ci error * Update TabContainer.tsx * fix: ci error * fix: ci error * fix: issue * fix: ci * fix: again * refactor(ui): replace Tooltip title prop with content for consistency * refactor(Tooltip): improve Tooltip component by extending props and simplifying implementation - Extend TooltipProps from HeroUITooltipProps instead of redefining - Remove redundant props and use spread operator for classNames - Export TooltipProps type for better type support * refactor(HelpTooltip): rename title prop to content and simplify component Update HelpTooltip component to use TooltipProps interface and rename title prop to content for consistency Update all instances where HelpTooltip is used to reflect the prop name change * refactor(IconTooltips): consolidate tooltip components into unified module Move HelpTooltip, InfoTooltip, and WarnTooltip into a single IconTooltips directory with shared types Update exports in components index to use new module structure * refactor(tooltip): update InfoTooltip prop from title to content and simplify component Consolidate tooltip props interface and update all instances to use content prop instead of title for consistency. Remove redundant interface definitions and simplify InfoTooltip component implementation. * refactor(ui): rename WarnTooltip prop from title to content for consistency Update all instances of WarnTooltip component to use content prop instead of title for better consistency with Tooltip component interface. Also simplify the component props by extending IconTooltipProps type. * fix(tooltip): update tooltip usage - Replace deprecated props like `mouseEnterDelay` and `mouseLeaveDelay` with `delay` and `closeDelay` - Rename `arrow` prop to `showArrow` for better semantics - Update styling props to use `classNames` instead of inline styles - Remove unnecessary props like `fresh` and `destroyOnHidden` * refactor(components): remove redundant placement="top" from Tooltip components The placement="top" prop was removed from all Tooltip components since it's the default value and redundant. This change improves code cleanliness without affecting functionality. * fix(HeaderNavbar): add tooltip placement for sidebar toggle buttons * fix(ui): add delay to tooltip components for better user experience * refactor(tooltip): adjust tooltip behavior and styling across components - Remove default delay values from base Tooltip component - Add delay and closeDelay props to specific tooltip instances - Fix tooltip compatibility issue with Antd Dropdown - Adjust tooltip placement and styling in various components * fix(ui): set closeDelay to 0 for Tooltip components to improve responsiveness Prevent tooltip delay from causing poor user experience by making them close immediately when mouse leaves the element * refactor(ui): remove redundant tooltip placement prop The 'placement="top"' prop was removed from Tooltip components as it's the default value and doesn't need to be explicitly set. * fix(ui): adjust tooltip delays for better user experience - Set consistent default delay of 1000ms for window controls - Increase delay for sidebar toggle tooltips to 2000ms - Adjust various message action tooltip delays between 600-1200ms * fix(SelectModelPopup): add delay props to provider settings tooltip Add delay and closeDelay props to Tooltip component to improve user experience by preventing accidental triggers * style(HelpTooltip): add cursor help style to improve UX * fix(components): add tooltip delay and placement props for better UX Add delay prop to CustomTag and ModelIdWithTags tooltips to prevent flickering Set placement prop for LocalBackupManager tooltip to top-start Add closeDelay prop to HelpTooltip in SaveToKnowledgePopup for immediate closing * refactor(ModelSelectButton): simplify tooltip props by using TooltipProps type Replace individual tooltip placement props with TooltipProps type from ui library for better maintainability * fix(ui): remove tooltip close delay for better user experience * docs(tooltip): add jsdoc comments explaining tooltip wrapper behavior * refactor(Tooltip): clarify showArrow prop * fix(Inputbar): set closeDelay to 0 for pause tooltip to improve UX Prevent tooltip from staying visible after interaction by removing the close delay * style(InputbarTools): improve tooltip consistency and css formatting - Add closeDelay to new topic tooltip for consistency - Remove redundant line breaks in tooltip props - Format css transition properties for better readability * chore: add tailwindCSS class attributes to vscode settings * fix(tooltips): improve tooltip behavior and styling across components - Add closeDelay=0 to most tooltips for instant closing - Add custom styling to CitationTooltip and ChatFlowHistory tooltips - Adjust delay times for navigation tooltips - Remove conflicting Tooltip wrappers around Popconfirm actions * refactor(ui): adjust tooltip delays and placements across components - Remove redundant isOpen prop from CustomNode tooltip - Standardize tooltip delays and placements in MessageGroupMenuBar, MessageTokens, ChatNavbar - Simplify tooltip wrapper structure in HeaderNavbar - Add consistent tooltip delays in MessageGroupModelList - Set tooltip placements in MinimalToolbar * refactor(Tooltip): enhance tooltip structure and props - Add className prop to Tooltip component for better customization - Wrap children in a div with relative positioning to improve layout * refactor(Tooltip): enhance props structure for improved customization - Update Tooltip component to allow optional classNames with a placeholder property - Modify child wrapper to utilize classNames for better styling control * refactor(IconTooltips): consolidate icon props into single iconProps object Replace individual icon styling props (iconColor, iconSize, iconStyle) with a unified iconProps object using LucideProps type. This simplifies the component API and improves maintainability by using a standardized props structure across all icon tooltip components. * feat(JoplinSettings): add help button to open Joplin documentation Add a help button in Joplin settings that opens the official Joplin documentation in a minapp popup when clicked. This provides users with quick access to Joplin's help resources. * feat(NotionSettings): add help link click handler for notion title Add click handler to open help documentation when clicking on Notion title in settings * feat(S3Settings): add help link to S3 settings title Add click handler to open documentation for S3 settings when title is clicked * feat(settings): add help button for siyuan integration Add click handler to open help documentation for siyuan integration settings * feat(yuque-settings): add help button to open yuque token guide Add a help button in Yuque settings that opens a minapp popup with Yuque's token guide. This helps users easily access documentation for generating API tokens. * fix(ui): adjust tooltip delay settings for better user experience Set closeDelay to 0 for reset button tooltip to prevent lingering Add delay of 500ms for api key list tooltip to avoid accidental triggers * fix(ModelList): set closeDelay to 0 for all Tooltip components Prevent tooltips from staying open longer than necessary by immediately closing them on mouse leave * fix(ui): improve tooltip placement and delay settings adjust tooltip placement and delay for better user experience * refactor(tests): update tooltip mock implementation and snapshots - Consolidate tooltip mock to handle both title and content props - Remove deprecated placement attributes from snapshots - Clean up test tooltip content assertions * refactor: remove unnecessary whitespace and simplify tooltip components clean up code by removing redundant whitespace and simplifying tooltip component usage across multiple files --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: icarus <eurfelux@gmail.com> Co-authored-by: MyPrototypeWhat <daoquqiexing@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { CodeEditor, type CodeEditorHandles } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { CopyIcon, FilePngIcon } from '@renderer/components/Icons'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
@@ -8,7 +8,7 @@ import { useTemporaryValue } from '@renderer/hooks/useTemporaryValue'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { extractHtmlTitle, getFileNameFromHtmlTitle } from '@renderer/utils/formats'
|
||||
import { captureScrollableIframeAsBlob, captureScrollableIframeAsDataURL } from '@renderer/utils/image'
|
||||
import { Dropdown, Modal, Splitter, Tooltip, Typography } from 'antd'
|
||||
import { Dropdown, Modal, Splitter, Typography } from 'antd'
|
||||
import { Camera, Check, Code, Eye, Maximize2, Minimize2, SaveIcon, SquareSplitHorizontal, X } from 'lucide-react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -126,7 +126,7 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
}
|
||||
]
|
||||
}}>
|
||||
<Tooltip title={t('html_artifacts.capture.label')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('html_artifacts.capture.label')} closeDelay={0}>
|
||||
<Button variant="light" startContent={<Camera size={16} />} isIconOnly className="nodrag" />
|
||||
</Tooltip>
|
||||
</Dropdown>
|
||||
@@ -164,7 +164,7 @@ const HtmlArtifactsPopup: React.FC<HtmlArtifactsPopupProps> = ({ open, title, ht
|
||||
}}
|
||||
/>
|
||||
<ToolbarWrapper>
|
||||
<Tooltip title={t('code_block.edit.save.label')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('code_block.edit.save.label')} closeDelay={0}>
|
||||
<ToolbarButton radius="full" size="lg" isIconOnly onPress={handleSave}>
|
||||
{saved ? (
|
||||
<Check size={16} color="var(--color-status-success)" />
|
||||
|
||||
@@ -6,8 +6,8 @@ import CodeToolButton from '../button'
|
||||
|
||||
// Mock Antd components
|
||||
const mocks = vi.hoisted(() => ({
|
||||
Tooltip: vi.fn(({ children, title }) => (
|
||||
<div data-testid="tooltip" data-title={title}>
|
||||
Tooltip: vi.fn(({ children, title, content }) => (
|
||||
<div data-testid="tooltip" data-title={content || title}>
|
||||
{children}
|
||||
</div>
|
||||
)),
|
||||
@@ -19,10 +19,13 @@ const mocks = vi.hoisted(() => ({
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: mocks.Tooltip,
|
||||
Dropdown: mocks.Dropdown
|
||||
}))
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Tooltip: mocks.Tooltip
|
||||
}))
|
||||
|
||||
// Mock ToolWrapper
|
||||
vi.mock('../styles', () => ({
|
||||
ToolWrapper: ({ children, onClick }: { children: React.ReactNode; onClick?: () => void }) => (
|
||||
|
||||
@@ -14,8 +14,8 @@ const mocks = vi.hoisted(() => ({
|
||||
{tool.icon}
|
||||
</div>
|
||||
)),
|
||||
Tooltip: vi.fn(({ children, title }) => (
|
||||
<div data-testid="tooltip" data-title={title}>
|
||||
Tooltip: vi.fn(({ children, title, content }) => (
|
||||
<div data-testid="tooltip" data-title={content || title}>
|
||||
{children}
|
||||
</div>
|
||||
)),
|
||||
@@ -39,11 +39,8 @@ vi.mock('../button', () => ({
|
||||
default: mocks.CodeToolButton
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: mocks.Tooltip
|
||||
}))
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Tooltip: mocks.Tooltip,
|
||||
RowFlex: mocks.RowFlex
|
||||
}))
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { ActionTool } from '@renderer/components/ActionTools'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import { Dropdown } from 'antd'
|
||||
import { memo, useMemo } from 'react'
|
||||
|
||||
import { ToolWrapper } from './styles'
|
||||
@@ -11,7 +12,7 @@ interface CodeToolButtonProps {
|
||||
const CodeToolButton = ({ tool }: CodeToolButtonProps) => {
|
||||
const mainTool = useMemo(
|
||||
() => (
|
||||
<Tooltip key={tool.id} title={tool.tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip key={tool.id} content={tool.tooltip} delay={500} closeDelay={0}>
|
||||
<ToolWrapper onClick={tool.onClick}>{tool.icon}</ToolWrapper>
|
||||
</Tooltip>
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { ActionTool } from '@renderer/components/ActionTools'
|
||||
import { Tooltip } from 'antd'
|
||||
import { EllipsisVertical } from 'lucide-react'
|
||||
import { memo, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -39,7 +39,7 @@ const CodeToolbar = ({ tools }: { tools: ActionTool[] }) => {
|
||||
{/* 有多个快捷工具时通过 more 按钮展示 */}
|
||||
{quickToolButtons}
|
||||
{quickTools.length > 1 && (
|
||||
<Tooltip title={t('code_block.more')} mouseEnterDelay={0.5}>
|
||||
<Tooltip content={t('code_block.more')} delay={500}>
|
||||
<ToolWrapper onClick={() => setShowQuickTools(!showQuickTools)} className={showQuickTools ? 'active' : ''}>
|
||||
<EllipsisVertical className="tool-icon" />
|
||||
</ToolWrapper>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import i18n from '@renderer/i18n'
|
||||
import type { InputRef } from 'antd'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import { Search } from 'lucide-react'
|
||||
import { motion } from 'motion/react'
|
||||
import React, { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
@@ -93,7 +94,7 @@ const CollapsibleSearchBar = ({
|
||||
}}
|
||||
style={{ cursor: 'pointer', display: 'flex' }}
|
||||
onClick={() => setSearchVisible(true)}>
|
||||
<Tooltip title={tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip content={tooltip} delay={500} closeDelay={0}>
|
||||
{icon}
|
||||
</Tooltip>
|
||||
</motion.div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import NarrowLayout from '@renderer/pages/home/Messages/NarrowLayout'
|
||||
import { Tooltip } from 'antd'
|
||||
import { debounce } from 'lodash'
|
||||
import { CaseSensitive, ChevronDown, ChevronUp, User, WholeWord, X } from 'lucide-react'
|
||||
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||
@@ -363,17 +363,17 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
/>
|
||||
<ToolBar>
|
||||
{showUserToggle && (
|
||||
<Tooltip title={t('button.includes_user_questions')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('button.includes_user_questions')} delay={800}>
|
||||
<ActionIconButton
|
||||
onPress={userOutlinedButtonOnClick}
|
||||
isIconOnly
|
||||
icon={
|
||||
<User size={18} style={{ color: includeUser ? 'var(--color-link)' : 'var(--color-icon)' }} />
|
||||
}
|
||||
/>
|
||||
/>{' '}
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('button.case_sensitive')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('button.case_sensitive')} delay={800}>
|
||||
<ActionIconButton
|
||||
onPress={caseSensitiveButtonOnClick}
|
||||
icon={
|
||||
@@ -382,9 +382,9 @@ export const ContentSearch = React.forwardRef<ContentSearchRef, Props>(
|
||||
style={{ color: isCaseSensitive ? 'var(--color-link)' : 'var(--color-icon)' }}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
/>{' '}
|
||||
</Tooltip>
|
||||
<Tooltip title={t('button.whole_word')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('button.whole_word')} delay={800}>
|
||||
<ActionIconButton
|
||||
onPress={wholeWordButtonOnClick}
|
||||
icon={
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { Copy } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -47,7 +47,7 @@ const CopyButton: FC<CopyButtonProps> = ({
|
||||
)
|
||||
|
||||
if (tooltip) {
|
||||
return <Tooltip title={tooltip}>{button}</Tooltip>
|
||||
return <Tooltip content={tooltip}>{button}</Tooltip>
|
||||
}
|
||||
|
||||
return button
|
||||
|
||||
+2
-1
@@ -20,7 +20,8 @@ exports[`DraggableVirtualList > snapshot > should match snapshot with custom sty
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ScrollBarContainer-eGlIoO jgKpou virtual-scroller"
|
||||
class="virtual-scroller"
|
||||
data-testid="scrollbar"
|
||||
style="height: 100%; width: 100%; overflow-y: auto; position: relative;"
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CheckCircleFilled, CloseCircleFilled, ExclamationCircleFilled, LoadingOutlined } from '@ant-design/icons'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Tooltip, Typography } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { Typography } from 'antd'
|
||||
import React, { memo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -51,7 +52,7 @@ const HealthStatusIndicator: React.FC<HealthStatusIndicatorProps> = ({
|
||||
return (
|
||||
<Flex className="items-center gap-1.5">
|
||||
{latencyText && <LatencyText type="secondary">{latencyText}</LatencyText>}
|
||||
<Tooltip title={tooltip} styles={{ body: { userSelect: 'text' } }}>
|
||||
<Tooltip content={tooltip} className="select-text">
|
||||
<IndicatorWrapper $type={overallStatus}>{icon}</IndicatorWrapper>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -9,7 +9,7 @@ const ReasoningIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip title={t('models.type.reasoning')} placement="top">
|
||||
<Tooltip content={t('models.type.reasoning')}>
|
||||
<Icon className="iconfont icon-thinking" {...(props as any)} />
|
||||
</Tooltip>
|
||||
</Container>
|
||||
|
||||
@@ -279,7 +279,7 @@ export function PoeLogo(props: SVGProps<SVGSVGElement>) {
|
||||
y1="7.303"
|
||||
y2="27.715">
|
||||
<stop stopColor="#46A6F7"></stop>
|
||||
<stop offset="1" stop-color="#8364FF"></stop>
|
||||
<stop offset="1" stopColor="#8364FF"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
@@ -289,7 +289,7 @@ export function PoeLogo(props: SVGProps<SVGSVGElement>) {
|
||||
y1="23.511"
|
||||
y2="9.464">
|
||||
<stop stopColor="#FF44D3"></stop>
|
||||
<stop offset="1" stop-color="#CF4BFF"></stop>
|
||||
<stop offset="1" stopColor="#CF4BFF"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ToolOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -10,7 +10,7 @@ const ToolsCallingIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElem
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip title={t('models.function_calling')} placement="top">
|
||||
<Tooltip content={t('models.function_calling')}>
|
||||
<Icon {...(props as any)} />
|
||||
</Tooltip>
|
||||
</Container>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ImageIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
@@ -10,7 +10,7 @@ const VisionIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>,
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip title={t('models.type.vision')} placement="top">
|
||||
<Tooltip content={t('models.type.vision')}>
|
||||
<Icon size={15} {...(props as any)} />
|
||||
</Tooltip>
|
||||
</Container>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { GlobalOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -10,7 +10,7 @@ const WebSearchIcon: FC<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip title={t('models.type.websearch')} placement="top">
|
||||
<Tooltip content={t('models.type.websearch')}>
|
||||
<Icon {...(props as any)} />
|
||||
</Tooltip>
|
||||
</Container>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { RefreshIcon } from '@renderer/components/Icons'
|
||||
import { useProvider } from '@renderer/hooks/useProvider'
|
||||
import type { Model } from '@renderer/types'
|
||||
import { getErrorMessage } from '@renderer/utils'
|
||||
import { InputNumber, Space, Tooltip } from 'antd'
|
||||
import { InputNumber, Space } from 'antd'
|
||||
import { memo, useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -74,7 +74,7 @@ const InputEmbeddingDimension = ({
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Tooltip title={t('knowledge.dimensions_auto_set')}>
|
||||
<Tooltip content={t('knowledge.dimensions_auto_set')}>
|
||||
<Button
|
||||
role="button"
|
||||
aria-label="Get embedding dimension"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button, Flex } from '@cherrystudio/ui'
|
||||
import { Button, Flex, Tooltip } from '@cherrystudio/ui'
|
||||
import { restoreFromLocal } from '@renderer/services/BackupService'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -168,7 +168,7 @@ export function LocalBackupManager({ visible, onClose, localBackupDir, restoreMe
|
||||
showTitle: false
|
||||
},
|
||||
render: (fileName: string) => (
|
||||
<Tooltip placement="topLeft" title={fileName}>
|
||||
<Tooltip content={fileName} placement="top-start">
|
||||
{fileName}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -10,8 +10,7 @@ import {
|
||||
PushpinOutlined,
|
||||
ReloadOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Avatar } from '@cherrystudio/ui'
|
||||
import { Avatar, Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import WindowControls from '@renderer/components/WindowControls'
|
||||
@@ -26,7 +25,7 @@ import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import type { MinAppType } from '@renderer/types'
|
||||
import { delay } from '@renderer/utils'
|
||||
import { clearWebviewState, getWebviewLoaded, setWebviewLoaded } from '@renderer/utils/webviewStateManager'
|
||||
import { Alert, Drawer, Tooltip } from 'antd'
|
||||
import { Alert, Drawer } from 'antd'
|
||||
import type { WebviewTag } from 'electron'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -401,24 +400,19 @@ const MinappPopupContainer: React.FC = () => {
|
||||
return (
|
||||
<TitleContainer style={{ backgroundColor: backgroundColor }}>
|
||||
<Tooltip
|
||||
title={
|
||||
placement="right-end"
|
||||
className="max-w-100"
|
||||
content={
|
||||
<TitleTextTooltip>
|
||||
{url ?? appInfo.url} <br />
|
||||
<CopyOutlined className="icon-copy" />
|
||||
{t('minapp.popup.rightclick_copyurl')}
|
||||
</TitleTextTooltip>
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="rightBottom"
|
||||
styles={{
|
||||
root: {
|
||||
maxWidth: '400px'
|
||||
}
|
||||
}}>
|
||||
}>
|
||||
<TitleText onContextMenu={(e) => handleCopyUrl(e, url ?? appInfo.url)}>{appInfo.name}</TitleText>
|
||||
</Tooltip>
|
||||
{appInfo.canOpenExternalLink && (
|
||||
<Tooltip title={t('minapp.popup.openExternal')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.openExternal')} delay={800}>
|
||||
<TitleButton onClick={() => handleOpenLink(url ?? appInfo.url)}>
|
||||
<ExportOutlined />
|
||||
</TitleButton>
|
||||
@@ -429,24 +423,24 @@ const MinappPopupContainer: React.FC = () => {
|
||||
className={isWin || isLinux ? 'windows' : ''}
|
||||
style={{ marginRight: isWin || isLinux ? '140px' : 0 }}
|
||||
isTopNavbar={isTopNavbar}>
|
||||
<Tooltip title={t('minapp.popup.goBack')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.goBack')} delay={800}>
|
||||
<TitleButton onClick={() => handleGoBack(appInfo.id)}>
|
||||
<ArrowLeftOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('minapp.popup.goForward')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.goForward')} delay={800}>
|
||||
<TitleButton onClick={() => handleGoForward(appInfo.id)}>
|
||||
<ArrowRightOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('minapp.popup.refresh')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.refresh')} delay={800}>
|
||||
<TitleButton onClick={() => handleReload(appInfo.id)}>
|
||||
<ReloadOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
{appInfo.canPinned && (
|
||||
<Tooltip
|
||||
title={
|
||||
content={
|
||||
appInfo.isPinned
|
||||
? isTopNavbar
|
||||
? t('minapp.remove_from_launchpad')
|
||||
@@ -455,40 +449,40 @@ const MinappPopupContainer: React.FC = () => {
|
||||
? t('minapp.add_to_launchpad')
|
||||
: t('minapp.add_to_sidebar')
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
delay={800}>
|
||||
<TitleButton onClick={() => handleTogglePin(appInfo.id)} className={appInfo.isPinned ? 'pinned' : ''}>
|
||||
<PushpinOutlined style={{ fontSize: 16 }} />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip
|
||||
title={
|
||||
content={
|
||||
minappsOpenLinkExternal
|
||||
? t('minapp.popup.open_link_external_on')
|
||||
: t('minapp.popup.open_link_external_off')
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
delay={800}>
|
||||
<TitleButton onClick={handleToggleOpenExternal} className={minappsOpenLinkExternal ? 'open-external' : ''}>
|
||||
<LinkOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
{isDev && (
|
||||
<Tooltip title={t('minapp.popup.devtools')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.devtools')} delay={800}>
|
||||
<TitleButton onClick={() => handleOpenDevTools(appInfo.id)}>
|
||||
<CodeOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{canMinimize && (
|
||||
<Tooltip title={t('minapp.popup.minimize')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.minimize')} delay={800}>
|
||||
<TitleButton onClick={() => handlePopupMinimize()}>
|
||||
<MinusOutlined />
|
||||
</TitleButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('minapp.popup.close')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Tooltip placement="bottom" content={t('minapp.popup.close')} delay={800}>
|
||||
<TitleButton onClick={() => handlePopupClose(appInfo.id)}>
|
||||
<CloseOutlined />
|
||||
</TitleButton>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { Model } from '@renderer/types'
|
||||
import { Tooltip, Typography } from 'antd'
|
||||
import { Typography } from 'antd'
|
||||
import { memo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -20,20 +21,13 @@ const ModelIdWithTags = ({
|
||||
return (
|
||||
<ListItemName ref={ref} $fontSize={fontSize} style={style}>
|
||||
<Tooltip
|
||||
styles={{
|
||||
root: {
|
||||
width: 'auto',
|
||||
maxWidth: '500px'
|
||||
}
|
||||
}}
|
||||
destroyOnHidden
|
||||
title={
|
||||
content={
|
||||
<Typography.Text style={{ color: 'white' }} copyable={{ text: model.id }}>
|
||||
{model.id}
|
||||
</Typography.Text>
|
||||
}
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top">
|
||||
className="w-auto max-w-125"
|
||||
delay={500}>
|
||||
<NameSpan>{model.name}</NameSpan>
|
||||
</Tooltip>
|
||||
<ModelTagsWithLabel model={model} size={11} style={{ flexShrink: 0 }} />
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import type { TooltipProps } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import type { Model } from '@renderer/types'
|
||||
import type { TooltipProps } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import ModelAvatar from './Avatar/ModelAvatar'
|
||||
@@ -39,7 +38,7 @@ const ModelSelectButton = ({ model, onSelectModel, modelFilter, noTooltip, toolt
|
||||
return button
|
||||
} else {
|
||||
return (
|
||||
<Tooltip title={model.name} {...tooltipProps}>
|
||||
<Tooltip content={model.name} {...tooltipProps}>
|
||||
{button}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Flex, Tooltip } from '@cherrystudio/ui'
|
||||
import { type HealthResult, HealthStatusIndicator } from '@renderer/components/HealthStatusIndicator'
|
||||
import { EditIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import type { ApiKeyWithStatus } from '@renderer/types/healthCheck'
|
||||
import { maskApiKey } from '@renderer/utils/api'
|
||||
import type { InputRef } from 'antd'
|
||||
import { Input, List, Popconfirm, Tooltip, Typography } from 'antd'
|
||||
import { Input, List, Popconfirm, Typography } from 'antd'
|
||||
import { Check, Minus, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useEffect, useRef, useState } from 'react'
|
||||
@@ -108,7 +107,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Flex className="items-center gap-0">
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Tooltip content={t('common.save')}>
|
||||
<Button
|
||||
color={hasUnsavedChanges ? 'primary' : 'default'}
|
||||
variant={hasUnsavedChanges ? 'solid' : 'light'}
|
||||
@@ -118,7 +117,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<Tooltip content={t('common.cancel')}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<X size={16} />}
|
||||
@@ -132,15 +131,12 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
) : (
|
||||
<>
|
||||
<Tooltip
|
||||
title={
|
||||
content={
|
||||
<Typography.Text style={{ color: 'white' }} copyable={{ text: keyStatus.key }}>
|
||||
{keyStatus.key}
|
||||
</Typography.Text>
|
||||
}
|
||||
mouseEnterDelay={0.5}
|
||||
placement="top"
|
||||
// 确保不留下明文
|
||||
destroyOnHidden>
|
||||
delay={500}>
|
||||
<span style={{ cursor: 'help' }}>{maskApiKey(keyStatus.key)}</span>
|
||||
</Tooltip>
|
||||
|
||||
@@ -149,7 +145,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
|
||||
<Flex className="items-center gap-0">
|
||||
{showHealthCheck && (
|
||||
<Tooltip title={t('settings.provider.check')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('settings.provider.check')} closeDelay={0}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<StreamlineGoodHealthAndWellBeing size={18} isActive={keyStatus.checking} />}
|
||||
@@ -159,7 +155,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.edit')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('common.edit')} closeDelay={0}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<EditIcon size={16} />}
|
||||
@@ -175,7 +171,7 @@ const ApiKeyItem: FC<ApiKeyItemProps> = ({
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ color: 'danger' }}>
|
||||
<Tooltip title={t('common.delete')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('common.delete')} closeDelay={0}>
|
||||
<Button variant="light" startContent={<Minus size={16} />} isDisabled={disabled} isIconOnly />
|
||||
</Tooltip>
|
||||
</Popconfirm>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Flex, Tooltip } from '@cherrystudio/ui'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
import { StreamlineGoodHealthAndWellBeing } from '@renderer/components/Icons/SVGIcon'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -11,7 +10,7 @@ import { isProviderSupportAuth } from '@renderer/services/ProviderService'
|
||||
import type { PreprocessProviderId, WebSearchProviderId } from '@renderer/types'
|
||||
import type { ApiKeyWithStatus } from '@renderer/types/healthCheck'
|
||||
import { HealthStatus } from '@renderer/types/healthCheck'
|
||||
import { Card, List, Popconfirm, Space, Tooltip, Typography } from 'antd'
|
||||
import { Card, List, Popconfirm, Space, Typography } from 'antd'
|
||||
import { Plus } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -143,7 +142,7 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
okText={t('common.confirm')}
|
||||
cancelText={t('common.cancel')}
|
||||
okButtonProps={{ color: 'danger' }}>
|
||||
<Tooltip title={t('settings.provider.remove_invalid_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('settings.provider.remove_invalid_keys')} closeDelay={0}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<DeleteIcon size={16} className="lucide-custom" />}
|
||||
@@ -155,7 +154,7 @@ export const ApiKeyList: FC<ApiKeyListProps> = ({ provider, updateProvider, show
|
||||
</Popconfirm>
|
||||
|
||||
{/* 批量检查 */}
|
||||
<Tooltip title={t('settings.provider.check_all_keys')} placement="top" mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('settings.provider.check_all_keys')} closeDelay={0}>
|
||||
<Button
|
||||
variant="light"
|
||||
startContent={<StreamlineGoodHealthAndWellBeing size={'1.2em'} />}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { CopyIcon, DeleteIcon } from '@renderer/components/Icons'
|
||||
import { useChatContext } from '@renderer/hooks/useChatContext'
|
||||
import type { Topic } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Save, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -36,7 +35,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
<ActionBar>
|
||||
<SelectionCount>{t('common.selectedMessages', { count: selectedMessageIds.length })}</SelectionCount>
|
||||
<ActionButtons>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Tooltip content={t('common.save')}>
|
||||
<Button
|
||||
radius="full"
|
||||
variant="light"
|
||||
@@ -46,7 +45,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.copy')}>
|
||||
<Tooltip content={t('common.copy')}>
|
||||
<Button
|
||||
radius="full"
|
||||
variant="light"
|
||||
@@ -56,7 +55,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
isIconOnly
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.delete')}>
|
||||
<Tooltip content={t('common.delete')}>
|
||||
<Button
|
||||
radius="full"
|
||||
color="danger"
|
||||
@@ -67,7 +66,7 @@ const MultiSelectActionPopup: FC<Props> = ({ topic }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
</ActionButtons>
|
||||
<Tooltip title={t('chat.navigation.close')}>
|
||||
<Tooltip content={t('chat.navigation.close')}>
|
||||
<Button radius="full" variant="light" startContent={<X size={16} />} onPress={handleClose} isIconOnly />
|
||||
</Tooltip>
|
||||
</ActionBar>
|
||||
@@ -92,7 +91,7 @@ const ActionBar = styled.div`
|
||||
background-color: var(--color-background);
|
||||
padding: 4px 4px;
|
||||
border-radius: 99px;
|
||||
box-shadow: 0px 2px 8px 0px rgb(128 128 128 / 20%);
|
||||
box-shadow: 0 2px 8px 0 rgb(128 128 128 / 20%);
|
||||
border: 0.5px solid var(--color-border);
|
||||
gap: 16px;
|
||||
`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ColFlex, Flex } from '@cherrystudio/ui'
|
||||
import { ColFlex, Flex, HelpTooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
processMessageContent,
|
||||
processTopicContent
|
||||
} from '@renderer/utils/knowledge'
|
||||
import { Form, Modal, Select, Tooltip, Typography } from 'antd'
|
||||
import { Check, CircleHelp } from 'lucide-react'
|
||||
import { Form, Modal, Select, Typography } from 'antd'
|
||||
import { Check } from 'lucide-react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -375,9 +375,7 @@ const PopupContainer: React.FC<Props> = ({ source, title, resolve }) => {
|
||||
{option.count}
|
||||
</CustomTag>
|
||||
<span>{option.label}</span>
|
||||
<Tooltip title={option.description} mouseLeaveDelay={0}>
|
||||
<CircleHelp size={16} style={{ cursor: 'help' }} />
|
||||
</Tooltip>
|
||||
<HelpTooltip content={option.description} closeDelay={0} />
|
||||
</Flex>
|
||||
{selectedTypes.includes(option.type) && <Check size={16} color={TAG_COLORS.SELECTED} />}
|
||||
</ContentTypeItem>
|
||||
|
||||
+2
-1
@@ -16,7 +16,8 @@ exports[`TagFilterSection > rendering > should match snapshot 1`] = `
|
||||
class="c0"
|
||||
>
|
||||
<div
|
||||
class="box-border flex flex-wrap gap-1"
|
||||
class="flex-wrap gap-1"
|
||||
data-testid="flex"
|
||||
>
|
||||
<span
|
||||
class="c1"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PushpinOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Avatar } from '@cherrystudio/ui'
|
||||
import { FreeTrialModelTag } from '@renderer/components/FreeTrialModelTag'
|
||||
@@ -13,7 +14,7 @@ import type { Model, ModelType, Provider } from '@renderer/types'
|
||||
import { objectEntries } from '@renderer/types'
|
||||
import { classNames, filterModelsByKeywords, getFancyProviderName } from '@renderer/utils'
|
||||
import { getModelTags } from '@renderer/utils/model'
|
||||
import { Divider, Empty, Modal, Tooltip } from 'antd'
|
||||
import { Divider, Empty, Modal } from 'antd'
|
||||
import { first, sortBy } from 'lodash'
|
||||
import { Settings2 } from 'lucide-react'
|
||||
import React, {
|
||||
@@ -183,7 +184,7 @@ const PopupContainer: React.FC<Props> = ({ model, filter: baseFilter, showTagFil
|
||||
type: 'group',
|
||||
name: getFancyProviderName(p),
|
||||
actions: p.id !== 'cherryai' && (
|
||||
<Tooltip title={t('navigate.provider_settings')} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('navigate.provider_settings')} delay={500} closeDelay={0}>
|
||||
<Settings2
|
||||
size={12}
|
||||
color="var(--color-text)"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { memo } from 'react'
|
||||
|
||||
interface ImageToolButtonProps {
|
||||
@@ -10,7 +9,7 @@ interface ImageToolButtonProps {
|
||||
|
||||
const ImageToolButton = ({ tooltip, icon, onPress }: ImageToolButtonProps) => {
|
||||
return (
|
||||
<Tooltip title={tooltip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip content={tooltip} delay={500} closeDelay={0}>
|
||||
<Button radius="full" startContent={icon} onPress={onPress} isIconOnly aria-label={tooltip} />
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -3,14 +3,23 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import ImageToolButton from '../ImageToolButton'
|
||||
|
||||
// Mock antd components
|
||||
// Mock components
|
||||
vi.mock('antd', () => ({
|
||||
Button: vi.fn(({ children, onClick, ...props }) => (
|
||||
<button type="button" data-testid="custom-button" onClick={onClick} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
)),
|
||||
Tooltip: vi.fn(({ children, title }) => <div title={title}>{children}</div>)
|
||||
))
|
||||
}))
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Button: ({ children, onPress, disabled, isDisabled, startContent, ...props }: any) => (
|
||||
<button type="button" data-testid="button" onClick={onPress} disabled={disabled || isDisabled} {...props}>
|
||||
{startContent}
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
Tooltip: ({ children }: { children: React.ReactNode }) => <>{children}</>
|
||||
}))
|
||||
|
||||
describe('ImageToolButton', () => {
|
||||
|
||||
+10
-17
@@ -2,24 +2,17 @@
|
||||
|
||||
exports[`ImageToolButton > should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
title="Test tooltip"
|
||||
<button
|
||||
aria-label="Test tooltip"
|
||||
data-testid="button"
|
||||
radius="full"
|
||||
type="button"
|
||||
>
|
||||
<button
|
||||
aria-label="Test tooltip"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-small gap-2 rounded-full px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-10 w-10 h-10 data-[hover=true]:opacity-hover"
|
||||
data-react-aria-pressable="true"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
<span
|
||||
data-testid="test-icon"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
data-testid="test-icon"
|
||||
focusable="false"
|
||||
>
|
||||
Icon
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
Icon
|
||||
</span>
|
||||
</button>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { SearchOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ProviderAvatarPrimitive } from '@renderer/components/ProviderAvatar'
|
||||
import { PROVIDER_LOGO_MAP } from '@renderer/config/providers'
|
||||
import { getProviderLabel } from '@renderer/i18n/label'
|
||||
import { Input, Tooltip } from 'antd'
|
||||
import { Input } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@@ -51,9 +52,14 @@ const ProviderLogoPicker: FC<Props> = ({ onProviderClick }) => {
|
||||
</SearchContainer>
|
||||
<LogoGrid>
|
||||
{filteredProviders.map(({ id, name, logo }) => (
|
||||
<Tooltip key={id} title={name} placement="top" mouseLeaveDelay={0}>
|
||||
<Tooltip key={id} content={name} closeDelay={0}>
|
||||
<LogoItem onClick={(e) => handleProviderClick(e, id)}>
|
||||
<ProviderAvatarPrimitive providerId={id} style={{ width: '52px', height: '52px' }} providerName={name} logoSrc={logo} />
|
||||
<ProviderAvatarPrimitive
|
||||
providerId={id}
|
||||
style={{ width: '52px', height: '52px' }}
|
||||
providerName={name}
|
||||
logoSrc={logo}
|
||||
/>
|
||||
</LogoItem>
|
||||
</Tooltip>
|
||||
))}
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
import { CopyOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { DEFAULT_LANGUAGES, getHighlighter, getShiki } from '@renderer/utils/shiki'
|
||||
import { NodeViewContent, NodeViewWrapper, type ReactNodeViewProps, ReactNodeViewRenderer } from '@tiptap/react'
|
||||
import { Select, Tooltip } from 'antd'
|
||||
import { Select } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
@@ -66,7 +66,7 @@ const CodeBlockNodeView: FC<ReactNodeViewProps> = (props) => {
|
||||
options={languageOptions.map((lang) => ({ value: lang, label: lang }))}
|
||||
style={{ minWidth: 90 }}
|
||||
/>
|
||||
<Tooltip title="Copy">
|
||||
<Tooltip content="Copy">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="light"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { ContentSearch, type ContentSearchRef } from '@renderer/components/ContentSearch'
|
||||
import DragHandle from '@tiptap/extension-drag-handle-react'
|
||||
import { EditorContent } from '@tiptap/react'
|
||||
import { Tooltip } from 'antd'
|
||||
import { t } from 'i18next'
|
||||
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, GripVertical, Plus, Trash2 } from 'lucide-react'
|
||||
import React, { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
||||
@@ -402,12 +402,12 @@ const RichEditor = ({
|
||||
<Scrollbar ref={scrollContainerRef} style={{ flex: 1, display: 'flex' }}>
|
||||
<StyledEditorContent>
|
||||
<PlusButton editor={editor} onElementClick={handlePlusButtonClick}>
|
||||
<Tooltip title={t('richEditor.plusButton')}>
|
||||
<Tooltip content={t('richEditor.plusButton')}>
|
||||
<Plus />
|
||||
</Tooltip>
|
||||
</PlusButton>
|
||||
<DragHandle editor={editor} onElementDragEnd={handleDragEnd}>
|
||||
<Tooltip title={t('richEditor.dragHandle')}>
|
||||
<Tooltip content={t('richEditor.dragHandle')}>
|
||||
<GripVertical />
|
||||
</Tooltip>
|
||||
</DragHandle>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { TFunction } from 'i18next'
|
||||
import type { LucideProps } from 'lucide-react'
|
||||
import type { ForwardRefExoticComponent, RefAttributes } from 'react'
|
||||
@@ -177,7 +177,7 @@ export const Toolbar: React.FC<ToolbarProps> = ({ editor, formattingState, onCom
|
||||
)
|
||||
|
||||
return (
|
||||
<Tooltip key={item.id} title={tooltipText} placement="top">
|
||||
<Tooltip key={item.id} content={tooltipText}>
|
||||
{buttonElement}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { restoreFromS3 } from '@renderer/services/BackupService'
|
||||
import type { S3Config } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -207,7 +207,7 @@ export function S3BackupManager({ visible, onClose, s3Config, restoreMethod }: S
|
||||
showTitle: false
|
||||
},
|
||||
render: (fileName: string) => (
|
||||
<Tooltip placement="topLeft" title={fileName}>
|
||||
<Tooltip placement="top-start" content={fileName}>
|
||||
{fileName}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PlusOutlined } from '@ant-design/icons'
|
||||
import { Sortable, useDndReorder } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import HorizontalScrollContainer from '@renderer/components/HorizontalScrollContainer'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
@@ -16,7 +17,6 @@ import { addTab, removeTab, setActiveTab, setTabs } from '@renderer/store/tabs'
|
||||
import type { MinAppType } from '@renderer/types'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Tooltip } from 'antd'
|
||||
import type { LRUCache } from 'lru-cache'
|
||||
import {
|
||||
FileSearch,
|
||||
@@ -263,9 +263,9 @@ const TabsContainer: React.FC<TabsContainerProps> = ({ children }) => {
|
||||
</HorizontalScrollContainer>
|
||||
<RightButtonsContainer>
|
||||
<Tooltip
|
||||
title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
placement="bottom"
|
||||
content={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
delay={800}>
|
||||
<ThemeButton onClick={toggleTheme}>
|
||||
{settedTheme === ThemeMode.dark ? (
|
||||
<Moon size={16} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CloseOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { CSSProperties, FC, MouseEventHandler } from 'react'
|
||||
import { memo, useMemo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
@@ -61,7 +61,7 @@ const CustomTag: FC<CustomTagProps> = ({
|
||||
)
|
||||
|
||||
return tooltip ? (
|
||||
<Tooltip title={tooltip} placement="top" mouseEnterDelay={0.3}>
|
||||
<Tooltip content={tooltip} delay={300}>
|
||||
{tagContent}
|
||||
</Tooltip>
|
||||
) : (
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { TooltipProps } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { HelpCircle } from 'lucide-react'
|
||||
|
||||
type InheritedTooltipProps = Omit<TooltipProps, 'children'>
|
||||
|
||||
interface HelpTooltipProps extends InheritedTooltipProps {
|
||||
iconColor?: string
|
||||
iconSize?: string | number
|
||||
iconStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
const HelpTooltip = ({ iconColor = 'var(--color-text-2)', iconSize = 14, iconStyle, ...rest }: HelpTooltipProps) => {
|
||||
return (
|
||||
<Tooltip {...rest}>
|
||||
<HelpCircle
|
||||
size={iconSize}
|
||||
color={iconColor}
|
||||
style={{ ...iconStyle, cursor: 'help' }}
|
||||
role="img"
|
||||
aria-label="Help"
|
||||
className="relative z-10"
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default HelpTooltip
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { TooltipProps } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Info } from 'lucide-react'
|
||||
|
||||
type InheritedTooltipProps = Omit<TooltipProps, 'children'>
|
||||
|
||||
interface InfoTooltipProps extends InheritedTooltipProps {
|
||||
iconColor?: string
|
||||
iconSize?: string | number
|
||||
iconStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
const InfoTooltip = ({ iconColor = 'var(--color-text-2)', iconSize = 14, iconStyle, ...rest }: InfoTooltipProps) => {
|
||||
return (
|
||||
<Tooltip {...rest}>
|
||||
<Info size={iconSize} color={iconColor} style={{ ...iconStyle }} role="img" aria-label="Information" />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default InfoTooltip
|
||||
@@ -1,26 +0,0 @@
|
||||
import type { TooltipProps } from 'antd'
|
||||
import { Tooltip } from 'antd'
|
||||
import { AlertTriangle } from 'lucide-react'
|
||||
|
||||
type InheritedTooltipProps = Omit<TooltipProps, 'children'>
|
||||
|
||||
interface WarnTooltipProps extends InheritedTooltipProps {
|
||||
iconColor?: string
|
||||
iconSize?: string | number
|
||||
iconStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
const WarnTooltip = ({
|
||||
iconColor = 'var(--color-status-warning)',
|
||||
iconSize = 14,
|
||||
iconStyle,
|
||||
...rest
|
||||
}: WarnTooltipProps) => {
|
||||
return (
|
||||
<Tooltip {...rest}>
|
||||
<AlertTriangle size={iconSize} color={iconColor} style={{ ...iconStyle }} role="img" aria-label="Information" />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default WarnTooltip
|
||||
@@ -1,38 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import InfoTooltip from '../InfoTooltip'
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: ({ children, title }: { children: React.ReactNode; title: string }) => (
|
||||
<div>
|
||||
{children}
|
||||
{title && <div>{title}</div>}
|
||||
</div>
|
||||
)
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
Info: ({ ref, ...props }) => (
|
||||
<div {...props} ref={ref} role="img" aria-label="Information">
|
||||
Info
|
||||
</div>
|
||||
)
|
||||
}))
|
||||
|
||||
describe('InfoTooltip', () => {
|
||||
it('should match snapshot', () => {
|
||||
const { container } = render(
|
||||
<InfoTooltip title="Test tooltip" placement="top" iconColor="#1890ff" iconStyle={{ fontSize: '16px' }} />
|
||||
)
|
||||
expect(container.firstChild).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should pass title prop to the underlying Tooltip component', () => {
|
||||
const tooltipText = 'This is helpful information'
|
||||
render(<InfoTooltip title={tooltipText} />)
|
||||
|
||||
expect(screen.getByRole('img', { name: 'Information' })).toBeInTheDocument()
|
||||
expect(screen.getByText(tooltipText)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`InfoTooltip > should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
aria-label="Information"
|
||||
color="#1890ff"
|
||||
role="img"
|
||||
size="14"
|
||||
style="font-size: 16px;"
|
||||
>
|
||||
Info
|
||||
</div>
|
||||
<div>
|
||||
Test tooltip
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as HelpTooltip } from './HelpTooltip'
|
||||
export { default as InfoTooltip } from './InfoTooltip'
|
||||
export { default as WarnTooltip } from './WarnTooltip'
|
||||
@@ -1,10 +1,9 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import useTranslate from '@renderer/hooks/useTranslate'
|
||||
import { translateText } from '@renderer/services/TranslateService'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Languages } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -66,10 +65,8 @@ const TranslateButton: FC<Props> = ({ text, onTranslated, disabled, style, isLoa
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.translate', { target_language: getLanguageByLangcode(targetLanguage).label() })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
content={t('chat.input.translate', { target_language: getLanguageByLangcode(targetLanguage).label() })}
|
||||
closeDelay={0}>
|
||||
<Button
|
||||
onPress={handleTranslate}
|
||||
isDisabled={disabled || isTranslating}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DeleteOutlined, ExclamationCircleOutlined, ReloadOutlined } from '@ant-design/icons'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { restoreFromWebdav } from '@renderer/services/BackupService'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Modal, Table, Tooltip } from 'antd'
|
||||
import { Modal, Table } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -214,7 +214,7 @@ export function WebdavBackupManager({
|
||||
showTitle: false
|
||||
},
|
||||
render: (fileName: string) => (
|
||||
<Tooltip placement="topLeft" title={fileName}>
|
||||
<Tooltip placement="top-start" content={fileName}>
|
||||
{fileName}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { isLinux, isWin } from '@renderer/config/constant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Minus, Square, X } from 'lucide-react'
|
||||
import type { SVGProps } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -11,6 +11,8 @@ interface WindowRestoreIconProps extends SVGProps<SVGSVGElement> {
|
||||
size?: string | number
|
||||
}
|
||||
|
||||
const DEFAULT_DELAY = 1000
|
||||
|
||||
export const WindowRestoreIcon = ({ size = '1.1em', ...props }: WindowRestoreIconProps) => (
|
||||
<svg
|
||||
width={size}
|
||||
@@ -44,8 +46,6 @@ export const WindowRestoreIcon = ({ size = '1.1em', ...props }: WindowRestoreIco
|
||||
</svg>
|
||||
)
|
||||
|
||||
const DEFAULT_DELAY = 1
|
||||
|
||||
const WindowControls: React.FC = () => {
|
||||
const [isMaximized, setIsMaximized] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
@@ -85,20 +85,20 @@ const WindowControls: React.FC = () => {
|
||||
|
||||
return (
|
||||
<WindowControlsContainer>
|
||||
<Tooltip title={t('navbar.window.minimize')} placement="bottom" mouseEnterDelay={DEFAULT_DELAY}>
|
||||
<Tooltip placement="bottom" content={t('navbar.window.minimize')} delay={DEFAULT_DELAY}>
|
||||
<ControlButton onClick={handleMinimize} aria-label="Minimize">
|
||||
<Minus size={14} />
|
||||
</ControlButton>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={isMaximized ? t('navbar.window.restore') : t('navbar.window.maximize')}
|
||||
placement="bottom"
|
||||
mouseEnterDelay={DEFAULT_DELAY}>
|
||||
content={isMaximized ? t('navbar.window.restore') : t('navbar.window.maximize')}
|
||||
delay={DEFAULT_DELAY}>
|
||||
<ControlButton onClick={handleMaximize} aria-label={isMaximized ? 'Restore' : 'Maximize'}>
|
||||
{isMaximized ? <WindowRestoreIcon size={14} /> : <Square size={14} />}
|
||||
</ControlButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('navbar.window.close')} placement="bottom" mouseEnterDelay={DEFAULT_DELAY}>
|
||||
<Tooltip placement="bottom" content={t('navbar.window.close')} delay={DEFAULT_DELAY}>
|
||||
<ControlButton $isClose onClick={handleClose} aria-label="Close">
|
||||
<X size={17} />
|
||||
</ControlButton>
|
||||
|
||||
@@ -28,18 +28,16 @@ describe('CustomTag', () => {
|
||||
reasoning
|
||||
</CustomTag>
|
||||
)
|
||||
// 鼠标悬停触发 Tooltip
|
||||
// 鼠标悬停触发 Tooltip(mock 直接渲染 tooltip 内容)
|
||||
await userEvent.hover(screen.getByText('reasoning'))
|
||||
expect(await screen.findByText('reasoning model')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('tooltip-content')).toHaveTextContent('reasoning model')
|
||||
})
|
||||
|
||||
it('should not render Tooltip when tooltip is not set', () => {
|
||||
render(<CustomTag color="#ff0000">no tooltip</CustomTag>)
|
||||
|
||||
expect(screen.getByText('no tooltip')).toBeInTheDocument()
|
||||
// 不应有 tooltip 相关内容
|
||||
expect(document.querySelector('.ant-tooltip')).toBeNull()
|
||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument()
|
||||
expect(screen.queryByTestId('tooltip-content')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not allow click when disabled', async () => {
|
||||
|
||||
@@ -54,19 +54,26 @@ vi.mock('antd', () => {
|
||||
</button>
|
||||
)
|
||||
|
||||
const MockTooltip: React.FC<React.PropsWithChildren<{ title: string }>> = ({ children, title }) => (
|
||||
return {
|
||||
Button: MockButton,
|
||||
InputNumber: MockInputNumber,
|
||||
Space: { Compact: MockSpaceCompact }
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Button: ({ children, onPress, disabled, isDisabled, startContent, ...props }: any) => (
|
||||
<button type="button" data-testid="button" onClick={onPress} disabled={disabled || isDisabled} {...props}>
|
||||
{startContent}
|
||||
{children}
|
||||
</button>
|
||||
),
|
||||
Tooltip: ({ children, title }: { children: React.ReactNode; title: React.ReactNode }) => (
|
||||
<div data-testid="tooltip" data-title={title}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
return {
|
||||
Button: MockButton,
|
||||
InputNumber: MockInputNumber,
|
||||
Space: { Compact: MockSpaceCompact },
|
||||
Tooltip: MockTooltip
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock('@renderer/aiCore', () => ({
|
||||
|
||||
+2
-16
@@ -14,22 +14,17 @@ exports[`InputEmbeddingDimension > basic rendering > should match snapshot with
|
||||
/>
|
||||
<div
|
||||
data-testid="tooltip"
|
||||
data-title="自动设置维度"
|
||||
>
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-tiny gap-2 rounded-small px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-8 w-8 h-8 data-[hover=true]:opacity-hover"
|
||||
data-react-aria-pressable="true"
|
||||
data-testid="button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="refresh"
|
||||
class=""
|
||||
data-testid="refresh-icon"
|
||||
focusable="false"
|
||||
role="img"
|
||||
size="16"
|
||||
>
|
||||
@@ -54,32 +49,23 @@ exports[`InputEmbeddingDimension > basic rendering > should match snapshot with
|
||||
/>
|
||||
<div
|
||||
data-testid="tooltip"
|
||||
data-title="自动设置维度"
|
||||
>
|
||||
<button
|
||||
aria-label="Get embedding dimension"
|
||||
class="z-0 group relative inline-flex items-center justify-center box-border appearance-none select-none whitespace-nowrap font-normal subpixel-antialiased overflow-hidden tap-highlight-transparent transform-gpu data-[pressed=true]:scale-[0.97] cursor-pointer outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-tiny gap-2 rounded-small opacity-disabled pointer-events-none px-0 !gap-0 transition-transform-colors-opacity motion-reduce:transition-none bg-default text-default-foreground min-w-8 w-8 h-8 data-[hover=true]:opacity-hover"
|
||||
data-disabled="true"
|
||||
data-react-aria-pressable="true"
|
||||
data-testid="button"
|
||||
disabled=""
|
||||
role="button"
|
||||
type="button"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-label="refresh"
|
||||
class="animation-rotate"
|
||||
data-testid="refresh-icon"
|
||||
focusable="false"
|
||||
role="img"
|
||||
size="16"
|
||||
>
|
||||
RefreshIcon
|
||||
</svg>
|
||||
<span
|
||||
class="heroui-ripple"
|
||||
style="position: absolute; background-color: currentColor; border-radius: 100%; transform-origin: center; pointer-events: none; overflow: hidden; inset: 0; z-index: 0; top: 0px; left: 0px; width: 0px; height: 0px; transform: scale(0); opacity: 0.35;"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
@@ -5,7 +6,7 @@ import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
|
||||
import type { MinAppType } from '@renderer/types'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import { Dropdown } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -86,16 +87,18 @@ export const SidebarOpenedMinappTabs: FC = () => {
|
||||
const isActive = minappShow && currentMinappId === app.id
|
||||
|
||||
return (
|
||||
<Tooltip key={app.id} title={app.name} mouseEnterDelay={0.8} placement="right">
|
||||
<Dropdown menu={{ items: menuItems }} trigger={['contextMenu']} overlayStyle={{ zIndex: 10000 }}>
|
||||
<Icon
|
||||
theme={theme}
|
||||
onClick={() => handleOnClick(app)}
|
||||
className={`${isActive ? 'opened-active' : ''}`}>
|
||||
<MinAppIcon size={20} app={app} style={{ borderRadius: 6 }} sidebar />
|
||||
</Icon>
|
||||
</Dropdown>
|
||||
</Tooltip>
|
||||
<Dropdown
|
||||
key={app.id}
|
||||
menu={{ items: menuItems }}
|
||||
trigger={['contextMenu']}
|
||||
overlayStyle={{ zIndex: 10000 }}>
|
||||
{/* FIXME: Antd Dropdown is not compatible with HeroUI Tooltip */}
|
||||
{/* <Tooltip content={app.name} placement="right" delay={800}> */}
|
||||
<Icon theme={theme} onClick={() => handleOnClick(app)} className={`${isActive ? 'opened-active' : ''}`}>
|
||||
<MinAppIcon size={20} app={app} style={{ borderRadius: 6 }} sidebar />
|
||||
</Icon>
|
||||
{/* </Tooltip> */}
|
||||
</Dropdown>
|
||||
)
|
||||
})}
|
||||
</Menus>
|
||||
@@ -126,7 +129,7 @@ export const SidebarPinnedApps: FC = () => {
|
||||
]
|
||||
const isActive = minappShow && currentMinappId === app.id
|
||||
return (
|
||||
<Tooltip key={app.id} title={app.name} mouseEnterDelay={0.8} placement="right">
|
||||
<Tooltip key={app.id} content={app.name} placement="right" delay={800}>
|
||||
<Dropdown menu={{ items: menuItems }} trigger={['contextMenu']} overlayStyle={{ zIndex: 10000 }}>
|
||||
<Icon
|
||||
theme={theme}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||
import { Avatar, EmojiAvatar, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { isMac } from '@renderer/config/constant'
|
||||
import { UserAvatar } from '@renderer/config/env'
|
||||
@@ -13,7 +13,6 @@ import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { getSidebarIconLabel, getThemeModeLabel } from '@renderer/i18n/label'
|
||||
import { isEmoji } from '@renderer/utils'
|
||||
import { ThemeMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Tooltip } from 'antd'
|
||||
import {
|
||||
Code,
|
||||
FileSearch,
|
||||
@@ -90,9 +89,9 @@ const Sidebar: FC = () => {
|
||||
</MainMenusContainer>
|
||||
<Menus>
|
||||
<Tooltip
|
||||
title={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="right">
|
||||
placement="right"
|
||||
content={t('settings.theme.title') + ': ' + getThemeModeLabel(settedTheme)}
|
||||
delay={800}>
|
||||
<Icon theme={theme} onClick={toggleTheme}>
|
||||
{settedTheme === ThemeMode.dark ? (
|
||||
<Moon size={20} className="icon" />
|
||||
@@ -103,7 +102,7 @@ const Sidebar: FC = () => {
|
||||
)}
|
||||
</Icon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('settings.title')} mouseEnterDelay={0.8} placement="right">
|
||||
<Tooltip placement="right" content={t('settings.title')} delay={800}>
|
||||
<StyledLink
|
||||
onClick={async () => {
|
||||
hideMinappPopup()
|
||||
@@ -161,7 +160,7 @@ const MainMenus: FC = () => {
|
||||
const isActive = path === '/' ? isRoute(path) : isRoutes(path)
|
||||
|
||||
return (
|
||||
<Tooltip key={icon} title={getSidebarIconLabel(icon)} mouseEnterDelay={0.8} placement="right">
|
||||
<Tooltip key={icon} placement="right" content={getSidebarIconLabel(icon)} delay={800}>
|
||||
<StyledLink
|
||||
onClick={async () => {
|
||||
hideMinappPopup()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Avatar } from '@cherrystudio/ui'
|
||||
import { Avatar, Button, Tooltip } from '@cherrystudio/ui'
|
||||
import AiProvider from '@renderer/aiCore'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import ModelSelector from '@renderer/components/ModelSelector'
|
||||
@@ -18,7 +17,7 @@ import { setIsBunInstalled } from '@renderer/store/mcp'
|
||||
import type { EndpointType, Model } from '@renderer/types'
|
||||
import type { TerminalConfig } from '@shared/config/constant'
|
||||
import { codeTools, terminalApps } from '@shared/config/constant'
|
||||
import { Alert, Checkbox, Input, Popover, Select, Space, Tooltip } from 'antd'
|
||||
import { Alert, Checkbox, Input, Popover, Select, Space } from 'antd'
|
||||
import { ArrowUpRight, Download, FolderOpen, HelpCircle, Terminal, X } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
@@ -458,7 +457,7 @@ const CodeToolsPage: FC = () => {
|
||||
selectedTerminal !== terminalApps.cmd &&
|
||||
selectedTerminal !== terminalApps.powershell &&
|
||||
selectedTerminal !== terminalApps.windowsTerminal && (
|
||||
<Tooltip title={terminalCustomPaths[selectedTerminal] || t('code.set_custom_path')}>
|
||||
<Tooltip content={terminalCustomPaths[selectedTerminal] || t('code.set_custom_path')}>
|
||||
<Button
|
||||
startContent={<FolderOpen size={16} />}
|
||||
isIconOnly
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { NavbarHeader } from '@renderer/components/app/Navbar'
|
||||
import SearchPopup from '@renderer/components/Popups/SearchPopup'
|
||||
@@ -8,7 +9,6 @@ import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import type { 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'
|
||||
@@ -68,14 +68,14 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
<NavbarHeader className="home-navbar">
|
||||
<RowFlex className="items-center">
|
||||
{showAssistants && (
|
||||
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('navbar.hide_sidebar')} delay={800}>
|
||||
<NavbarIcon onClick={toggleShowAssistants}>
|
||||
<PanelLeftClose size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!showAssistants && (
|
||||
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('navbar.show_sidebar')} delay={800}>
|
||||
<NavbarIcon onClick={() => toggleShowAssistants()} style={{ marginRight: 8 }}>
|
||||
<PanelRightClose size={18} />
|
||||
</NavbarIcon>
|
||||
@@ -98,25 +98,25 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
</RowFlex>
|
||||
<RowFlex className="items-center gap-2">
|
||||
<UpdateAppButton />
|
||||
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('navbar.expand')} delay={800}>
|
||||
<NarrowIcon onClick={handleNarrowModeToggle}>
|
||||
<i className="iconfont icon-icon-adaptive-width"></i>
|
||||
</NarrowIcon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('chat.assistant.search.placeholder')} delay={800}>
|
||||
<NavbarIcon onClick={() => SearchPopup.show()}>
|
||||
<Search size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
{topicPosition === 'right' && !showTopics && (
|
||||
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={2}>
|
||||
<Tooltip placement="bottom" content={t('navbar.show_sidebar')} delay={2000}>
|
||||
<NavbarIcon onClick={toggleShowTopics}>
|
||||
<PanelLeftClose size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
{topicPosition === 'right' && showTopics && (
|
||||
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={2}>
|
||||
<Tooltip placement="bottom" content={t('navbar.hide_sidebar')} delay={2000}>
|
||||
<NavbarIcon onClick={toggleShowTopics}>
|
||||
<PanelRightClose size={18} />
|
||||
</NavbarIcon>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { useKnowledgeBases } from '@renderer/hooks/useKnowledge'
|
||||
import type { FileType, KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { filterSupportedFiles, formatFileSize } from '@renderer/utils/file'
|
||||
import { Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { FileSearch, FileText, Paperclip, Upload } from 'lucide-react'
|
||||
import type { Dispatch, FC, SetStateAction } from 'react'
|
||||
@@ -144,10 +144,8 @@ const AttachmentButton: FC<Props> = ({ ref, couldAddImageFile, extensions, files
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={couldAddImageFile ? t('chat.input.upload.image_or_document') : t('chat.input.upload.document')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
content={couldAddImageFile ? t('chat.input.upload.image_or_document') : t('chat.input.upload.document')}
|
||||
closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={openFileSelectDialog}
|
||||
active={files.length > 0}
|
||||
|
||||
@@ -13,12 +13,13 @@ import {
|
||||
LinkOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { ColFlex } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { useAttachment } from '@renderer/hooks/useAttachment'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import type { FileMetadata } from '@renderer/types'
|
||||
import { formatFileSize } from '@renderer/utils'
|
||||
import { Image, Tooltip } from 'antd'
|
||||
import { Image } from 'antd'
|
||||
import { isEmpty } from 'lodash'
|
||||
import type { FC } from 'react'
|
||||
import { useState } from 'react'
|
||||
@@ -95,13 +96,10 @@ export const FileNameRender: FC<{ file: FileMetadata }> = ({ file }) => {
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
styles={{
|
||||
body: {
|
||||
padding: 5
|
||||
}
|
||||
classNames={{
|
||||
content: 'p-1'
|
||||
}}
|
||||
fresh
|
||||
title={
|
||||
content={
|
||||
<ColFlex className="items-center gap-0.5">
|
||||
{isImage(file.ext) && (
|
||||
<Image
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { isGenerateImageModel } from '@renderer/config/models'
|
||||
import type { Assistant, Model } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Image } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -17,12 +17,9 @@ const GenerateImageButton: FC<Props> = ({ model, assistant, onEnableGenerateImag
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={
|
||||
content={
|
||||
isGenerateImageModel(model) ? t('chat.input.generate_image') : t('chat.input.generate_image_not_supported')
|
||||
}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
}>
|
||||
<ActionIconButton
|
||||
onPress={onEnableGenerateImage}
|
||||
active={assistant.enableGenerateImage}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { HolderOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -45,7 +46,6 @@ import {
|
||||
} from '@renderer/utils/input'
|
||||
import { documentExts, imageExts, textExts } from '@shared/config/constant'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Tooltip } from 'antd'
|
||||
import type { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { debounce, isEmpty } from 'lodash'
|
||||
@@ -911,7 +911,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
|
||||
<TranslateButton text={text} onTranslated={onTranslated} isLoading={isTranslating} />
|
||||
<SendMessageButton sendMessage={sendMessage} disabled={inputEmpty} />
|
||||
{loading && (
|
||||
<Tooltip placement="top" title={t('chat.input.pause')} mouseLeaveDelay={0} arrow>
|
||||
<Tooltip content={t('chat.input.pause')} closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onClick={onPause}
|
||||
className="mr-[-2px]"
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { DropResult } from '@hello-pangea/dnd'
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -23,7 +24,7 @@ import type { FileType, KnowledgeBase, Model } from '@renderer/types'
|
||||
import { FileTypes } from '@renderer/types'
|
||||
import { classNames } from '@renderer/utils'
|
||||
import { isPromptToolUse, isSupportedToolUse } from '@renderer/utils/mcp-tools'
|
||||
import { Divider, Dropdown, Tooltip } from 'antd'
|
||||
import { Divider, Dropdown } from 'antd'
|
||||
import type { ItemType } from 'antd/es/menu/interface'
|
||||
import {
|
||||
AtSign,
|
||||
@@ -354,11 +355,7 @@ const InputbarTools = ({
|
||||
key: 'new_topic',
|
||||
label: t('chat.input.new_topic', { Command: '' }),
|
||||
component: (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.new_topic', { Command: newTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<Tooltip content={t('chat.input.new_topic', { Command: newTopicShortcut })} closeDelay={0}>
|
||||
<ActionIconButton onPress={addNewTopic} icon={<MessageSquareDiff size={19} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
@@ -459,11 +456,7 @@ const InputbarTools = ({
|
||||
key: 'clear_topic',
|
||||
label: t('chat.input.clear.label', { Command: '' }),
|
||||
component: (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.clear.label', { Command: clearTopicShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<Tooltip content={t('chat.input.clear.label', { Command: clearTopicShortcut })} closeDelay={0} showArrow>
|
||||
<ActionIconButton onPress={clearTopic} icon={<PaintbrushVertical size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
@@ -472,11 +465,7 @@ const InputbarTools = ({
|
||||
key: 'toggle_expand',
|
||||
label: isExpended ? t('chat.input.collapse') : t('chat.input.expand'),
|
||||
component: (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={isExpended ? t('chat.input.collapse') : t('chat.input.expand')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<Tooltip content={isExpended ? t('chat.input.collapse') : t('chat.input.expand')} closeDelay={0} showArrow>
|
||||
<ActionIconButton
|
||||
onPress={onToggleExpended}
|
||||
icon={isExpended ? <Minimize size={18} /> : <Maximize size={18} />}
|
||||
@@ -655,10 +644,7 @@ const InputbarTools = ({
|
||||
</DragDropContext>
|
||||
|
||||
{showCollapseButton && (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={isCollapse ? t('chat.input.tools.expand') : t('chat.input.tools.collapse')}
|
||||
arrow>
|
||||
<Tooltip content={isCollapse ? t('chat.input.tools.expand') : t('chat.input.tools.collapse')} showArrow>
|
||||
<ActionIconButton
|
||||
onPress={() => dispatch(setIsCollapsed(!isCollapse))}
|
||||
icon={
|
||||
@@ -715,9 +701,10 @@ const ToolWrapper = styled.div`
|
||||
width 0.2s,
|
||||
margin-right 0.2s,
|
||||
opacity 0.2s;
|
||||
|
||||
&.is-collapsed {
|
||||
width: 0px;
|
||||
margin-right: 0px;
|
||||
width: 0;
|
||||
margin-right: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import type { QuickPanelListItem } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
import { useAppSelector } from '@renderer/store'
|
||||
import type { KnowledgeBase } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { CircleX, FileSearch, Plus } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react'
|
||||
@@ -108,7 +108,7 @@ const KnowledgeBaseButton: FC<Props> = ({ ref, selectedBases, onSelect, disabled
|
||||
}))
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.knowledge_base')} mouseLeaveDelay={0} arrow>
|
||||
<Tooltip content={t('chat.input.knowledge_base')} closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={selectedBases && selectedBases.length > 0}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import type { QuickPanelListItem } from '@renderer/components/QuickPanel'
|
||||
import { QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
@@ -10,7 +11,7 @@ import { getProviderByModel } from '@renderer/services/AssistantService'
|
||||
import { EventEmitter } from '@renderer/services/EventService'
|
||||
import type { MCPPrompt, MCPResource, MCPServer } from '@renderer/types'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Form, Input, Tooltip } from 'antd'
|
||||
import { Form, Input } from 'antd'
|
||||
import { CircleX, Hammer, Plus } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||
@@ -487,7 +488,7 @@ const MCPToolsButton: FC<Props> = ({ ref, setInputValue, resizeTextArea, assista
|
||||
}))
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('settings.mcp.title')} mouseLeaveDelay={0} arrow>
|
||||
<Tooltip content={t('settings.mcp.title')} closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={assistant.mcpServers && assistant.mcpServers.length > 0}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Avatar } from '@cherrystudio/ui'
|
||||
import { Avatar, Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import ModelTagsWithLabel from '@renderer/components/ModelTagsWithLabel'
|
||||
import { type QuickPanelListItem, QuickPanelReservedSymbol, useQuickPanel } from '@renderer/components/QuickPanel'
|
||||
@@ -8,7 +8,6 @@ import { useProviders } from '@renderer/hooks/useProvider'
|
||||
import { getModelUniqId } from '@renderer/services/ModelService'
|
||||
import type { FileType, Model } from '@renderer/types'
|
||||
import { getFancyProviderName } from '@renderer/utils'
|
||||
import { Tooltip } from 'antd'
|
||||
import { useLiveQuery } from 'dexie-react-hooks'
|
||||
import { first, sortBy } from 'lodash'
|
||||
import { AtSign, CircleX, Plus } from 'lucide-react'
|
||||
@@ -136,7 +135,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
),
|
||||
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
||||
icon: (
|
||||
<Avatar src={getModelLogo(m.id)} className="w-5 h-5">
|
||||
<Avatar src={getModelLogo(m.id)} className="h-5 w-5">
|
||||
{first(m.name)}
|
||||
</Avatar>
|
||||
),
|
||||
@@ -172,7 +171,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
),
|
||||
description: <ModelTagsWithLabel model={m} showLabel={false} size={10} style={{ opacity: 0.8 }} />,
|
||||
icon: (
|
||||
<Avatar src={getModelLogo(m.id)} className="w-5 h-5">
|
||||
<Avatar src={getModelLogo(m.id)} className="h-5 w-5">
|
||||
{first(m.name)}
|
||||
</Avatar>
|
||||
),
|
||||
@@ -304,7 +303,7 @@ const MentionModelsButton: FC<Props> = ({
|
||||
}))
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('agents.edit.model.select.title')} mouseLeaveDelay={0} arrow>
|
||||
<Tooltip content={t('agents.edit.model.select.title')} closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={mentionedModels.length > 0}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Eraser } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -15,11 +15,7 @@ const NewContextButton: FC<Props> = ({ onNewContext }) => {
|
||||
useShortcut('toggle_new_context', onNewContext)
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={t('chat.input.new.context', { Command: newContextShortcut })}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<Tooltip content={t('chat.input.new.context', { Command: newContextShortcut })} closeDelay={0}>
|
||||
<ActionIconButton onPress={onNewContext} icon={<Eraser size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import {
|
||||
type QuickPanelListItem,
|
||||
@@ -9,7 +10,7 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import QuickPhraseService from '@renderer/services/QuickPhraseService'
|
||||
import type { QuickPhrase } from '@renderer/types'
|
||||
import { Input, Modal, Radio, Space, Tooltip } from 'antd'
|
||||
import { Input, Modal, Radio, Space } from 'antd'
|
||||
import { BotMessageSquare, Plus, Zap } from 'lucide-react'
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -156,7 +157,7 @@ const QuickPhrasesButton = ({ ref, setInputValue, resizeTextArea, assistantId }:
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip placement="top" title={t('settings.quickPhrase.title')} mouseLeaveDelay={0} arrow>
|
||||
<Tooltip content={t('settings.quickPhrase.title')} closeDelay={0}>
|
||||
<ActionIconButton onPress={handleOpenQuickPanel} icon={<Zap size={18} />} />
|
||||
</Tooltip>
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import {
|
||||
MdiLightbulbAutoOutline,
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { getReasoningEffortOptionsLabel } from '@renderer/i18n/label'
|
||||
import type { Model, ThinkingOption } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import type { FC, ReactElement } from 'react'
|
||||
import { useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -132,14 +132,12 @@ const ThinkingButton: FC<Props> = ({ ref, model, assistantId }): ReactElement =>
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={
|
||||
content={
|
||||
isThinkingEnabled && supportedOptions.includes('off')
|
||||
? t('common.close')
|
||||
: t('assistants.settings.reasoning_effort.label')
|
||||
}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={handleOpenQuickPanel}
|
||||
active={currentReasoningEffort !== 'off'}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useTimer } from '@renderer/hooks/useTimer'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Link } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback } from 'react'
|
||||
@@ -47,7 +47,7 @@ const UrlContextButton: FC<Props> = ({ assistantId }) => {
|
||||
}, [setTimeoutTimer, assistant, urlContentNewState, updateAssistant, t])
|
||||
|
||||
return (
|
||||
<Tooltip placement="top" title={t('chat.input.url_context')} arrow>
|
||||
<Tooltip content={t('chat.input.url_context')}>
|
||||
<ActionIconButton onPress={handleToggle} active={assistant.enableUrlContext} icon={<Link size={18} />} />
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BaiduOutlined, GoogleOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
import { BingLogo, BochaLogo, ExaLogo, SearXNGLogo, TavilyLogo, ZhipuLogo } from '@renderer/components/Icons'
|
||||
@@ -19,7 +20,6 @@ import WebSearchService from '@renderer/services/WebSearchService'
|
||||
import type { WebSearchProvider, WebSearchProviderId } from '@renderer/types'
|
||||
import { hasObjectKey } from '@renderer/utils'
|
||||
import { isToolUseModeFunction } from '@renderer/utils/assistant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Globe } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback, useImperativeHandle, useMemo } from 'react'
|
||||
@@ -207,11 +207,7 @@ const WebSearchButton: FC<Props> = ({ ref, assistantId }) => {
|
||||
}))
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={enableWebSearch ? t('common.close') : t('chat.input.web_search.label')}
|
||||
mouseLeaveDelay={0}
|
||||
arrow>
|
||||
<Tooltip content={enableWebSearch ? t('common.close') : t('chat.input.web_search.label')} closeDelay={0}>
|
||||
<ActionIconButton
|
||||
onPress={onClick}
|
||||
active={!!enableWebSearch}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import Favicon from '@renderer/components/Icons/FallbackFavicon'
|
||||
import { Tooltip } from 'antd'
|
||||
import React, { memo, useCallback, useMemo } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { z } from 'zod'
|
||||
@@ -57,17 +57,9 @@ const CitationTooltip: React.FC<CitationTooltipProps> = ({ children, citation })
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
arrow={false}
|
||||
overlay={tooltipContent}
|
||||
placement="top"
|
||||
color="var(--color-background)"
|
||||
styles={{
|
||||
body: {
|
||||
border: '1px solid var(--color-border)',
|
||||
padding: '12px',
|
||||
borderRadius: '8px'
|
||||
}
|
||||
}}>
|
||||
content={tooltipContent}
|
||||
showArrow={false}
|
||||
className="rounded-[8px] border border-[var(--color-border)] bg-[var(--color-background)] p-3">
|
||||
{children}
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -26,7 +26,6 @@ const Hyperlink: React.FC<HyperLinkProps> = ({ children, href }) => {
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
content={<OGCard link={link} show={open} />}
|
||||
placement="top"
|
||||
styles={{
|
||||
body: {
|
||||
padding: 0,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { CopyIcon } from '@renderer/components/Icons'
|
||||
import { useTemporaryValue } from '@renderer/hooks/useTemporaryValue'
|
||||
import store from '@renderer/store'
|
||||
import { messageBlocksSelectors } from '@renderer/store/messageBlock'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Check } from 'lucide-react'
|
||||
import React, { memo, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -40,7 +40,7 @@ const Table: React.FC<Props> = ({ children, node, blockId }) => {
|
||||
<TableWrapper className="table-wrapper">
|
||||
<table>{children}</table>
|
||||
<ToolbarWrapper className="table-toolbar">
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.copy')} delay={800}>
|
||||
<ToolButton role="button" aria-label={t('common.copy')} onClick={handleCopyTable}>
|
||||
{copied ? <Check size={14} color="var(--color-primary)" /> : <CopyIcon size={14} />}
|
||||
</ToolButton>
|
||||
|
||||
@@ -12,20 +12,17 @@ vi.mock('@renderer/components/Icons/FallbackFavicon', () => ({
|
||||
default: (props: any) => <div data-testid="mock-favicon" {...props} />
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: ({ children, overlay, title, placement, color, styles, ...props }: any) => (
|
||||
<div
|
||||
data-testid="tooltip-wrapper"
|
||||
data-placement={placement}
|
||||
data-color={color}
|
||||
data-styles={JSON.stringify(styles)}
|
||||
{...props}>
|
||||
const uiMocks = vi.hoisted(() => ({
|
||||
Tooltip: vi.fn(({ children, title, content, placement, ...props }: any) => (
|
||||
<div data-testid="tooltip-wrapper" data-placement={placement} {...props}>
|
||||
{children}
|
||||
<div data-testid="tooltip-content">{overlay || title}</div>
|
||||
<div data-testid="tooltip-content">{content || title}</div>
|
||||
</div>
|
||||
)
|
||||
))
|
||||
}))
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => uiMocks)
|
||||
|
||||
const originalWindowOpen = window.open
|
||||
|
||||
describe('CitationTooltip', () => {
|
||||
@@ -87,22 +84,6 @@ describe('CitationTooltip', () => {
|
||||
expect(favicon).toHaveAttribute('alt', 'Example Title')
|
||||
})
|
||||
|
||||
it('should pass correct props to Tooltip component', () => {
|
||||
const citation = createCitationData()
|
||||
renderCitationTooltip(citation)
|
||||
|
||||
const tooltip = screen.getByTestId('tooltip-wrapper')
|
||||
expect(tooltip).toHaveAttribute('data-placement', 'top')
|
||||
expect(tooltip).toHaveAttribute('data-color', 'var(--color-background)')
|
||||
|
||||
const styles = JSON.parse(tooltip.getAttribute('data-styles') || '{}')
|
||||
expect(styles.body).toEqual({
|
||||
border: '1px solid var(--color-border)',
|
||||
padding: '12px',
|
||||
borderRadius: '8px'
|
||||
})
|
||||
})
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const citation = createCitationData()
|
||||
const { container } = render(
|
||||
|
||||
@@ -102,7 +102,6 @@ describe('Hyperlink', () => {
|
||||
const popover = screen.getByTestId('popover')
|
||||
expect(popover).toBeInTheDocument()
|
||||
expect(popover).toHaveAttribute('data-arrow', 'false')
|
||||
expect(popover).toHaveAttribute('data-placement', 'top')
|
||||
|
||||
// Content includes decoded url text and favicon with hostname
|
||||
expect(screen.getByTestId('favicon')).toHaveAttribute('data-hostname', 'domain.com')
|
||||
|
||||
@@ -33,7 +33,10 @@ vi.mock('@renderer/components/Icons', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
Check: ({ size }: { size: number }) => <div data-testid="check-icon" style={{ width: size, height: size }} />
|
||||
Check: ({ size }: { size: number }) => <div data-testid="check-icon" style={{ width: size, height: size }} />,
|
||||
CheckIcon: ({ size }: { size: number }) => <div data-testid="check-icon" style={{ width: size, height: size }} />,
|
||||
CircleXIcon: () => <span>error</span>,
|
||||
AlertTriangleIcon: () => <span>alert</span>
|
||||
}))
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
@@ -42,9 +45,9 @@ vi.mock('react-i18next', () => ({
|
||||
})
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Tooltip: ({ children, title }: any) => (
|
||||
<div data-testid="tooltip" title={title}>
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Tooltip: ({ children, title, content }: any) => (
|
||||
<div data-testid="tooltip" title={content || title}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
+1
-3
@@ -47,9 +47,7 @@ exports[`CitationTooltip > basic rendering > should match snapshot 1`] = `
|
||||
}
|
||||
|
||||
<div
|
||||
data-color="var(--color-background)"
|
||||
data-placement="top"
|
||||
data-styles="{"body":{"border":"1px solid var(--color-border)","padding":"12px","borderRadius":"8px"}}"
|
||||
class="rounded-[8px] border border-[var(--color-border)] bg-[var(--color-background)] p-3"
|
||||
data-testid="tooltip-wrapper"
|
||||
>
|
||||
<span>
|
||||
|
||||
@@ -4,7 +4,6 @@ exports[`Hyperlink > should match snapshot for normal url 1`] = `
|
||||
<div>
|
||||
<div
|
||||
data-arrow="false"
|
||||
data-placement="top"
|
||||
data-styles="{"body":{"padding":0,"borderRadius":"8px","overflow":"hidden"}}"
|
||||
data-testid="popover"
|
||||
>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { CheckOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import ThinkingEffect from '@renderer/components/ThinkingEffect'
|
||||
import { useTemporaryValue } from '@renderer/hooks/useTemporaryValue'
|
||||
import { MessageBlockStatus, type ThinkingMessageBlock } from '@renderer/types/newMessage'
|
||||
import { Collapse, Tooltip } from 'antd'
|
||||
import { Collapse } from 'antd'
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
@@ -81,7 +82,7 @@ const ThinkingBlock: React.FC<Props> = ({ block }) => {
|
||||
fontSize
|
||||
}}>
|
||||
{!isThinking && (
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.copy')} delay={800}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -42,17 +42,20 @@ vi.mock('antd', () => ({
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
Tooltip: ({ title, children, mouseEnterDelay }: any) => (
|
||||
<div data-testid="tooltip" title={title} data-mouse-enter-delay={mouseEnterDelay}>
|
||||
{children}
|
||||
</div>
|
||||
),
|
||||
message: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn()
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
Tooltip: ({ title, children, mouseEnterDelay }: any) => (
|
||||
<div data-testid="tooltip" title={title} data-mouse-enter-delay={mouseEnterDelay}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}))
|
||||
|
||||
// Mock icons
|
||||
vi.mock('@ant-design/icons', () => ({
|
||||
CheckOutlined: ({ style }: any) => (
|
||||
@@ -68,7 +71,10 @@ vi.mock('lucide-react', () => ({
|
||||
💡
|
||||
</span>
|
||||
),
|
||||
ChevronRight: (props: any) => <svg data-testid="chevron-right-icon" {...props} />
|
||||
ChevronRight: (props: any) => <svg data-testid="chevron-right-icon" {...props} />,
|
||||
CheckIcon: () => <span>check</span>,
|
||||
CircleXIcon: () => <span>error</span>,
|
||||
AlertTriangleIcon: () => <span>alert</span>
|
||||
}))
|
||||
|
||||
// Mock motion
|
||||
|
||||
-2
@@ -85,9 +85,7 @@ exports[`ThinkingBlock > basic rendering > should match snapshot 1`] = `
|
||||
style="font-family: var(--font-family); font-size: 14px;"
|
||||
>
|
||||
<div
|
||||
data-mouse-enter-delay="0.8"
|
||||
data-testid="tooltip"
|
||||
title="Copy"
|
||||
>
|
||||
<button
|
||||
aria-label="Copy"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import '@xyflow/react/dist/style.css'
|
||||
|
||||
import { RobotOutlined, UserOutlined } from '@ant-design/icons'
|
||||
import { Avatar } from '@cherrystudio/ui'
|
||||
import { EmojiAvatar } from '@cherrystudio/ui'
|
||||
import { Avatar, EmojiAvatar, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import { getModelLogo } from '@renderer/config/models'
|
||||
@@ -18,7 +17,7 @@ import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||
import type { Edge, Node, NodeTypes } from '@xyflow/react'
|
||||
import { Controls, Handle, MiniMap, ReactFlow, ReactFlowProvider } from '@xyflow/react'
|
||||
import { Position, useEdgesState, useNodesState } from '@xyflow/react'
|
||||
import { Spin, Tooltip } from 'antd'
|
||||
import { Spin } from 'antd'
|
||||
import { isEqual } from 'lodash'
|
||||
import type { FC } from 'react'
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
@@ -91,13 +90,7 @@ const CustomNode: FC<{ data: any }> = ({ data }) => {
|
||||
avatar = <ModelAvatar model={data.modelInfo} size={32} />
|
||||
} else if (data.modelId) {
|
||||
const modelLogo = getModelLogo(data.modelId)
|
||||
avatar = (
|
||||
<Avatar
|
||||
src={modelLogo}
|
||||
icon={!modelLogo ? <RobotOutlined /> : undefined}
|
||||
className="bg-primary"
|
||||
/>
|
||||
)
|
||||
avatar = <Avatar src={modelLogo} icon={!modelLogo ? <RobotOutlined /> : undefined} className="bg-primary" />
|
||||
} else {
|
||||
avatar = <Avatar icon={<RobotOutlined />} className="bg-primary" />
|
||||
}
|
||||
@@ -141,18 +134,16 @@ const CustomNode: FC<{ data: any }> = ({ data }) => {
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
title={
|
||||
content={
|
||||
<TooltipContent>
|
||||
<TooltipTitle>{title}</TooltipTitle>
|
||||
<TooltipBody>{data.content}</TooltipBody>
|
||||
<TooltipFooter>{t('chat.history.click_to_navigate')}</TooltipFooter>
|
||||
</TooltipContent>
|
||||
}
|
||||
placement="top"
|
||||
color="rgba(0, 0, 0, 0.85)"
|
||||
mouseEnterDelay={0.3}
|
||||
mouseLeaveDelay={0.1}
|
||||
destroyOnHidden>
|
||||
classNames={{ content: 'bg-[#000000d8] text-gray-200 text-sm' }}
|
||||
delay={300}
|
||||
closeDelay={100}>
|
||||
<CustomNodeContainer
|
||||
style={{
|
||||
borderColor,
|
||||
|
||||
@@ -6,11 +6,11 @@ import {
|
||||
VerticalAlignBottomOutlined,
|
||||
VerticalAlignTopOutlined
|
||||
} from '@ant-design/icons'
|
||||
// import { selectCurrentTopicId } from '@renderer/store/newMessage'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import type { RootState } from '@renderer/store'
|
||||
import { Drawer, Tooltip } from 'antd'
|
||||
// import { selectCurrentTopicId } from '@renderer/store/newMessage'
|
||||
import { Drawer } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -337,7 +337,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
<>
|
||||
<NavigationContainer $isVisible={isVisible} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
||||
<ButtonGroup>
|
||||
<Tooltip title={t('chat.navigation.close')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.close')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<CloseOutlined />}
|
||||
@@ -346,7 +346,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.top')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.top')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<VerticalAlignTopOutlined />}
|
||||
@@ -355,7 +355,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.prev')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.prev')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<ArrowUpOutlined />}
|
||||
@@ -364,7 +364,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.next')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.next')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<ArrowDownOutlined />}
|
||||
@@ -373,7 +373,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.bottom')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.bottom')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<VerticalAlignBottomOutlined />}
|
||||
@@ -382,7 +382,7 @@ const ChatNavigation: FC<ChatNavigationProps> = ({ containerId }) => {
|
||||
/>
|
||||
</Tooltip>
|
||||
<Divider />
|
||||
<Tooltip title={t('chat.navigation.history')} placement="left" mouseEnterDelay={0.5}>
|
||||
<Tooltip placement="left" content={t('chat.navigation.history')} delay={500}>
|
||||
<NavigationButton
|
||||
variant="light"
|
||||
startContent={<HistoryOutlined />}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { ActionIconButton } from '@renderer/components/Buttons'
|
||||
@@ -19,7 +20,7 @@ import { getFilesFromDropEvent, isSendMessageKeyPressed } from '@renderer/utils/
|
||||
import { createFileBlock, createImageBlock } from '@renderer/utils/messageUtils/create'
|
||||
import { findAllBlocks } from '@renderer/utils/messageUtils/find'
|
||||
import { documentExts, imageExts, textExts } from '@shared/config/constant'
|
||||
import { Space, Tooltip } from 'antd'
|
||||
import { Space } from 'antd'
|
||||
import type { TextAreaRef } from 'antd/es/input/TextArea'
|
||||
import TextArea from 'antd/es/input/TextArea'
|
||||
import { Save, Send, X } from 'lucide-react'
|
||||
@@ -359,14 +360,14 @@ const MessageBlockEditor: FC<Props> = ({ message, topicId, onSave, onResend, onC
|
||||
</ActionBarLeft>
|
||||
<ActionBarMiddle />
|
||||
<ActionBarRight>
|
||||
<Tooltip title={t('common.cancel')}>
|
||||
<Tooltip content={t('common.cancel')}>
|
||||
<ActionIconButton onPress={onCancel} icon={<X size={16} />} />
|
||||
</Tooltip>
|
||||
<Tooltip title={t('common.save')}>
|
||||
<Tooltip content={t('common.save')}>
|
||||
<ActionIconButton onPress={handleSave} icon={<Save size={16} />} />
|
||||
</Tooltip>
|
||||
{message.role === 'user' && (
|
||||
<Tooltip title={t('chat.resend')}>
|
||||
<Tooltip content={t('chat.resend')}>
|
||||
<ActionIconButton onPress={handleResend} icon={<Send size={16} />} />
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
ReloadOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { useAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
|
||||
import type { Topic } from '@renderer/types'
|
||||
@@ -15,7 +15,6 @@ import type { Message } from '@renderer/types/newMessage'
|
||||
import { AssistantMessageStatus } from '@renderer/types/newMessage'
|
||||
import { getMainTextContent } from '@renderer/utils/messageUtils/find'
|
||||
import type { MultiModelMessageStyle } from '@shared/data/preference/preferenceTypes'
|
||||
import { Tooltip } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -107,9 +106,11 @@ const MessageGroupMenuBar: FC<Props> = ({
|
||||
<LayoutContainer>
|
||||
{(['fold', 'vertical', 'horizontal', 'grid'] as const).map((layout) => (
|
||||
<Tooltip
|
||||
mouseEnterDelay={0.5}
|
||||
delay={500}
|
||||
key={layout}
|
||||
title={t('message.message.multi_model_style.label') + ': ' + multiModelMessageStyleTextByLayout[layout]}>
|
||||
content={
|
||||
t('message.message.multi_model_style.label') + ': ' + multiModelMessageStyleTextByLayout[layout]
|
||||
}>
|
||||
<LayoutOption
|
||||
$active={multiModelMessageStyle === layout}
|
||||
onClick={() => setMultiModelMessageStyle(layout)}>
|
||||
@@ -136,7 +137,7 @@ const MessageGroupMenuBar: FC<Props> = ({
|
||||
{multiModelMessageStyle === 'grid' && <MessageGroupSettings />}
|
||||
</RowFlex>
|
||||
{hasFailedMessages && (
|
||||
<Tooltip title={t('message.group.retry_failed')} mouseEnterDelay={0.6}>
|
||||
<Tooltip content={t('message.group.retry_failed')} delay={600}>
|
||||
<Button
|
||||
variant="light"
|
||||
size="sm"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ArrowsAltOutlined, ShrinkOutlined } from '@ant-design/icons'
|
||||
import { Avatar, AvatarGroup, RowFlex } from '@cherrystudio/ui'
|
||||
import { Avatar, AvatarGroup, RowFlex, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import ModelAvatar from '@renderer/components/Avatar/ModelAvatar'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
@@ -8,7 +8,7 @@ import type { Model } from '@renderer/types'
|
||||
import { AssistantMessageStatus, type Message } from '@renderer/types/newMessage'
|
||||
import { lightbulbSoftVariants } from '@renderer/utils/motionVariants'
|
||||
import type { MultiModelFoldDisplayMode } from '@shared/data/preference/preferenceTypes'
|
||||
import { Segmented as AntdSegmented, Tooltip } from 'antd'
|
||||
import { Segmented as AntdSegmented } from 'antd'
|
||||
import { first } from 'lodash'
|
||||
import { motion } from 'motion/react'
|
||||
import type { FC } from 'react'
|
||||
@@ -41,7 +41,7 @@ const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, selec
|
||||
|
||||
if (isCompact) {
|
||||
return (
|
||||
<Tooltip key={message.id} title={modelTip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip key={message.id} content={modelTip} delay={500} closeDelay={0}>
|
||||
<AvatarWrapper
|
||||
className="avatar-wrapper"
|
||||
$isSelected={message.id === selectMessageId}
|
||||
@@ -68,14 +68,13 @@ const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, selec
|
||||
return (
|
||||
<Container>
|
||||
<Tooltip
|
||||
title={
|
||||
content={
|
||||
isCompact
|
||||
? t('message.message.multi_model_style.fold.expand')
|
||||
: t('message.message.multi_model_style.fold.compress')
|
||||
}
|
||||
placement="top"
|
||||
mouseEnterDelay={0.5}
|
||||
mouseLeaveDelay={0}>
|
||||
delay={500}
|
||||
closeDelay={0}>
|
||||
<DisplayModeToggle
|
||||
displayMode={foldDisplayMode}
|
||||
onClick={() => setFoldDisplayMode(isCompact ? 'expanded' : 'compact')}>
|
||||
@@ -91,7 +90,7 @@ const MessageGroupModelList: FC<MessageGroupModelListProps> = ({ messages, selec
|
||||
const isSelected = message.id === selectMessageId
|
||||
|
||||
return (
|
||||
<Tooltip key={message.id} title={modelTip} mouseEnterDelay={0.5} mouseLeaveDelay={0}>
|
||||
<Tooltip key={message.id} content={modelTip} delay={500} closeDelay={0}>
|
||||
<Avatar
|
||||
src={getModelLogo(message.model?.id || '')}
|
||||
name={first(message.model?.name)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Avatar, EmojiAvatar } from '@cherrystudio/ui'
|
||||
import { Avatar, EmojiAvatar, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import UserPopup from '@renderer/components/Popups/UserPopup'
|
||||
import { APP_NAME, AppLogo, isLocalAi } from '@renderer/config/env'
|
||||
@@ -15,7 +15,7 @@ import { getModelName } from '@renderer/services/ModelService'
|
||||
import type { Assistant, Model, Topic } from '@renderer/types'
|
||||
import type { Message } from '@renderer/types/newMessage'
|
||||
import { firstLetter, isEmoji, removeLeadingEmoji } from '@renderer/utils'
|
||||
import { Checkbox, Tooltip } from 'antd'
|
||||
import { Checkbox } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { Sparkle } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -118,7 +118,7 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message, topic, isGro
|
||||
{username}
|
||||
</UserName>
|
||||
{isGroupContextMessage && (
|
||||
<Tooltip title={t('chat.message.useful.tip')}>
|
||||
<Tooltip content={t('chat.message.useful.tip')}>
|
||||
<Sparkle fill="var(--color-primary)" strokeWidth={0} size={18} />
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// import { InfoCircleOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { useMultiplePreferences } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
@@ -41,7 +42,7 @@ import {
|
||||
findTranslationBlocksById,
|
||||
getMainTextContent
|
||||
} from '@renderer/utils/messageUtils/find'
|
||||
import { Dropdown, Popconfirm, Tooltip } from 'antd'
|
||||
import { Dropdown, Popconfirm } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import {
|
||||
AtSign,
|
||||
@@ -490,17 +491,18 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
okButtonProps={{ danger: true }}
|
||||
onConfirm={() => handleResendUserMessage()}
|
||||
onOpenChange={(open) => open && setShowDeleteTooltip(false)}>
|
||||
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
$softHoverBg={isBubbleStyle}>
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
{/* FIXME: Popconfirm from antd is not compatible with Tooltip from HeroUI */}
|
||||
{/* <Tooltip content={t('common.regenerate')} delay={800}> */}
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
$softHoverBg={isBubbleStyle}>
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
{/* </Tooltip> */}
|
||||
</Popconfirm>
|
||||
) : (
|
||||
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.regenerate')} delay={800}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={() => handleResendUserMessage()}
|
||||
@@ -510,13 +512,13 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
</Tooltip>
|
||||
))}
|
||||
{message.role === 'user' && (
|
||||
<Tooltip title={t('common.edit')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.edit')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={onEdit} $softHoverBg={softHoverBg}>
|
||||
<EditIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.copy')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={onCopy} $softHoverBg={softHoverBg}>
|
||||
{!copied && <CopyIcon size={15} />}
|
||||
{copied && <Check size={15} color="var(--color-primary)" />}
|
||||
@@ -529,24 +531,25 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
okButtonProps={{ danger: true }}
|
||||
onConfirm={onRegenerate}
|
||||
onOpenChange={(open) => open && setShowDeleteTooltip(false)}>
|
||||
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
$softHoverBg={softHoverBg}>
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
{/* FIXME: Popconfirm from antd is not compatible with Tooltip from HeroUI */}
|
||||
{/* <Tooltip content={t('common.regenerate')} delay={800}> */}
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
$softHoverBg={softHoverBg}>
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
{/* </Tooltip> */}
|
||||
</Popconfirm>
|
||||
) : (
|
||||
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('common.regenerate')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={onRegenerate} $softHoverBg={softHoverBg}>
|
||||
<RefreshIcon size={15} />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
))}
|
||||
{isAssistantMessage && (
|
||||
<Tooltip title={t('message.mention.title')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('message.mention.title')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={onMentionModel} $softHoverBg={softHoverBg}>
|
||||
<AtSign size={15} />
|
||||
</ActionButton>
|
||||
@@ -615,9 +618,8 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
onClick: (e) => e.domEvent.stopPropagation()
|
||||
}}
|
||||
trigger={['click']}
|
||||
placement="top"
|
||||
arrow>
|
||||
<Tooltip title={t('chat.translate')} mouseEnterDelay={1.2}>
|
||||
<Tooltip content={t('chat.translate')} delay={1200}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
@@ -628,7 +630,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
</Dropdown>
|
||||
)}
|
||||
{isAssistantMessage && isGrouped && (
|
||||
<Tooltip title={t('chat.message.useful.label')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('chat.message.useful.label')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={onUseful} $softHoverBg={softHoverBg}>
|
||||
{message.useful ? (
|
||||
<ThumbsUp size={17.5} fill="var(--color-primary)" strokeWidth={0} />
|
||||
@@ -639,7 +641,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
</Tooltip>
|
||||
)}
|
||||
{isAssistantMessage && (
|
||||
<Tooltip title={t('notes.save')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('notes.save')} delay={800}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={async (e) => {
|
||||
@@ -663,11 +665,7 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
className="message-action-button"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
$softHoverBg={softHoverBg}>
|
||||
<Tooltip
|
||||
title={t('common.delete')}
|
||||
mouseEnterDelay={1}
|
||||
open={showDeleteTooltip}
|
||||
onOpenChange={setShowDeleteTooltip}>
|
||||
<Tooltip content={t('common.delete')} delay={800}>
|
||||
<DeleteIcon size={15} />
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
@@ -681,16 +679,16 @@ const MessageMenubar: FC<Props> = (props) => {
|
||||
}}
|
||||
$softHoverBg={softHoverBg}>
|
||||
<Tooltip
|
||||
title={t('common.delete')}
|
||||
mouseEnterDelay={1}
|
||||
open={showDeleteTooltip}
|
||||
content={t('common.delete')}
|
||||
delay={1000}
|
||||
isOpen={showDeleteTooltip}
|
||||
onOpenChange={setShowDeleteTooltip}>
|
||||
<DeleteIcon size={15} />
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
)}
|
||||
{enableDeveloperMode && message.traceId && (
|
||||
<Tooltip title={t('trace.label')} mouseEnterDelay={0.8}>
|
||||
<Tooltip content={t('trace.label')} delay={800}>
|
||||
<ActionButton className="message-action-button" onClick={() => handleTraceUserMessage()}>
|
||||
<TraceIcon size={16} className={'lucide lucide-trash'} />
|
||||
</ActionButton>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { loggerService } from '@logger'
|
||||
import { CopyIcon, LoadingIcon } from '@renderer/components/Icons'
|
||||
@@ -12,7 +12,7 @@ import { isToolAutoApproved } from '@renderer/utils/mcp-tools'
|
||||
import { cancelToolAction, confirmToolAction } from '@renderer/utils/userConfirmation'
|
||||
import type { MCPProgressEvent } from '@shared/config/types'
|
||||
import { IpcChannel } from '@shared/IpcChannel'
|
||||
import { Collapse, ConfigProvider, Dropdown, Modal, Progress, Tabs, Tooltip } from 'antd'
|
||||
import { Collapse, ConfigProvider, Dropdown, Modal, Progress, Tabs } from 'antd'
|
||||
import {
|
||||
Check,
|
||||
ChevronDown,
|
||||
@@ -263,7 +263,7 @@ const MessageMcpTool: FC<Props> = ({ block }) => {
|
||||
<ToolName className="items-center gap-1">
|
||||
{tool.serverName} : {tool.name}
|
||||
{isToolAutoApproved(tool) && (
|
||||
<Tooltip title={t('message.tools.autoApproveEnabled')} mouseLeaveDelay={0}>
|
||||
<Tooltip content={t('message.tools.autoApproveEnabled')} closeDelay={0}>
|
||||
<ShieldCheck size={14} color="var(--status-color-success)" />
|
||||
</Tooltip>
|
||||
)}
|
||||
@@ -275,7 +275,7 @@ const MessageMcpTool: FC<Props> = ({ block }) => {
|
||||
) : (
|
||||
renderStatusIndicator(status, hasError)
|
||||
)}
|
||||
<Tooltip title={t('common.expand')} mouseEnterDelay={0.5}>
|
||||
<Tooltip content={t('common.expand')} delay={500}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => {
|
||||
@@ -290,7 +290,7 @@ const MessageMcpTool: FC<Props> = ({ block }) => {
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
{!isPending && (
|
||||
<Tooltip title={t('common.copy')} mouseEnterDelay={0.5}>
|
||||
<Tooltip content={t('common.copy')} delay={500}>
|
||||
<ActionButton
|
||||
className="message-action-button"
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
|
||||
import SearchPopup from '@renderer/components/Popups/SearchPopup'
|
||||
@@ -9,7 +10,6 @@ import { useShortcut } from '@renderer/hooks/useShortcuts'
|
||||
import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
|
||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||
import type { 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'
|
||||
@@ -74,7 +74,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
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}>
|
||||
<Tooltip placement="bottom" content={t('navbar.hide_sidebar')} delay={800}>
|
||||
<NavbarIcon onClick={toggleShowAssistants}>
|
||||
<PanelLeftClose size={18} />
|
||||
</NavbarIcon>
|
||||
@@ -92,7 +92,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
paddingRight: 10,
|
||||
minWidth: 'auto'
|
||||
}}>
|
||||
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('navbar.show_sidebar')} delay={800}>
|
||||
<NavbarIcon onClick={() => toggleShowAssistants()}>
|
||||
<PanelRightClose size={18} />
|
||||
</NavbarIcon>
|
||||
@@ -123,26 +123,26 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
||||
}}
|
||||
className="home-navbar-right">
|
||||
<RowFlex className="items-center gap-1.5">
|
||||
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('chat.assistant.search.placeholder')} delay={800}>
|
||||
<NarrowIcon onClick={() => SearchPopup.show()}>
|
||||
<Search size={18} />
|
||||
</NarrowIcon>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
||||
<Tooltip placement="bottom" content={t('navbar.expand')} delay={800}>
|
||||
<NarrowIcon onClick={handleNarrowModeToggle}>
|
||||
<i className="iconfont icon-icon-adaptive-width"></i>
|
||||
</NarrowIcon>
|
||||
</Tooltip>
|
||||
<UpdateAppButton />
|
||||
{topicPosition === 'right' && !showTopics && (
|
||||
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={2}>
|
||||
<Tooltip placement="bottom" content={t('navbar.show_sidebar')} delay={2000}>
|
||||
<NavbarIcon onClick={toggleShowTopics}>
|
||||
<PanelLeftClose size={18} />
|
||||
</NavbarIcon>
|
||||
</Tooltip>
|
||||
)}
|
||||
{topicPosition === 'right' && showTopics && (
|
||||
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={2}>
|
||||
<Tooltip placement="bottom" content={t('navbar.hide_sidebar')} delay={2000}>
|
||||
<NavbarIcon onClick={toggleShowTopics}>
|
||||
<PanelRightClose size={18} />
|
||||
</NavbarIcon>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { DownOutlined, RightOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { DraggableList } from '@renderer/components/DraggableList'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
@@ -7,7 +8,7 @@ import { useAssistantsTabSortType } from '@renderer/hooks/useStore'
|
||||
import { useTags } from '@renderer/hooks/useTags'
|
||||
import type { Assistant } from '@renderer/types'
|
||||
import type { AssistantTabSortType } from '@shared/data/preference/preferenceTypes'
|
||||
import { Tooltip, Typography } from 'antd'
|
||||
import { Typography } from 'antd'
|
||||
import { Plus } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
@@ -93,7 +94,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
||||
<TagsContainer key={group.tag}>
|
||||
{group.tag !== t('assistants.tags.untagged') && (
|
||||
<GroupTitle onClick={() => toggleTagCollapse(group.tag)}>
|
||||
<Tooltip title={group.tag}>
|
||||
<Tooltip content={group.tag}>
|
||||
<GroupTitleName>
|
||||
{collapsedTags[group.tag] ? (
|
||||
<RightOutlined style={{ fontSize: '10px', marginRight: '5px' }} />
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Button, DescriptionSwitch, RowFlex, Selector, type SelectorItem } from '@cherrystudio/ui'
|
||||
import { Button, DescriptionSwitch, HelpTooltip, RowFlex, Selector, type SelectorItem } from '@cherrystudio/ui'
|
||||
import { useMultiplePreferences, usePreference } from '@data/hooks/usePreference'
|
||||
import EditableNumber from '@renderer/components/EditableNumber'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { HelpTooltip } from '@renderer/components/TooltipIcons'
|
||||
import { DEFAULT_CONTEXTCOUNT, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||
import { isOpenAIModel } from '@renderer/config/models'
|
||||
import { UNKNOWN } from '@renderer/config/translate'
|
||||
@@ -254,7 +253,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
}}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.temperature.label')}
|
||||
<HelpTooltip title={t('chat.settings.temperature.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.temperature.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</Row>
|
||||
@@ -277,7 +276,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<Row align="middle">
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.context_count.label')}
|
||||
<HelpTooltip title={t('chat.settings.context_count.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.context_count.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</Row>
|
||||
<Row align="middle" gutter={10}>
|
||||
@@ -325,7 +324,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
}}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.max_tokens.label')}
|
||||
<HelpTooltip title={t('chat.settings.max_tokens.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.max_tokens.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -383,7 +382,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<DescriptionSwitch isSelected={thoughtAutoCollapse} onValueChange={setThoughtAutoCollapse}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.thought_auto_collapse.label')}
|
||||
<HelpTooltip title={t('chat.settings.thought_auto_collapse.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.thought_auto_collapse.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -475,7 +474,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<DescriptionSwitch size="sm" isSelected={mathEnableSingleDollar} onValueChange={setMathEnableSingleDollar}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('settings.math.single_dollar.label')}
|
||||
<HelpTooltip title={t('settings.math.single_dollar.tip')} />
|
||||
<HelpTooltip content={t('settings.math.single_dollar.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -504,7 +503,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<DescriptionSwitch size="sm" isSelected={codeFancyBlock} onValueChange={setCodeFancyBlock}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_fancy_block.label')}
|
||||
<HelpTooltip title={t('chat.settings.code_fancy_block.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.code_fancy_block.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -520,7 +519,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
onValueChange={(checked) => setCodeExecution({ enabled: checked })}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_execution.title')}
|
||||
<HelpTooltip title={t('chat.settings.code_execution.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.code_execution.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -530,7 +529,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<SettingRow style={{ paddingLeft: 8 }}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_execution.timeout_minutes.label')}
|
||||
<HelpTooltip title={t('chat.settings.code_execution.timeout_minutes.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.code_execution.timeout_minutes.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<EditableNumber
|
||||
size="small"
|
||||
@@ -568,7 +567,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
onValueChange={(checked) => setCodeEditor({ highlightActiveLine: checked })}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_editor.highlight_active_line')}
|
||||
<HelpTooltip title={t('chat.settings.code_editor.highlight_active_line.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.code_editor.highlight_active_line.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
@@ -627,7 +626,7 @@ const SettingsTab: FC<Props> = (props) => {
|
||||
<DescriptionSwitch size="sm" isSelected={codeImageTools} onValueChange={setCodeImageTools}>
|
||||
<SettingRowTitleSmall>
|
||||
{t('chat.settings.code_image_tools.label')}
|
||||
<HelpTooltip title={t('chat.settings.code_image_tools.tip')} />
|
||||
<HelpTooltip content={t('chat.settings.code_image_tools.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
</DescriptionSwitch>
|
||||
</SettingRow>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { HelpTooltip } from '@cherrystudio/ui'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { useCache } from '@data/hooks/useCache'
|
||||
import { usePreference } from '@data/hooks/usePreference'
|
||||
import { useMultiplePreferences } from '@data/hooks/usePreference'
|
||||
@@ -29,14 +31,13 @@ import {
|
||||
topicToMarkdown
|
||||
} from '@renderer/utils/export'
|
||||
import type { MenuProps } from 'antd'
|
||||
import { Dropdown, Tooltip } from 'antd'
|
||||
import { Dropdown } from 'antd'
|
||||
import type { ItemType, MenuItemType } from 'antd/es/menu/interface'
|
||||
import dayjs from 'dayjs'
|
||||
import { findIndex } from 'lodash'
|
||||
import {
|
||||
BrushCleaning,
|
||||
FolderOpen,
|
||||
HelpCircle,
|
||||
MenuIcon,
|
||||
NotebookPen,
|
||||
PackagePlus,
|
||||
@@ -266,11 +267,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
label: t('chat.topics.prompt.label'),
|
||||
key: 'topic-prompt',
|
||||
icon: <PackagePlus size={14} />,
|
||||
extra: (
|
||||
<Tooltip title={t('chat.topics.prompt.tips')}>
|
||||
<HelpCircle size={14} />
|
||||
</Tooltip>
|
||||
),
|
||||
extra: <HelpTooltip content={t('chat.topics.prompt.tips')} />,
|
||||
async onClick() {
|
||||
const prompt = await PromptPopup.show({
|
||||
title: t('chat.topics.prompt.edit.title'),
|
||||
@@ -575,9 +572,9 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
{!topic.pinned && (
|
||||
<Tooltip
|
||||
placement="bottom"
|
||||
mouseEnterDelay={0.7}
|
||||
mouseLeaveDelay={0}
|
||||
title={
|
||||
delay={700}
|
||||
closeDelay={0}
|
||||
content={
|
||||
<div style={{ fontSize: '12px', opacity: 0.8, fontStyle: 'italic' }}>
|
||||
{t('chat.topics.delete.shortcut', { key: isMac ? '⌘' : 'Ctrl' })}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { HelpTooltip } from '@cherrystudio/ui'
|
||||
import Selector from '@renderer/components/Selector'
|
||||
import {
|
||||
isSupportedReasoningEffortOpenAIModel,
|
||||
@@ -14,8 +15,6 @@ import { setOpenAISummaryText, setOpenAIVerbosity } from '@renderer/store/settin
|
||||
import type { Model, OpenAIServiceTier, OpenAISummaryText, ServiceTier } from '@renderer/types'
|
||||
import { GroqServiceTiers, OpenAIServiceTiers, SystemProviderIds } from '@renderer/types'
|
||||
import type { OpenAIVerbosity } from '@types'
|
||||
import { Tooltip } from 'antd'
|
||||
import { CircleHelp } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -167,9 +166,7 @@ const OpenAISettingsGroup: FC<Props> = ({ model, providerId, SettingGroup, Setti
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>
|
||||
{t('settings.openai.service_tier.title')}{' '}
|
||||
<Tooltip title={t('settings.openai.service_tier.tip')}>
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
<HelpTooltip content={t('settings.openai.service_tier.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={serviceTierMode}
|
||||
@@ -188,9 +185,7 @@ const OpenAISettingsGroup: FC<Props> = ({ model, providerId, SettingGroup, Setti
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>
|
||||
{t('settings.openai.summary_text_mode.title')}{' '}
|
||||
<Tooltip title={t('settings.openai.summary_text_mode.tip')}>
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
<HelpTooltip content={t('settings.openai.summary_text_mode.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={summaryText}
|
||||
@@ -206,10 +201,7 @@ const OpenAISettingsGroup: FC<Props> = ({ model, providerId, SettingGroup, Setti
|
||||
{isSupportVerbosity && (
|
||||
<SettingRow>
|
||||
<SettingRowTitleSmall>
|
||||
{t('settings.openai.verbosity.title')}{' '}
|
||||
<Tooltip title={t('settings.openai.verbosity.tip')}>
|
||||
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
|
||||
</Tooltip>
|
||||
{t('settings.openai.verbosity.title')} <HelpTooltip content={t('settings.openai.verbosity.tip')} />
|
||||
</SettingRowTitleSmall>
|
||||
<Selector
|
||||
value={verbosity}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { RedoOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, RowFlex, Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import CustomTag from '@renderer/components/Tags/CustomTag'
|
||||
import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import { NavbarIcon } from '@renderer/pages/home/ChatNavbar'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase } from '@renderer/types'
|
||||
import { Empty, Tabs, Tag, Tooltip } from 'antd'
|
||||
import { Empty, Tabs, Tag } from 'antd'
|
||||
import { Book, Folder, Globe, Link, Notebook, Search, Settings, Video } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -156,7 +155,7 @@ const KnowledgeContent: FC<KnowledgeContentProps> = ({ selectedBase }) => {
|
||||
<div className="label-column">
|
||||
<label>{t('models.embedding_model')}</label>
|
||||
</div>
|
||||
<Tooltip title={providerName} placement="bottom">
|
||||
<Tooltip placement="bottom" content={providerName}>
|
||||
<div className="tag-column">
|
||||
<Tag style={{ borderRadius: 20, margin: 0 }}>{base.model.name}</Tag>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@ const mocks = vi.hoisted(() => {
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('@renderer/components/TooltipIcons', () => ({
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
InfoTooltip: ({ title }: { title: string }) => <div>{mocks.i18n.t(title)}</div>
|
||||
}))
|
||||
|
||||
@@ -36,7 +36,10 @@ vi.mock('react-i18next', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('lucide-react', () => ({
|
||||
TriangleAlert: () => <span>warning</span>
|
||||
TriangleAlert: () => <span>warning</span>,
|
||||
CheckIcon: () => <span>check</span>,
|
||||
CircleXIcon: () => <span>error</span>,
|
||||
AlertTriangleIcon: () => <span>alert</span>
|
||||
}))
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
|
||||
@@ -31,10 +31,10 @@ const mocks = vi.hoisted(() => ({
|
||||
}))
|
||||
|
||||
// Mock InfoTooltip component
|
||||
vi.mock('@renderer/components/TooltipIcons', () => ({
|
||||
vi.mock('@cherrystudio/ui', () => ({
|
||||
InfoTooltip: ({ title, placement }: { title: string; placement: string }) => (
|
||||
<span data-testid="info-tooltip" title={title} data-placement={placement}>
|
||||
ℹ️
|
||||
<span data-testid="info-tooltip" data-placement={placement}>
|
||||
{title}
|
||||
</span>
|
||||
)
|
||||
}))
|
||||
|
||||
+3
-9
@@ -27,9 +27,7 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
class="settings-label"
|
||||
>
|
||||
分块大小
|
||||
<div>
|
||||
knowledge.chunk_size_tooltip
|
||||
</div>
|
||||
<div />
|
||||
</div>
|
||||
<input
|
||||
aria-label="分块大小"
|
||||
@@ -47,9 +45,7 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
class="settings-label"
|
||||
>
|
||||
分块重叠
|
||||
<div>
|
||||
knowledge.chunk_overlap_tooltip
|
||||
</div>
|
||||
<div />
|
||||
</div>
|
||||
<input
|
||||
aria-label="分块重叠"
|
||||
@@ -67,9 +63,7 @@ exports[`AdvancedSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
class="settings-label"
|
||||
>
|
||||
检索相似度阈值
|
||||
<div>
|
||||
knowledge.threshold_tooltip
|
||||
</div>
|
||||
<div />
|
||||
</div>
|
||||
<input
|
||||
aria-label="检索相似度阈值"
|
||||
|
||||
+5
-20
@@ -44,10 +44,7 @@ exports[`GeneralSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
<span
|
||||
data-placement="right"
|
||||
data-testid="info-tooltip"
|
||||
title="settings.tool.preprocess.tooltip"
|
||||
>
|
||||
ℹ️
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<select
|
||||
data-allow-clear="true"
|
||||
@@ -81,10 +78,7 @@ exports[`GeneralSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
<span
|
||||
data-placement="right"
|
||||
data-testid="info-tooltip"
|
||||
title="models.embedding_model_tooltip"
|
||||
>
|
||||
ℹ️
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<select
|
||||
data-has-providers="true"
|
||||
@@ -119,10 +113,7 @@ exports[`GeneralSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
<span
|
||||
data-placement="right"
|
||||
data-testid="info-tooltip"
|
||||
title="knowledge.dimensions_size_tooltip"
|
||||
>
|
||||
ℹ️
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
data-model="text-embedding-3-small"
|
||||
@@ -141,10 +132,7 @@ exports[`GeneralSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
<span
|
||||
data-placement="right"
|
||||
data-testid="info-tooltip"
|
||||
title="models.rerank_model_tooltip"
|
||||
>
|
||||
ℹ️
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<select
|
||||
data-allow-clear="true"
|
||||
@@ -180,10 +168,7 @@ exports[`GeneralSettingsPanel > basic rendering > should match snapshot 1`] = `
|
||||
<span
|
||||
data-placement="right"
|
||||
data-testid="info-tooltip"
|
||||
title="knowledge.document_count_help"
|
||||
>
|
||||
ℹ️
|
||||
</span>
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
data-marks="{"1":"1","6":"knowledge.document_count_default","30":"30","50":"50"}"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CopyOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import type { FileMetadata, KnowledgeSearchResult } from '@renderer/types'
|
||||
import { Tooltip, Typography } from 'antd'
|
||||
import { Typography } from 'antd'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -44,7 +45,7 @@ export const CopyButtonContainer: React.FC<CopyButtonContainerProps> = ({ textTo
|
||||
|
||||
return (
|
||||
<TagContainer>
|
||||
<Tooltip title={tooltipTitle}>
|
||||
<Tooltip content={tooltipTitle}>
|
||||
<CopyButton onClick={() => handleCopy(textToCopy)}>
|
||||
<CopyOutlined />
|
||||
</CopyButton>
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
import { InfoTooltip } from '@renderer/components/TooltipIcons'
|
||||
import { InfoTooltip } from '@cherrystudio/ui'
|
||||
import type { KnowledgeBase } from '@renderer/types'
|
||||
import { Alert, InputNumber } from 'antd'
|
||||
import { TriangleAlert } from 'lucide-react'
|
||||
@@ -24,7 +24,7 @@ const AdvancedSettingsPanel: React.FC<AdvancedSettingsPanelProps> = ({ newBase,
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('knowledge.chunk_size')}
|
||||
<InfoTooltip title={t('knowledge.chunk_size_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('knowledge.chunk_size_tooltip')} placement="right" />
|
||||
</div>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
@@ -39,7 +39,7 @@ const AdvancedSettingsPanel: React.FC<AdvancedSettingsPanelProps> = ({ newBase,
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('knowledge.chunk_overlap')}
|
||||
<InfoTooltip title={t('knowledge.chunk_overlap_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('knowledge.chunk_overlap_tooltip')} placement="right" />
|
||||
</div>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
@@ -54,7 +54,7 @@ const AdvancedSettingsPanel: React.FC<AdvancedSettingsPanelProps> = ({ newBase,
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('knowledge.threshold')}
|
||||
<InfoTooltip title={t('knowledge.threshold_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('knowledge.threshold_tooltip')} placement="right" />
|
||||
</div>
|
||||
<InputNumber
|
||||
style={{ width: '100%' }}
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
import { InfoTooltip } from '@cherrystudio/ui'
|
||||
import InputEmbeddingDimension from '@renderer/components/InputEmbeddingDimension'
|
||||
import ModelSelector from '@renderer/components/ModelSelector'
|
||||
import { InfoTooltip } from '@renderer/components/TooltipIcons'
|
||||
import { DEFAULT_KNOWLEDGE_DOCUMENT_COUNT } from '@renderer/config/constant'
|
||||
import { isEmbeddingModel, isRerankModel } from '@renderer/config/models'
|
||||
import { useProviders } from '@renderer/hooks/useProvider'
|
||||
@@ -51,7 +51,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = ({
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('settings.tool.preprocess.title')}
|
||||
<InfoTooltip title={t('settings.tool.preprocess.tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('settings.tool.preprocess.tooltip')} placement="right" />
|
||||
</div>
|
||||
<Select
|
||||
value={selectedDocPreprocessProvider?.id}
|
||||
@@ -66,7 +66,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = ({
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('models.embedding_model')}
|
||||
<InfoTooltip title={t('models.embedding_model_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('models.embedding_model_tooltip')} placement="right" />
|
||||
</div>
|
||||
<ModelSelector
|
||||
providers={providers}
|
||||
@@ -81,7 +81,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = ({
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('knowledge.dimensions')}
|
||||
<InfoTooltip title={t('knowledge.dimensions_size_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('knowledge.dimensions_size_tooltip')} placement="right" />
|
||||
</div>
|
||||
<InputEmbeddingDimension
|
||||
value={newBase.dimensions}
|
||||
@@ -94,7 +94,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = ({
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('models.rerank_model')}
|
||||
<InfoTooltip title={t('models.rerank_model_tooltip')} placement="right" />
|
||||
<InfoTooltip content={t('models.rerank_model_tooltip')} placement="right" />
|
||||
</div>
|
||||
<ModelSelector
|
||||
providers={providers}
|
||||
@@ -110,7 +110,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = ({
|
||||
<SettingsItem>
|
||||
<div className="settings-label">
|
||||
{t('knowledge.document_count')}
|
||||
<InfoTooltip title={t('knowledge.document_count_help')} placement="right" />
|
||||
<InfoTooltip content={t('knowledge.document_count_help')} placement="right" />
|
||||
</div>
|
||||
<Slider
|
||||
style={{ width: '100%' }}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons'
|
||||
import { Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import type { KnowledgeBase, ProcessingStatus } from '@renderer/types'
|
||||
import { Progress, Tooltip } from 'antd'
|
||||
import { Progress } from 'antd'
|
||||
import type { FC } from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -36,19 +37,19 @@ const StatusIcon: FC<StatusIconProps> = ({
|
||||
if (item?.uniqueId) {
|
||||
if (isPreprocessed && item.type === 'file') {
|
||||
return (
|
||||
<Tooltip title={t('knowledge.status_preprocess_completed')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_preprocess_completed')}>
|
||||
<CheckCircleOutlined style={{ color: '#52c41a' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Tooltip title={t('knowledge.status_embedding_completed')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_embedding_completed')}>
|
||||
<CheckCircleOutlined style={{ color: '#52c41a' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Tooltip title={t('knowledge.status_new')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_new')}>
|
||||
<StatusDot $status="new" />
|
||||
</Tooltip>
|
||||
)
|
||||
@@ -57,7 +58,7 @@ const StatusIcon: FC<StatusIconProps> = ({
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return (
|
||||
<Tooltip title={t('knowledge.status_pending')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_pending')}>
|
||||
<StatusDot $status="pending" />
|
||||
</Tooltip>
|
||||
)
|
||||
@@ -66,20 +67,20 @@ const StatusIcon: FC<StatusIconProps> = ({
|
||||
return type === 'directory' || type === 'file' ? (
|
||||
<Progress type="circle" size={14} percent={Number(progress?.toFixed(0))} />
|
||||
) : (
|
||||
<Tooltip title={t('knowledge.status_processing')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_processing')}>
|
||||
<StatusDot $status="processing" />
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
case 'completed':
|
||||
return (
|
||||
<Tooltip title={t('knowledge.status_completed')} placement="left">
|
||||
<Tooltip placement="left" content={t('knowledge.status_completed')}>
|
||||
<CheckCircleOutlined style={{ color: '#52c41a' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
case 'failed':
|
||||
return (
|
||||
<Tooltip title={errorText || t('knowledge.status_failed')} placement="left">
|
||||
<Tooltip placement="left" content={errorText || t('knowledge.status_failed')}>
|
||||
<CloseCircleOutlined style={{ color: '#ff4d4f' }} />
|
||||
</Tooltip>
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { DeleteIcon } from '@renderer/components/Icons'
|
||||
@@ -7,7 +7,6 @@ import { useKnowledge } from '@renderer/hooks/useKnowledge'
|
||||
import FileItem from '@renderer/pages/files/FileItem'
|
||||
import { getProviderName } from '@renderer/services/ProviderService'
|
||||
import type { KnowledgeBase, KnowledgeItem } from '@renderer/types'
|
||||
import { Tooltip } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusIcon } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
@@ -94,7 +93,7 @@ const KnowledgeDirectories: FC<KnowledgeContentProps> = ({ selectedBase, progres
|
||||
name: (
|
||||
<ClickableSpan onClick={() => window.api.file.openPath(item.content as string)}>
|
||||
<Ellipsis>
|
||||
<Tooltip title={item.content as string}>{item.content as string}</Tooltip>
|
||||
<Tooltip content={item.content as string}>{item.content as string}</Tooltip>
|
||||
</Ellipsis>
|
||||
</ClickableSpan>
|
||||
),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from '@cherrystudio/ui'
|
||||
import { Button, Tooltip } from '@cherrystudio/ui'
|
||||
import { loggerService } from '@logger'
|
||||
import Ellipsis from '@renderer/components/Ellipsis'
|
||||
import { useFiles } from '@renderer/hooks/useFiles'
|
||||
@@ -11,7 +11,7 @@ import type { FileMetadata, FileTypes, KnowledgeBase, KnowledgeItem } from '@ren
|
||||
import { isKnowledgeFileItem } from '@renderer/types'
|
||||
import { formatFileSize, uuid } from '@renderer/utils'
|
||||
import { bookExts, documentExts, textExts, thirdPartyApplicationExts } from '@shared/config/constant'
|
||||
import { Tooltip, Upload } from 'antd'
|
||||
import { Upload } from 'antd'
|
||||
import dayjs from 'dayjs'
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@@ -193,7 +193,7 @@ const KnowledgeFiles: FC<KnowledgeContentProps> = ({ selectedBase, progressMap,
|
||||
name: (
|
||||
<ClickableSpan onClick={() => window.api.file.openFileWithRelativePath(file)}>
|
||||
<Ellipsis>
|
||||
<Tooltip title={file.origin_name}>{file.origin_name}</Tooltip>
|
||||
<Tooltip content={file.origin_name}>{file.origin_name}</Tooltip>
|
||||
</Ellipsis>
|
||||
</ClickableSpan>
|
||||
),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user