Yi Xiao hace 8 meses
padre
commit
3be756eaed
Se han modificado 93 ficheros con 640 adiciones y 758 borrados
  1. 3 4
      web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx
  2. 3 4
      web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx
  3. 3 6
      web/app/(commonLayout)/datasets/DatasetCard.tsx
  4. 12 8
      web/app/components/app-sidebar/basic.tsx
  5. 6 7
      web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx
  6. 6 9
      web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx
  7. 7 6
      web/app/components/app/configuration/config-var/index.tsx
  8. 7 8
      web/app/components/app/configuration/config-vision/index.tsx
  9. 9 10
      web/app/components/app/configuration/config-vision/param-config-content.tsx
  10. 9 10
      web/app/components/app/configuration/config-voice/param-config-content.tsx
  11. 1 4
      web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx
  12. 17 15
      web/app/components/app/configuration/config/agent/agent-tools/index.tsx
  13. 2 3
      web/app/components/app/configuration/dataset-config/card-item/index.tsx
  14. 6 10
      web/app/components/app/configuration/dataset-config/context-var/index.tsx
  15. 23 17
      web/app/components/app/configuration/dataset-config/params-config/config-content.tsx
  16. 3 3
      web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx
  17. 8 9
      web/app/components/app/configuration/features/chat-group/suggested-questions-after-answer/index.tsx
  18. 2 1
      web/app/components/app/configuration/prompt-value-panel/index.tsx
  19. 9 7
      web/app/components/app/configuration/toolbox/annotation/annotation-ctrl-btn/index.tsx
  20. 3 8
      web/app/components/app/configuration/toolbox/annotation/config-param.tsx
  21. 10 7
      web/app/components/app/configuration/tools/index.tsx
  22. 9 13
      web/app/components/app/create-app-modal/index.tsx
  23. 9 13
      web/app/components/app/log/list.tsx
  24. 3 5
      web/app/components/app/overview/appCard.tsx
  25. 1 2
      web/app/components/app/overview/embedded/index.tsx
  26. 9 3
      web/app/components/app/overview/settings/index.tsx
  27. 7 7
      web/app/components/base/audio-btn/index.tsx
  28. 13 7
      web/app/components/base/chat/chat/answer/operation.tsx
  29. 3 3
      web/app/components/base/chat/chat/chat-input.tsx
  30. 1 3
      web/app/components/base/chat/embedded-chatbot/header.tsx
  31. 1 3
      web/app/components/base/chat/embedded-chatbot/index.tsx
  32. 2 6
      web/app/components/base/copy-btn/index.tsx
  33. 7 10
      web/app/components/base/copy-feedback/index.tsx
  34. 3 3
      web/app/components/base/copy-icon/index.tsx
  35. 2 7
      web/app/components/base/features/feature-panel/suggested-questions-after-answer/index.tsx
  36. 10 10
      web/app/components/base/features/feature-panel/text-to-speech/param-config-content.tsx
  37. 3 3
      web/app/components/base/image-uploader/image-list.tsx
  38. 4 8
      web/app/components/base/param-item/index.tsx
  39. 3 3
      web/app/components/base/prompt-editor/plugins/workflow-variable-block/component.tsx
  40. 2 3
      web/app/components/base/qrcode/index.tsx
  41. 0 109
      web/app/components/base/tooltip-plus/index.tsx
  42. 98 38
      web/app/components/base/tooltip/index.tsx
  43. 7 16
      web/app/components/billing/pricing/plan-item.tsx
  44. 3 3
      web/app/components/billing/priority-label/index.tsx
  45. 7 6
      web/app/components/billing/usage-info/index.tsx
  46. 9 11
      web/app/components/datasets/common/retrieval-param-config/index.tsx
  47. 9 7
      web/app/components/datasets/create/embedding-process/index.tsx
  48. 8 10
      web/app/components/datasets/create/step-two/index.tsx
  49. 7 9
      web/app/components/datasets/create/website/firecrawl/base/field.tsx
  50. 3 1
      web/app/components/datasets/documents/detail/metadata/index.tsx
  51. 15 13
      web/app/components/datasets/documents/list.tsx
  52. 3 5
      web/app/components/datasets/hit-testing/textarea.tsx
  53. 14 17
      web/app/components/develop/secret-key/input-copy.tsx
  54. 2 3
      web/app/components/develop/secret-key/secret-key-modal.tsx
  55. 4 4
      web/app/components/header/account-setting/members-page/invited-modal/index.tsx
  56. 2 6
      web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx
  57. 2 4
      web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx
  58. 5 8
      web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx
  59. 3 3
      web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx
  60. 3 3
      web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx
  61. 14 12
      web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx
  62. 3 3
      web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx
  63. 1 2
      web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx
  64. 3 3
      web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx
  65. 8 3
      web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx
  66. 8 7
      web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
  67. 1 2
      web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx
  68. 4 6
      web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx
  69. 33 33
      web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
  70. 6 8
      web/app/components/share/text-generation/result/header.tsx
  71. 3 4
      web/app/components/tools/add-tool-modal/tools.tsx
  72. 4 9
      web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx
  73. 2 8
      web/app/components/tools/workflow-tool/index.tsx
  74. 2 4
      web/app/components/workflow/block-selector/blocks.tsx
  75. 3 5
      web/app/components/workflow/block-selector/tools.tsx
  76. 3 3
      web/app/components/workflow/header/view-history.tsx
  77. 6 8
      web/app/components/workflow/nodes/_base/components/field.tsx
  78. 4 2
      web/app/components/workflow/nodes/_base/components/help-link.tsx
  79. 3 3
      web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx
  80. 4 3
      web/app/components/workflow/nodes/_base/components/node-control.tsx
  81. 10 9
      web/app/components/workflow/nodes/_base/components/option-card.tsx
  82. 6 7
      web/app/components/workflow/nodes/_base/components/prompt/editor.tsx
  83. 4 3
      web/app/components/workflow/nodes/_base/panel.tsx
  84. 3 3
      web/app/components/workflow/nodes/iteration/add-block.tsx
  85. 4 6
      web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx
  86. 7 10
      web/app/components/workflow/nodes/llm/panel.tsx
  87. 9 10
      web/app/components/workflow/nodes/parameter-extractor/panel.tsx
  88. 9 10
      web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx
  89. 5 3
      web/app/components/workflow/note-node/note-editor/toolbar/command.tsx
  90. 3 4
      web/app/components/workflow/operator/tip-popup.tsx
  91. 7 7
      web/app/components/workflow/panel/debug-and-preview/index.tsx
  92. 10 9
      web/app/components/workflow/panel/env-panel/variable-modal.tsx
  93. 3 5
      web/app/signin/oneMoreStep.tsx

+ 3 - 4
web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/config-popup.tsx

@@ -10,7 +10,7 @@ import { TracingProvider } from './type'
 import ProviderConfigModal from './provider-config-modal'
 import Indicator from '@/app/components/header/indicator'
 import Switch from '@/app/components/base/switch'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 const I18N_PREFIX = 'app.tracing'
 
@@ -121,12 +121,11 @@ const ConfigPopup: FC<PopupProps> = ({
             <>
               {providerAllNotConfigured
                 ? (
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={t(`${I18N_PREFIX}.disabledTip`)}
                   >
                     {switchContent}
-
-                  </TooltipPlus>
+                  </Tooltip>
                 )
                 : switchContent}
             </>

+ 3 - 4
web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/toggle-fold-btn.tsx

@@ -3,7 +3,7 @@ import { ChevronDoubleDownIcon } from '@heroicons/react/20/solid'
 import type { FC } from 'react'
 import { useTranslation } from 'react-i18next'
 import React, { useCallback } from 'react'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 const I18N_PREFIX = 'app.tracing'
 
@@ -25,9 +25,8 @@ const ToggleFoldBtn: FC<Props> = ({
   return (
     // text-[0px] to hide spacing between tooltip elements
     <div className='shrink-0 cursor-pointer text-[0px]' onClick={handleFoldChange}>
-      <TooltipPlus
+      <Tooltip
         popupContent={t(`${I18N_PREFIX}.${isFold ? 'expand' : 'collapse'}`)}
-        hideArrow
       >
         {isFold && (
           <div className='p-1 rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5'>
@@ -39,7 +38,7 @@ const ToggleFoldBtn: FC<Props> = ({
             <ChevronDoubleDownIcon className='w-4 h-4 transform rotate-180' />
           </div>
         )}
-      </TooltipPlus>
+      </Tooltip>
     </div>
   )
 }

+ 3 - 6
web/app/(commonLayout)/datasets/DatasetCard.tsx

@@ -4,9 +4,7 @@ import { useContext } from 'use-context-selector'
 import { useRouter } from 'next/navigation'
 import { useCallback, useEffect, useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiMoreFill,
-} from '@remixicon/react'
+import { RiMoreFill } from '@remixicon/react'
 import cn from '@/utils/classnames'
 import Confirm from '@/app/components/base/confirm'
 import { ToastContext } from '@/app/components/base/toast'
@@ -129,10 +127,9 @@ const DatasetCard = ({
               <div className={cn('truncate', !dataset.embedding_available && 'opacity-50 hover:opacity-100')} title={dataset.name}>{dataset.name}</div>
               {!dataset.embedding_available && (
                 <Tooltip
-                  selector={`dataset-tag-${dataset.id}`}
-                  htmlContent={t('dataset.unavailableTip')}
+                  popupContent={t('dataset.unavailableTip')}
                 >
-                  <span className='shrink-0 inline-flex w-max ml-1 px-1 border boder-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
+                  <span className='shrink-0 inline-flex w-max ml-1 px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
                 </Tooltip>
               )}
             </div>

+ 12 - 8
web/app/components/app-sidebar/basic.tsx

@@ -1,10 +1,6 @@
 import React from 'react'
-import {
-  InformationCircleIcon,
-} from '@heroicons/react/24/outline'
-import Tooltip from '../base/tooltip'
 import AppIcon from '../base/app-icon'
-import { randomString } from '@/utils'
+import Tooltip from '@/app/components/base/tooltip'
 
 export type IAppBasicProps = {
   iconType?: 'app' | 'api' | 'dataset' | 'webapp' | 'notion'
@@ -74,9 +70,17 @@ export default function AppBasic({ icon, icon_background, name, type, hoverTip,
         <div className={`flex flex-row items-center text-sm font-semibold text-gray-700 group-hover:text-gray-900 break-all ${textStyle?.main ?? ''}`}>
           {name}
           {hoverTip
-            && <Tooltip content={hoverTip} selector={`a${randomString(16)}`}>
-              <InformationCircleIcon className='w-4 h-4 ml-1 text-gray-400' />
-            </Tooltip>}
+            && <Tooltip
+              popupContent={
+                <div className='w-[240px]'>
+                  {hoverTip}
+                </div>
+              }
+              popupClassName='ml-1'
+              triggerClassName='w-4 h-4 ml-1'
+              position='top'
+            />
+          }
         </div>
         <div className={`text-xs font-normal text-gray-500 group-hover:text-gray-700 break-all ${textStyle?.extra ?? ''}`}>{type}</div>
       </div>}

+ 6 - 7
web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx

@@ -9,7 +9,6 @@ import produce from 'immer'
 import {
   RiDeleteBinLine,
   RiErrorWarningFill,
-  RiQuestionLine,
 } from '@remixicon/react'
 import s from './style.module.css'
 import MessageTypeSelector from './message-type-selector'
@@ -174,12 +173,12 @@ const AdvancedPromptInput: FC<Props> = ({
                     <div className='text-sm font-semibold uppercase text-indigo-800'>{t('appDebug.pageTitle.line1')}
                     </div>
                     <Tooltip
-                      htmlContent={<div className='w-[180px]'>
-                        {t('appDebug.promptTip')}
-                      </div>}
-                      selector='config-prompt-tooltip'>
-                      <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' />
-                    </Tooltip>
+                      popupContent={
+                        <div className='w-[180px]'>
+                          {t('appDebug.promptTip')}
+                        </div>
+                      }
+                    />
                   </div>)}
               <div className={cn(s.optionWrap, 'items-center space-x-1')}>
                 {canDelete && (

+ 6 - 9
web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx

@@ -3,9 +3,6 @@ import type { FC } from 'react'
 import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useBoolean } from 'ahooks'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import produce from 'immer'
 import { useContext } from 'use-context-selector'
 import ConfirmAddVar from './confirm-add-var'
@@ -156,12 +153,12 @@ const Prompt: FC<ISimplePromptInput> = ({
               <div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div>
               {!readonly && (
                 <Tooltip
-                  htmlContent={<div className='w-[180px]'>
-                    {t('appDebug.promptTip')}
-                  </div>}
-                  selector='config-prompt-tooltip'>
-                  <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' />
-                </Tooltip>
+                  popupContent={
+                    <div className='w-[180px]'>
+                      {t('appDebug.promptTip')}
+                    </div>
+                  }
+                />
               )}
             </div>
             <div className='flex items-center'>

+ 7 - 6
web/app/components/app/configuration/config-var/index.tsx

@@ -8,7 +8,6 @@ import { useContext } from 'use-context-selector'
 import produce from 'immer'
 import {
   RiDeleteBinLine,
-  RiQuestionLine,
 } from '@remixicon/react'
 import Panel from '../base/feature-panel'
 import EditModal from './config-modal'
@@ -282,11 +281,13 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
         <div className='flex items-center'>
           <div className='mr-1'>{t('appDebug.variableTitle')}</div>
           {!readonly && (
-            <Tooltip htmlContent={<div className='w-[180px]'>
-              {t('appDebug.variableTip')}
-            </div>} selector='config-var-tooltip'>
-              <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-            </Tooltip>
+            <Tooltip
+              popupContent={
+                <div className='w-[180px]'>
+                  {t('appDebug.variableTip')}
+                </div>
+              }
+            />
           )}
         </div>
       }

+ 7 - 8
web/app/components/app/configuration/config-vision/index.tsx

@@ -2,9 +2,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import { useContext } from 'use-context-selector'
 import Panel from '../base/feature-panel'
 import ParamConfig from './param-config'
@@ -33,11 +30,13 @@ const ConfigVision: FC = () => {
       title={
         <div className='flex items-center'>
           <div className='mr-1'>{t('appDebug.vision.name')}</div>
-          <Tooltip htmlContent={<div className='w-[180px]' >
-            {t('appDebug.vision.description')}
-          </div>} selector='config-vision-tooltip'>
-            <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-          </Tooltip>
+          <Tooltip
+            popupContent={
+              <div className='w-[180px]' >
+                {t('appDebug.vision.description')}
+              </div>
+            }
+          />
         </div>
       }
       headerRight={

+ 9 - 10
web/app/components/app/configuration/config-vision/param-config-content.tsx

@@ -3,9 +3,6 @@ import type { FC } from 'react'
 import React from 'react'
 import { useContext } from 'use-context-selector'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import RadioGroup from './radio-group'
 import ConfigContext from '@/context/debug-configuration'
 import { Resolution, TransferMethod } from '@/types/app'
@@ -37,13 +34,15 @@ const ParamConfigContent: FC = () => {
           <div>
             <div className='mb-2 flex items-center  space-x-1'>
               <div className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.vision.visionSettings.resolution')}</div>
-              <Tooltip htmlContent={<div className='w-[180px]' >
-                {t('appDebug.vision.visionSettings.resolutionTooltip').split('\n').map(item => (
-                  <div key={item}>{item}</div>
-                ))}
-              </div>} selector='config-resolution-tooltip'>
-                <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+              <Tooltip
+                popupContent={
+                  <div className='w-[180px]' >
+                    {t('appDebug.vision.visionSettings.resolutionTooltip').split('\n').map(item => (
+                      <div key={item}>{item}</div>
+                    ))}
+                  </div>
+                }
+              />
             </div>
             <RadioGroup
               className='space-x-3'

+ 9 - 10
web/app/components/app/configuration/config-voice/param-config-content.tsx

@@ -3,9 +3,6 @@ import useSWR from 'swr'
 import type { FC } from 'react'
 import { useContext } from 'use-context-selector'
 import React, { Fragment } from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import { usePathname } from 'next/navigation'
 import { useTranslation } from 'react-i18next'
 import { Listbox, Transition } from '@headlessui/react'
@@ -50,13 +47,15 @@ const VoiceParamConfig: FC = () => {
             <div className='mb-2 flex items-center  space-x-1'>
               <div
                 className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div>
-              <Tooltip htmlContent={<div className='w-[180px]'>
-                {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => (
-                  <div key={item}>{item}</div>
-                ))}
-              </div>} selector='config-resolution-tooltip'>
-                <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+              <Tooltip
+                popupContent={
+                  <div className='w-[180px]'>
+                    {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => (
+                      <div key={item}>{item}</div>
+                    ))}
+                  </div>
+                }
+              />
             </div>
             <Listbox
               value={languageItem}

+ 1 - 4
web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx

@@ -1,7 +1,6 @@
 'use client'
 import type { FC } from 'react'
 import React from 'react'
-import { RiQuestionLine } from '@remixicon/react'
 import cn from '@/utils/classnames'
 import Tooltip from '@/app/components/base/tooltip'
 type Props = {
@@ -25,14 +24,12 @@ const ItemPanel: FC<Props> = ({
         {icon}
         <div className='ml-3 mr-1 leading-6 text-sm font-semibold text-gray-800'>{name}</div>
         <Tooltip
-          htmlContent={
+          popupContent={
             <div className='w-[180px]'>
               {description}
             </div>
           }
-          selector={`agent-setting-tooltip-${name}`}
         >
-          <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
         </Tooltip>
       </div>
       <div>

+ 17 - 15
web/app/components/app/configuration/config/agent/agent-tools/index.tsx

@@ -7,13 +7,11 @@ import produce from 'immer'
 import {
   RiDeleteBinLine,
   RiHammerFill,
-  RiQuestionLine,
 } from '@remixicon/react'
 import { useFormattingChangedDispatcher } from '../../../debug/hooks'
 import SettingBuiltInTool from './setting-built-in-tool'
 import cn from '@/utils/classnames'
 import Panel from '@/app/components/app/configuration/base/feature-panel'
-import Tooltip from '@/app/components/base/tooltip'
 import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
 import OperationBtn from '@/app/components/app/configuration/base/operation-btn'
 import AppIcon from '@/app/components/base/app-icon'
@@ -23,7 +21,7 @@ import type { AgentTool } from '@/types/app'
 import { type Collection, CollectionType } from '@/app/components/tools/types'
 import { MAX_TOOLS_NUM } from '@/config'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other'
 import AddToolModal from '@/app/components/tools/add-tool-modal'
 
@@ -68,11 +66,13 @@ const AgentTools: FC = () => {
         title={
           <div className='flex items-center'>
             <div className='mr-1'>{t('appDebug.agent.tools.name')}</div>
-            <Tooltip htmlContent={<div className='w-[180px]'>
-              {t('appDebug.agent.tools.description')}
-            </div>} selector='config-tools-tooltip'>
-              <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-            </Tooltip>
+            <Tooltip
+              popupContent={
+                <div className='w-[180px]'>
+                  {t('appDebug.agent.tools.description')}
+                </div>
+              }
+            />
           </div>
         }
         headerRight={
@@ -119,19 +119,20 @@ const AgentTools: FC = () => {
                   className={cn((item.isDeleted || item.notAuthor) ? 'line-through opacity-50' : '', 'grow w-0 ml-2 leading-[18px] text-[13px] font-medium text-gray-800  truncate')}
                 >
                   <span className='text-gray-800 pr-2'>{item.provider_type === CollectionType.builtIn ? item.provider_name : item.tool_label}</span>
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={t('tools.toolNameUsageTip')}
                   >
                     <span className='text-gray-500'>{item.tool_name}</span>
-                  </TooltipPlus>
+                  </Tooltip>
                 </div>
               </div>
               <div className='shrink-0 ml-1 flex items-center'>
                 {(item.isDeleted || item.notAuthor)
                   ? (
                     <div className='flex items-center'>
-                      <TooltipPlus
+                      <Tooltip
                         popupContent={t(`tools.${item.isDeleted ? 'toolRemoved' : 'notAuthorized'}`)}
+                        needsDelay
                       >
                         <div className='mr-1 p-1 rounded-md hover:bg-black/5  cursor-pointer' onClick={() => {
                           if (item.notAuthor)
@@ -139,7 +140,7 @@ const AgentTools: FC = () => {
                         }}>
                           <AlertTriangle className='w-4 h-4 text-[#F79009]' />
                         </div>
-                      </TooltipPlus>
+                      </Tooltip>
 
                       <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
                         const newModelConfig = produce(modelConfig, (draft) => {
@@ -155,16 +156,17 @@ const AgentTools: FC = () => {
                   )
                   : (
                     <div className='hidden group-hover:flex items-center'>
-                      <TooltipPlus
+                      <Tooltip
                         popupContent={t('tools.setBuiltInTools.infoAndSetting')}
+                        needsDelay
                       >
-                        <div className='mr-1 p-1 rounded-md hover:bg-black/5  cursor-pointer' onClick={() => {
+                        <div className='p-1 rounded-md hover:bg-black/5  cursor-pointer' onClick={() => {
                           setCurrentTool(item)
                           setIsShowSettingTool(true)
                         }}>
                           <InfoCircle className='w-4 h-4 text-gray-500' />
                         </div>
-                      </TooltipPlus>
+                      </Tooltip>
 
                       <div className='p-1 rounded-md hover:bg-black/5 cursor-pointer' onClick={() => {
                         const newModelConfig = produce(modelConfig, (draft) => {

+ 2 - 3
web/app/components/app/configuration/dataset-config/card-item/index.tsx

@@ -39,10 +39,9 @@ const CardItem: FC<ICardItemProps> = ({
             <div className={cn('text-[13px] leading-[18px] font-medium text-gray-800 overflow-hidden text-ellipsis whitespace-nowrap', !config.embedding_available && 'opacity-50')}>{config.name}</div>
             {!config.embedding_available && (
               <Tooltip
-                selector={`unavailable-tag-${config.id}`}
-                htmlContent={t('dataset.unavailableTip')}
+                popupContent={t('dataset.unavailableTip')}
               >
-                <span className='shrink-0 inline-flex whitespace-nowrap px-1 border boder-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
+                <span className='shrink-0 inline-flex whitespace-nowrap px-1 border border-gray-200 rounded-md text-gray-500 text-xs font-normal leading-[18px]'>{t('dataset.unavailable')}</span>
               </Tooltip>
             )}
           </div>

+ 6 - 10
web/app/components/app/configuration/dataset-config/context-var/index.tsx

@@ -2,9 +2,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import type { Props } from './var-picker'
 import VarPicker from './var-picker'
 import cn from '@/utils/classnames'
@@ -24,13 +21,12 @@ const ContextVar: FC<Props> = (props) => {
         </div>
         <div className='mr-1 text-sm font-medium text-gray-800'>{t('appDebug.feature.dataSet.queryVariable.title')}</div>
         <Tooltip
-          htmlContent={<div className='w-[180px]'>
-            {t('appDebug.feature.dataSet.queryVariable.tip')}
-          </div>}
-          selector='context-var-tooltip'
-        >
-          <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-        </Tooltip>
+          popupContent={
+            <div className='w-[180px]'>
+              {t('appDebug.feature.dataSet.queryVariable.tip')}
+            </div>
+          }
+        />
       </div>
 
       <VarPicker {...props} />

+ 23 - 17
web/app/components/app/configuration/dataset-config/params-config/config-content.tsx

@@ -5,7 +5,6 @@ import type { FC } from 'react'
 import { useTranslation } from 'react-i18next'
 import {
   RiAlertFill,
-  RiQuestionLine,
 } from '@remixicon/react'
 import WeightedScore from './weighted-score'
 import TopKItem from '@/app/components/base/param-item/top-k-item'
@@ -23,7 +22,7 @@ import ModelSelector from '@/app/components/header/account-setting/model-provide
 import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
 import type { ModelConfig } from '@/app/components/workflow/types'
 import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
 import type {
   DataSet,
@@ -173,7 +172,7 @@ const ConfigContent: FC<Props> = ({
           title={(
             <div className='flex items-center'>
               {t('appDebug.datasetConfig.retrieveOneWay.title')}
-              <TooltipPlus
+              <Tooltip
                 popupContent={(
                   <div className='w-[320px]'>
                     {t('dataset.nTo1RetrievalLegacy')}
@@ -181,7 +180,7 @@ const ConfigContent: FC<Props> = ({
                 )}
               >
                 <div className='ml-1 flex items-center px-[5px] h-[18px] rounded-[5px] border border-text-accent-secondary system-2xs-medium-uppercase text-text-accent-secondary'>legacy</div>
-              </TooltipPlus>
+              </Tooltip>
             </div>
           )}
           description={t('appDebug.datasetConfig.retrieveOneWay.description')}
@@ -250,12 +249,15 @@ const ConfigContent: FC<Props> = ({
                       onClick={() => handleRerankModeChange(option.value)}
                     >
                       <div className='truncate'>{option.label}</div>
-                      <TooltipPlus
-                        popupContent={<div className='w-[200px]'>{option.tips}</div>}
-                        hideArrow
-                      >
-                        <RiQuestionLine className='ml-0.5 w-3.5 h-4.5 text-text-quaternary' />
-                      </TooltipPlus>
+                      <Tooltip
+                        popupContent={
+                          <div className='w-[200px]'>
+                            {option.tips}
+                          </div>
+                        }
+                        popupClassName='ml-0.5'
+                        triggerClassName='ml-0.5 w-3.5 h-3.5'
+                      />
                     </div>
                   ))
                 }
@@ -281,9 +283,15 @@ const ConfigContent: FC<Props> = ({
                     )
                   }
                   <div className='ml-2 leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.rerankModel.key')}</div>
-                  <TooltipPlus popupContent={<div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>}>
-                    <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-                  </TooltipPlus>
+                  <Tooltip
+                    popupContent={
+                      <div className="w-[200px]">
+                        {t('common.modelProvider.rerankModel.tip')}
+                      </div>
+                    }
+                    popupClassName='ml-0.5'
+                    triggerClassName='ml-0.5 w-3.5 h-3.5'
+                  />
                 </div>
                 <div>
                   <ModelSelector
@@ -361,11 +369,9 @@ const ConfigContent: FC<Props> = ({
         <div className='mt-4'>
           <div className='flex items-center space-x-0.5'>
             <div className='leading-[32px] text-[13px] font-medium text-gray-900'>{t('common.modelProvider.systemReasoningModel.key')}</div>
-            <TooltipPlus
+            <Tooltip
               popupContent={t('common.modelProvider.systemReasoningModel.tip')}
-            >
-              <RiQuestionLine className='w-3.5 h-4.5 text-gray-400' />
-            </TooltipPlus>
+            />
           </div>
           <ModelParameterModal
             isInWorkflow={isInWorkflow}

+ 3 - 3
web/app/components/app/configuration/debug/debug-with-multiple-model/model-parameter-trigger.tsx

@@ -13,7 +13,7 @@ import {
 } from '@/app/components/header/account-setting/model-provider-page/declarations'
 import { useDebugConfigurationContext } from '@/context/debug-configuration'
 import { CubeOutline } from '@/app/components/base/icons/src/vender/line/shapes'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
 import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
 
@@ -111,9 +111,9 @@ const ModelParameterTrigger: FC<ModelParameterTriggerProps> = ({
           <RiArrowDownSLine className={`w-3 h-3 ${(currentModel && currentProvider) ? 'text-gray-800' : 'text-primary-600'}`} />
           {
             currentModel && currentModel.status !== ModelStatusEnum.active && (
-              <TooltipPlus popupContent={MODEL_STATUS_TEXT[currentModel.status][language]}>
+              <Tooltip popupContent={MODEL_STATUS_TEXT[currentModel.status][language]}>
                 <AlertTriangle className='w-4 h-4 text-[#F79009]' />
-              </TooltipPlus>
+              </Tooltip>
             )
           }
         </div>

+ 8 - 9
web/app/components/app/configuration/features/chat-group/suggested-questions-after-answer/index.tsx

@@ -2,9 +2,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import Panel from '@/app/components/app/configuration/base/feature-panel'
 import SuggestedQuestionsAfterAnswerIcon from '@/app/components/app/configuration/base/icons/suggested-questions-after-answer-icon'
 import Tooltip from '@/app/components/base/tooltip'
@@ -15,13 +12,15 @@ const SuggestedQuestionsAfterAnswer: FC = () => {
   return (
     <Panel
       title={
-        <div className='flex items-center gap-2'>
+        <div className='flex items-center gap-1'>
           <div>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div>
-          <Tooltip htmlContent={<div className='w-[180px]'>
-            {t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}
-          </div>} selector='suggestion-question-tooltip'>
-            <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-          </Tooltip>
+          <Tooltip
+            popupContent={
+              <div className='w-[180px]'>
+                {t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}
+              </div>
+            }
+          />
         </div>
       }
       headerIcon={<SuggestedQuestionsAfterAnswerIcon />}

+ 2 - 1
web/app/components/app/configuration/prompt-value-panel/index.tsx

@@ -16,7 +16,7 @@ import { AppType, ModelModeType } from '@/types/app'
 import Select from '@/app/components/base/select'
 import { DEFAULT_VALUE_MAX_LEN } from '@/config'
 import Button from '@/app/components/base/button'
-import Tooltip from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import TextGenerationImageUploader from '@/app/components/base/image-uploader/text-generation-image-uploader'
 import type { VisionFile, VisionSettings } from '@/types/app'
 
@@ -207,6 +207,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
               {canNotRun
                 ? (<Tooltip
                   popupContent={t('appDebug.otherError.promptNoBeEmpty')}
+                  needsDelay
                 >
                   {renderRunButton()}
                 </Tooltip>)

+ 9 - 7
web/app/components/app/configuration/toolbox/annotation/annotation-ctrl-btn/index.tsx

@@ -8,7 +8,7 @@ import { MessageCheckRemove, MessageFastPlus } from '@/app/components/base/icons
 import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication'
 import { Edit04 } from '@/app/components/base/icons/src/vender/line/general'
 import RemoveAnnotationConfirmModal from '@/app/components/app/annotation/remove-annotation-confirm-modal'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { addAnnotation, delAnnotation } from '@/service/annotation'
 import Toast from '@/app/components/base/toast'
 import { useProviderContext } from '@/context/provider-context'
@@ -99,8 +99,9 @@ const CacheCtrlBtn: FC<Props> = ({
           )
           : answer
             ? (
-              <TooltipPlus
-                popupContent={t('appDebug.feature.annotation.add') as string}
+              <Tooltip
+                popupContent={t('appDebug.feature.annotation.add')}
+                needsDelay
               >
                 <div
                   className='p-1 rounded-md hover:bg-[#EEF4FF] hover:text-[#444CE7] cursor-pointer'
@@ -108,12 +109,13 @@ const CacheCtrlBtn: FC<Props> = ({
                 >
                   <MessageFastPlus className='w-4 h-4' />
                 </div>
-              </TooltipPlus>
+              </Tooltip>
             )
             : null
         }
-        <TooltipPlus
-          popupContent={t('appDebug.feature.annotation.edit') as string}
+        <Tooltip
+          popupContent={t('appDebug.feature.annotation.edit')}
+          needsDelay
         >
           <div
             className='p-1 cursor-pointer rounded-md hover:bg-black/5'
@@ -121,7 +123,7 @@ const CacheCtrlBtn: FC<Props> = ({
           >
             <Edit04 className='w-4 h-4' />
           </div>
-        </TooltipPlus>
+        </Tooltip>
 
       </div>
       <RemoveAnnotationConfirmModal

+ 3 - 8
web/app/components/app/configuration/toolbox/annotation/config-param.tsx

@@ -4,13 +4,10 @@ import React from 'react'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
 import { usePathname, useRouter } from 'next/navigation'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import ConfigParamModal from './config-param-modal'
 import Panel from '@/app/components/app/configuration/base/feature-panel'
 import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { LinkExternal02, Settings04 } from '@/app/components/base/icons/src/vender/line/general'
 import ConfigContext from '@/context/debug-configuration'
 import type { EmbeddingModelConfig } from '@/app/components/app/annotation/type'
@@ -31,13 +28,11 @@ export const Item: FC<{ title: string; tooltip: string; children: JSX.Element }>
     <div>
       <div className='flex items-center space-x-1'>
         <div>{title}</div>
-        <TooltipPlus
+        <Tooltip
           popupContent={
             <div className='max-w-[200px] leading-[18px] text-[13px] font-medium text-gray-800'>{tooltip}</div>
           }
-        >
-          <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-        </TooltipPlus>
+        />
       </div>
       <div>{children}</div>
     </div>

+ 10 - 7
web/app/components/app/configuration/tools/index.tsx

@@ -7,11 +7,10 @@ import {
   RiAddLine,
   RiArrowDownSLine,
   RiDeleteBinLine,
-  RiQuestionLine,
 } from '@remixicon/react'
 import ConfigContext from '@/context/debug-configuration'
 import Switch from '@/app/components/base/switch'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { Tool03 } from '@/app/components/base/icons/src/vender/solid/general'
 import {
   Settings01,
@@ -107,9 +106,13 @@ const Tools = () => {
           <div className='mr-1 text-sm font-semibold text-gray-800'>
             {t('appDebug.feature.tools.title')}
           </div>
-          <TooltipPlus popupContent={<div className='max-w-[160px]'>{t('appDebug.feature.tools.tips')}</div>}>
-            <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-          </TooltipPlus>
+          <Tooltip
+            popupContent={
+              <div className='max-w-[160px]'>
+                {t('appDebug.feature.tools.tips')}
+              </div>
+            }
+          />
         </div>
         {
           !expanded && !!externalDataToolsConfig.length && (
@@ -143,7 +146,7 @@ const Tools = () => {
                       background={item.icon_background}
                     />
                     <div className='mr-2 text-[13px] font-medium text-gray-800'>{item.label}</div>
-                    <TooltipPlus
+                    <Tooltip
                       popupContent={copied ? t('appApi.copied') : `${item.variable}, ${t('appApi.copy')}`}
                     >
                       <div
@@ -155,7 +158,7 @@ const Tools = () => {
                       >
                         {item.variable}
                       </div>
-                    </TooltipPlus>
+                    </Tooltip>
                   </div>
                   <div
                     className='hidden group-hover:flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'

+ 9 - 13
web/app/components/app/create-app-modal/index.tsx

@@ -23,7 +23,7 @@ import AppIcon from '@/app/components/base/app-icon'
 import AppsFull from '@/app/components/billing/apps-full-in-dialog'
 import { AiText, ChatBot, CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication'
 import { Route } from '@/app/components/base/icons/src/vender/solid/mapsAndTravel'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
 import { getRedirection } from '@/utils/app-redirection'
 
@@ -100,8 +100,7 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
       <div className='py-2 px-8'>
         <div className='py-2 text-sm leading-[20px] font-medium text-gray-900'>{t('app.newApp.captionAppType')}</div>
         <div className='flex'>
-          <TooltipPlus
-            hideArrow
+          <Tooltip
             popupContent={
               <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.chatbotDescription')}</div>
             }
@@ -120,9 +119,8 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
               <ChatBot className='w-6 h-6 text-[#1570EF]' />
               <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.chatbot')}</div>
             </div>
-          </TooltipPlus>
-          <TooltipPlus
-            hideArrow
+          </Tooltip>
+          <Tooltip
             popupContent={
               <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'>
                 <div className='text-gray-700'>{t('app.newApp.completionDescription')}</div>
@@ -143,9 +141,8 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
               <AiText className='w-6 h-6 text-[#0E9384]' />
               <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.newApp.completeApp')}</div>
             </div>
-          </TooltipPlus>
-          <TooltipPlus
-            hideArrow
+          </Tooltip>
+          <Tooltip
             popupContent={
               <div className='max-w-[280px] leading-[18px] text-xs text-gray-700'>{t('app.newApp.agentDescription')}</div>
             }
@@ -164,9 +161,8 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
               <CuteRobote className='w-6 h-6 text-indigo-600' />
               <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.agent')}</div>
             </div>
-          </TooltipPlus>
-          <TooltipPlus
-            hideArrow
+          </Tooltip>
+          <Tooltip
             popupContent={
               <div className='flex flex-col max-w-[320px] leading-[18px] text-xs'>
                 <div className='text-gray-700'>{t('app.newApp.workflowDescription')}</div>
@@ -188,7 +184,7 @@ const CreateAppModal = ({ show, onSuccess, onClose }: CreateAppDialogProps) => {
               <div className='h-5 text-[13px] font-medium leading-[18px]'>{t('app.types.workflow')}</div>
               <span className='absolute top-[-3px] right-[-3px] px-1 rounded-[5px] bg-white border border-black/8 text-gray-500 text-[10px] leading-[18px] font-medium'>BETA</span>
             </div>
-          </TooltipPlus>
+          </Tooltip>
         </div>
       </div>
       {showChatBotType && (

+ 9 - 13
web/app/components/app/log/list.tsx

@@ -5,10 +5,9 @@ import useSWR from 'swr'
 import {
   HandThumbDownIcon,
   HandThumbUpIcon,
-  InformationCircleIcon,
   XMarkIcon,
 } from '@heroicons/react/24/outline'
-import { RiEditFill } from '@remixicon/react'
+import { RiEditFill, RiQuestionLine } from '@remixicon/react'
 import { get } from 'lodash-es'
 import InfiniteScroll from 'react-infinite-scroll-component'
 import dayjs from 'dayjs'
@@ -20,7 +19,6 @@ import { useTranslation } from 'react-i18next'
 import s from './style.module.css'
 import VarPanel from './var-panel'
 import cn from '@/utils/classnames'
-import { randomString } from '@/utils'
 import type { FeedbackFunc, Feedbacktype, IChatItem, SubmitAnnotationFunc } from '@/app/components/base/chat/chat/type'
 import type { Annotation, ChatConversationFullDetailResponse, ChatConversationGeneralDetail, ChatConversationsResponse, ChatMessage, ChatMessagesRequest, CompletionConversationFullDetailResponse, CompletionConversationGeneralDetail, CompletionConversationsResponse, LogAnnotation } from '@/models/log'
 import type { App } from '@/types/app'
@@ -28,7 +26,6 @@ import Loading from '@/app/components/base/loading'
 import Drawer from '@/app/components/base/drawer'
 import Popover from '@/app/components/base/popover'
 import Chat from '@/app/components/base/chat/chat'
-import Tooltip from '@/app/components/base/tooltip'
 import { ToastContext } from '@/app/components/base/toast'
 import { fetchChatConversationDetail, fetchChatMessages, fetchCompletionConversationDetail, updateLogMessageAnnotations, updateLogMessageFeedbacks } from '@/service/log'
 import { TONE_LIST } from '@/config'
@@ -42,7 +39,7 @@ import MessageLogModal from '@/app/components/base/message-log-modal'
 import { useStore as useAppStore } from '@/app/components/app/store'
 import { useAppContext } from '@/context/app-context'
 import useTimestamp from '@/hooks/use-timestamp'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { CopyIcon } from '@/app/components/base/copy-icon'
 
 dayjs.extend(utc)
@@ -346,11 +343,11 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
           <div className='text-gray-500 text-[10px] leading-[14px]'>{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}</div>
           {isChatMode && (
             <div className='flex items-center text-gray-700 text-[13px] leading-[18px]'>
-              <TooltipPlus
-                hideArrow
-                popupContent={detail.id}>
+              <Tooltip
+                popupContent={detail.id}
+              >
                 <div className='max-w-[105px] truncate'>{detail.id}</div>
-              </TooltipPlus>
+              </Tooltip>
               <CopyIcon content={detail.id} />
             </div>
           )}
@@ -380,7 +377,7 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
                 btnClassName='mr-4 !bg-gray-50 !py-1.5 !px-2.5 border-none font-normal'
                 btnElement={<>
                   <span className='text-[13px]'>{targetTone}</span>
-                  <InformationCircleIcon className='h-4 w-4 text-gray-800 ml-1.5' />
+                  <RiQuestionLine className='h-4 w-4 text-gray-800 ml-1.5' />
                 </>}
                 htmlContent={<div className='w-[280px]'>
                   <div className='flex justify-between py-2 px-4 font-medium text-sm text-gray-700'>
@@ -641,13 +638,12 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
   const renderTdValue = (value: string | number | null, isEmptyStyle: boolean, isHighlight = false, annotation?: LogAnnotation) => {
     return (
       <Tooltip
-        htmlContent={
+        popupContent={
           <span className='text-xs text-gray-500 inline-flex items-center'>
             <RiEditFill className='w-3 h-3 mr-1' />{`${t('appLog.detail.annotationTip', { user: annotation?.account?.name })} ${formatTime(annotation?.created_at || dayjs().unix(), 'MM-DD hh:mm A')}`}
           </span>
         }
-        className={(isHighlight && !isChatMode) ? '' : '!hidden'}
-        selector={`highlight-${randomString(16)}`}
+        popupClassName={(isHighlight && !isChatMode) ? '' : '!hidden'}
       >
         <div className={cn(isEmptyStyle ? 'text-gray-400' : 'text-gray-700', !isHighlight ? '' : 'bg-orange-100', 'text-sm overflow-hidden text-ellipsis whitespace-nowrap')}>
           {value || '-'}

+ 3 - 5
web/app/components/app/overview/appCard.tsx

@@ -195,8 +195,7 @@ function AppCard({
               )}
               {isApp && isCurrentWorkspaceManager && (
                 <Tooltip
-                  content={t('appOverview.overview.appInfo.regenerate') || ''}
-                  selector={`code-generate-${randomString(8)}`}
+                  popupContent={t('appOverview.overview.appInfo.regenerate') || ''}
                 >
                   <div
                     className="w-8 h-8 ml-0.5 cursor-pointer hover:bg-gray-200 rounded-lg"
@@ -227,11 +226,10 @@ function AppCard({
                 disabled={disabled}
               >
                 <Tooltip
-                  content={
+                  popupContent={
                     t('appOverview.overview.appInfo.preUseReminder') ?? ''
                   }
-                  selector={`op-btn-${randomString(16)}`}
-                  className={disabled ? 'mt-[-8px]' : '!hidden'}
+                  popupClassName={disabled ? 'mt-[-8px]' : '!hidden'}
                 >
                   <div className="flex flex-row items-center">
                     <op.opIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" />

+ 1 - 2
web/app/components/app/overview/embedded/index.tsx

@@ -153,8 +153,7 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, classNam
           </div>
           <div className="flex items-center justify-center gap-1 p-2 rounded-lg">
             <Tooltip
-              selector={'code-copy-feedback'}
-              content={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''}
+              popupContent={(isCopied[option] ? t(`${prefixEmbedded}.copied`) : t(`${prefixEmbedded}.copy`)) || ''}
             >
               <div className="w-8 h-8 rounded-lg cursor-pointer hover:bg-gray-100">
                 <div onClick={onClickCopy} className={`w-full h-full ${copyStyle.copyIcon} ${isCopied[option] ? copyStyle.copied : ''}`}></div>

+ 9 - 3
web/app/components/app/overview/settings/index.tsx

@@ -15,7 +15,7 @@ import type { AppDetailResponse } from '@/models/app'
 import type { AppIconType, AppSSO, Language } from '@/types/app'
 import { useToastContext } from '@/app/components/base/toast'
 import { languages } from '@/i18n/language'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import AppContext from '@/context/app-context'
 import type { AppIconSelection } from '@/app/components/base/app-icon-picker'
 import AppIconPicker from '@/app/components/base/app-icon-picker'
@@ -240,9 +240,15 @@ const SettingsModal: FC<ISettingsModalProps> = ({
           <p className='system-xs-medium text-gray-500'>{t(`${prefixSettings}.sso.label`)}</p>
           <div className='flex justify-between items-center'>
             <div className='font-medium system-sm-semibold flex-grow text-gray-900'>{t(`${prefixSettings}.sso.title`)}</div>
-            <TooltipPlus disabled={systemFeatures.sso_enforced_for_web} popupContent={<div className='w-[180px]'>{t(`${prefixSettings}.sso.tooltip`)}</div>}>
+            <Tooltip
+              disabled={systemFeatures.sso_enforced_for_web}
+              popupContent={
+                <div className='w-[180px]'>{t(`${prefixSettings}.sso.tooltip`)}</div>
+              }
+              asChild={false}
+            >
               <Switch disabled={!systemFeatures.sso_enforced_for_web} defaultValue={systemFeatures.sso_enforced_for_web && inputInfo.enable_sso} onChange={v => setInputInfo({ ...inputInfo, enable_sso: v })}></Switch>
-            </TooltipPlus>
+            </Tooltip>
           </div>
           <p className='body-xs-regular text-gray-500'>{t(`${prefixSettings}.sso.description`)}</p>
         </div>}

+ 7 - 7
web/app/components/base/audio-btn/index.tsx

@@ -83,25 +83,25 @@ const AudioBtn = ({
   }[audioState]
 
   return (
-    <div className={`${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}>
+    <div className={`inline-flex items-center justify-center ${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}>
       <Tooltip
-        selector={selector.current}
-        content={tooltipContent}
-        className='z-10'
+        popupContent={tooltipContent}
       >
         <button
           disabled={audioState === 'loading'}
-          className={`box-border p-0.5 flex items-center justify-center cursor-pointer ${isAudition || '!p-0 rounded-md bg-white'}`}
+          className={`box-border w-6 h-6 flex items-center justify-center cursor-pointer ${isAudition ? 'p-0.5' : 'p-0 rounded-md bg-white'}`}
           onClick={handleToggle}
         >
           {audioState === 'loading'
             ? (
-              <div className='w-6 h-6 rounded-md flex items-center justify-center p-2'>
+              <div className='w-full h-full rounded-md flex items-center justify-center'>
                 <Loading />
               </div>
             )
             : (
-              <div className={`w-6 h-6 rounded-md ${!isAudition ? 'w-4 h-4 hover:bg-gray-50' : 'hover:bg-gray-50'} ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div>
+              <div className={`w-full h-full rounded-md flex items-center justify-center ${!isAudition ? 'hover:bg-gray-50' : 'hover:bg-gray-50'}`}>
+                <div className={`w-4 h-4 ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div>
+              </div>
             )}
         </button>
       </Tooltip>

+ 13 - 7
web/app/components/base/chat/chat/answer/operation.tsx

@@ -17,7 +17,7 @@ import {
   ThumbsDown,
   ThumbsUp,
 } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import Log from '@/app/components/base/chat/chat/log'
 
 type OperationProps = {
@@ -162,28 +162,34 @@ const Operation: FC<OperationProps> = ({
         {
           config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && (
             <div className='hidden group-hover:flex ml-1 shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'>
-              <TooltipPlus popupContent={t('appDebug.operation.agree')}>
+              <Tooltip
+                popupContent={t('appDebug.operation.agree')}
+              >
                 <div
                   className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
                   onClick={() => handleFeedback('like')}
                 >
                   <ThumbsUp className='w-4 h-4' />
                 </div>
-              </TooltipPlus>
-              <TooltipPlus popupContent={t('appDebug.operation.disagree')}>
+              </Tooltip>
+              <Tooltip
+                popupContent={t('appDebug.operation.disagree')}
+              >
                 <div
                   className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
                   onClick={() => handleFeedback('dislike')}
                 >
                   <ThumbsDown className='w-4 h-4' />
                 </div>
-              </TooltipPlus>
+              </Tooltip>
             </div>
           )
         }
         {
           config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && (
-            <TooltipPlus popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}>
+            <Tooltip
+              popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
+            >
               <div
                 className={`
                   flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer
@@ -203,7 +209,7 @@ const Operation: FC<OperationProps> = ({
                   )
                 }
               </div>
-            </TooltipPlus>
+            </Tooltip>
           )
         }
       </div>

+ 3 - 3
web/app/components/base/chat/chat/chat-input.tsx

@@ -17,7 +17,7 @@ import { TransferMethod } from '../types'
 import { useChatWithHistoryContext } from '../chat-with-history/context'
 import type { Theme } from '../embedded-chatbot/theme/theme-context'
 import { CssTransform } from '../embedded-chatbot/theme/utils'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { ToastContext } from '@/app/components/base/toast'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 import VoiceInput from '@/app/components/base/voice-input'
@@ -220,7 +220,7 @@ const ChatInput: FC<ChatInputProps> = ({
             {isMobile
               ? sendBtn
               : (
-                <TooltipPlus
+                <Tooltip
                   popupContent={
                     <div>
                       <div>{t('common.operation.send')} Enter</div>
@@ -229,7 +229,7 @@ const ChatInput: FC<ChatInputProps> = ({
                   }
                 >
                   {sendBtn}
-                </TooltipPlus>
+                </Tooltip>
               )}
           </div>
           {

+ 1 - 3
web/app/components/base/chat/embedded-chatbot/header.tsx

@@ -41,9 +41,7 @@ const Header: FC<IHeaderProps> = ({
         </div>
       </div>
       <Tooltip
-        selector={'embed-scene-restart-button'}
-        htmlContent={t('share.chat.resetChat')}
-        position='top'
+        popupContent={t('share.chat.resetChat')}
       >
         <div className='flex cursor-pointer hover:rounded-lg hover:bg-black/5 w-8 h-8 items-center justify-center' onClick={() => {
           onCreateNewChat?.()

+ 1 - 3
web/app/components/base/chat/embedded-chatbot/index.tsx

@@ -88,9 +88,7 @@ const Chatbot = () => {
               {!isMobile && (
                 <div className='absolute top-2.5 right-3 z-20'>
                   <Tooltip
-                    selector={'embed-scene-restart-button'}
-                    htmlContent={t('share.chat.resetChat')}
-                    position='top'
+                    popupContent={t('share.chat.resetChat')}
                   >
                     <div className='p-1.5 bg-white border-[0.5px] border-gray-100 rounded-lg shadow-md cursor-pointer' onClick={handleNewConversation}>
                       <RiLoopLeftLine className="h-4 w-4 text-gray-500"/>

+ 2 - 6
web/app/components/base/copy-btn/index.tsx

@@ -1,10 +1,9 @@
 'use client'
-import { useRef, useState } from 'react'
+import { useState } from 'react'
 import { t } from 'i18next'
 import copy from 'copy-to-clipboard'
 import s from './style.module.css'
 import Tooltip from '@/app/components/base/tooltip'
-import { randomString } from '@/utils'
 
 type ICopyBtnProps = {
   value: string
@@ -18,14 +17,11 @@ const CopyBtn = ({
   isPlain,
 }: ICopyBtnProps) => {
   const [isCopied, setIsCopied] = useState(false)
-  const selector = useRef(`copy-tooltip-${randomString(4)}`)
 
   return (
     <div className={`${className}`}>
       <Tooltip
-        selector={selector.current}
-        content={(isCopied ? t('appApi.copied') : t('appApi.copy')) as string}
-        className='z-10'
+        popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))}
       >
         <div
           className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'}

+ 7 - 10
web/app/components/base/copy-feedback/index.tsx

@@ -3,19 +3,17 @@ import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { debounce } from 'lodash-es'
 import copy from 'copy-to-clipboard'
-import Tooltip from '../tooltip'
-import TooltipPlus from '../tooltip-plus'
 import copyStyle from './style.module.css'
+import Tooltip from '@/app/components/base/tooltip'
 
 type Props = {
   content: string
-  selectorId: string
   className?: string
 }
 
 const prefixEmbedded = 'appOverview.overview.appInfo.embedded'
 
-const CopyFeedback = ({ content, selectorId, className }: Props) => {
+const CopyFeedback = ({ content, className }: Props) => {
   const { t } = useTranslation()
   const [isCopied, setIsCopied] = useState<boolean>(false)
 
@@ -30,8 +28,7 @@ const CopyFeedback = ({ content, selectorId, className }: Props) => {
 
   return (
     <Tooltip
-      selector={`common-copy-feedback-${selectorId}`}
-      content={
+      popupContent={
         (isCopied
           ? t(`${prefixEmbedded}.copied`)
           : t(`${prefixEmbedded}.copy`)) || ''
@@ -41,10 +38,10 @@ const CopyFeedback = ({ content, selectorId, className }: Props) => {
         className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${
           className ?? ''
         }`}
-        onMouseLeave={onMouseLeave}
       >
         <div
           onClick={onClickCopy}
+          onMouseLeave={onMouseLeave}
           className={`w-full h-full ${copyStyle.copyIcon} ${
             isCopied ? copyStyle.copied : ''
           }`}
@@ -70,7 +67,7 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
   }, 100)
 
   return (
-    <TooltipPlus
+    <Tooltip
       popupContent={
         (isCopied
           ? t(`${prefixEmbedded}.copied`)
@@ -81,15 +78,15 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
         className={`w-8 h-8 cursor-pointer hover:bg-gray-100 rounded-lg ${
           className ?? ''
         }`}
-        onMouseLeave={onMouseLeave}
       >
         <div
           onClick={onClickCopy}
+          onMouseLeave={onMouseLeave}
           className={`w-full h-full ${copyStyle.copyIcon} ${
             isCopied ? copyStyle.copied : ''
           }`}
         ></div>
       </div>
-    </TooltipPlus>
+    </Tooltip>
   )
 }

+ 3 - 3
web/app/components/base/copy-icon/index.tsx

@@ -3,7 +3,7 @@ import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { debounce } from 'lodash-es'
 import copy from 'copy-to-clipboard'
-import TooltipPlus from '../tooltip-plus'
+import Tooltip from '../tooltip'
 import {
   Clipboard,
   ClipboardCheck,
@@ -29,7 +29,7 @@ export const CopyIcon = ({ content }: Props) => {
   }, 100)
 
   return (
-    <TooltipPlus
+    <Tooltip
       popupContent={
         (isCopied
           ? t(`${prefixEmbedded}.copied`)
@@ -46,7 +46,7 @@ export const CopyIcon = ({ content }: Props) => {
           )
         }
       </div>
-    </TooltipPlus>
+    </Tooltip>
   )
 }
 

+ 2 - 7
web/app/components/base/features/feature-panel/suggested-questions-after-answer/index.tsx

@@ -2,11 +2,8 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import { MessageSmileSquare } from '@/app/components/base/icons/src/vender/solid/communication'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 const SuggestedQuestionsAfterAnswer: FC = () => {
   const { t } = useTranslation()
@@ -18,9 +15,7 @@ const SuggestedQuestionsAfterAnswer: FC = () => {
       </div>
       <div className='shrink-0 mr-2 flex items-center whitespace-nowrap text-sm text-gray-800 font-semibold'>
         <div className='mr-2'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}</div>
-        <TooltipPlus popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}>
-          <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-        </TooltipPlus>
+        <Tooltip popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.description')}/>
       </div>
       <div className='grow'></div>
       <div className='text-xs text-gray-500'>{t('appDebug.feature.suggestedQuestionsAfterAnswer.resDes')}</div>

+ 10 - 10
web/app/components/base/features/feature-panel/text-to-speech/param-config-content.tsx

@@ -2,9 +2,6 @@
 import useSWR from 'swr'
 import produce from 'immer'
 import React, { Fragment } from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import { usePathname } from 'next/navigation'
 import { useTranslation } from 'react-i18next'
 import { Listbox, Transition } from '@headlessui/react'
@@ -74,13 +71,16 @@ const VoiceParamConfig = ({
             <div className='mb-2 flex items-center  space-x-1'>
               <div
                 className='leading-[18px] text-[13px] font-semibold text-gray-800'>{t('appDebug.voice.voiceSettings.language')}</div>
-              <Tooltip htmlContent={<div className='w-[180px]'>
-                {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => (
-                  <div key={item}>{item}</div>
-                ))}
-              </div>} selector='config-resolution-tooltip'>
-                <RiQuestionLine className='w-[14px] h-[14px] text-gray-400'/>
-              </Tooltip>
+              <Tooltip
+                popupContent={
+                  <div className='w-[180px]'>
+                    {t('appDebug.voice.voiceSettings.resolutionTooltip').split('\n').map(item => (
+                      <div key={item}>{item}
+                      </div>
+                    ))}
+                  </div>
+                }
+              />
             </div>
             <Listbox
               value={languageItem}

+ 3 - 3
web/app/components/base/image-uploader/image-list.tsx

@@ -8,7 +8,7 @@ import {
 import cn from '@/utils/classnames'
 import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import type { ImageFile } from '@/types/app'
 import { TransferMethod } from '@/types/app'
 import ImagePreview from '@/app/components/base/image-uploader/image-preview'
@@ -87,11 +87,11 @@ const ImageList: FC<ImageListProps> = ({
                 <RiLoader2Line className="animate-spin w-5 h-5 text-white" />
               )}
               {item.progress === -1 && (
-                <TooltipPlus
+                <Tooltip
                   popupContent={t('common.imageUploader.pasteImageLinkInvalid')}
                 >
                   <AlertTriangle className="w-4 h-4 text-[#DC6803]" />
-                </TooltipPlus>
+                </Tooltip>
               )}
             </div>
           )}

+ 4 - 8
web/app/components/base/param-item/index.tsx

@@ -1,10 +1,6 @@
 'use client'
 import type { FC } from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
-
-import Tooltip from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import Slider from '@/app/components/base/slider'
 import Switch from '@/app/components/base/switch'
 
@@ -40,9 +36,9 @@ const ParamItem: FC<Props> = ({ className, id, name, noTooltip, tip, step = 0.1,
           )}
           <span className="mx-1 text-gray-900 text-[13px] leading-[18px] font-medium">{name}</span>
           {!noTooltip && (
-            <Tooltip popupContent={<div className="w-[200px]">{tip}</div>}>
-              <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-            </Tooltip>
+            <Tooltip
+              popupContent={<div className="w-[200px]">{tip}</div>}
+            />
           )}
 
         </div>

+ 3 - 3
web/app/components/base/prompt-editor/plugins/workflow-variable-block/component.tsx

@@ -25,7 +25,7 @@ import { BubbleX, Env } from '@/app/components/base/icons/src/vender/line/others
 import { VarBlockIcon } from '@/app/components/workflow/block-icon'
 import { Line3 } from '@/app/components/base/icons/src/public/common'
 import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type WorkflowVariableBlockComponentProps = {
   nodeKey: string
@@ -113,9 +113,9 @@ const WorkflowVariableBlockComponent = ({
 
   if (!node && !isEnv && !isChatVar) {
     return (
-      <TooltipPlus popupContent={t('workflow.errorMsg.invalidVariable')}>
+      <Tooltip popupContent={t('workflow.errorMsg.invalidVariable')}>
         {Item}
-      </TooltipPlus>
+      </Tooltip>
     )
   }
 

+ 2 - 3
web/app/components/base/qrcode/index.tsx

@@ -2,8 +2,8 @@
 import React, { useEffect, useRef, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import QRCode from 'qrcode.react'
-import Tooltip from '../tooltip'
 import QrcodeStyle from './style.module.css'
+import Tooltip from '@/app/components/base/tooltip'
 
 type Props = {
   content: string
@@ -51,8 +51,7 @@ const ShareQRCode = ({ content, selectorId, className }: Props) => {
 
   return (
     <Tooltip
-      selector={`common-qrcode-show-${selectorId}`}
-      content={t(`${prefixEmbedded}`) || ''}
+      popupContent={t(`${prefixEmbedded}`) || ''}
     >
       <div
         className={`w-8 h-8 cursor-pointer rounded-lg ${className ?? ''}`}

+ 0 - 109
web/app/components/base/tooltip-plus/index.tsx

@@ -1,109 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React, { useEffect, useRef, useState } from 'react'
-import { useBoolean } from 'ahooks'
-import type { OffsetOptions, Placement } from '@floating-ui/react'
-import cn from '@/utils/classnames'
-import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
-export type TooltipProps = {
-  position?: Placement
-  triggerMethod?: 'hover' | 'click'
-  disabled?: boolean
-  popupContent: React.ReactNode
-  children: React.ReactNode
-  hideArrow?: boolean
-  popupClassName?: string
-  offset?: OffsetOptions
-  asChild?: boolean
-}
-
-const arrow = (
-  <svg className="absolute text-white h-2 w-full left-0 top-full" x="0px" y="0px" viewBox="0 0 255 255"><polygon className="fill-current" points="0,0 127.5,127.5 255,0"></polygon></svg>
-)
-
-const Tooltip: FC<TooltipProps> = ({
-  position = 'top',
-  triggerMethod = 'hover',
-  disabled = false,
-  popupContent,
-  children,
-  hideArrow,
-  popupClassName,
-  offset,
-  asChild,
-}) => {
-  const [open, setOpen] = useState(false)
-  const [isHoverPopup, {
-    setTrue: setHoverPopup,
-    setFalse: setNotHoverPopup,
-  }] = useBoolean(false)
-
-  const isHoverPopupRef = useRef(isHoverPopup)
-  useEffect(() => {
-    isHoverPopupRef.current = isHoverPopup
-  }, [isHoverPopup])
-
-  const [isHoverTrigger, {
-    setTrue: setHoverTrigger,
-    setFalse: setNotHoverTrigger,
-  }] = useBoolean(false)
-
-  const isHoverTriggerRef = useRef(isHoverTrigger)
-  useEffect(() => {
-    isHoverTriggerRef.current = isHoverTrigger
-  }, [isHoverTrigger])
-
-  const handleLeave = (isTrigger: boolean) => {
-    if (isTrigger)
-      setNotHoverTrigger()
-
-    else
-      setNotHoverPopup()
-
-    // give time to move to the popup
-    setTimeout(() => {
-      if (!isHoverPopupRef.current && !isHoverTriggerRef.current)
-        setOpen(false)
-    }, 500)
-  }
-
-  return (
-    <PortalToFollowElem
-      open={disabled ? false : open}
-      onOpenChange={setOpen}
-      placement={position}
-      offset={offset ?? 10}
-    >
-      <PortalToFollowElemTrigger
-        onClick={() => triggerMethod === 'click' && setOpen(v => !v)}
-        onMouseEnter={() => {
-          if (triggerMethod === 'hover') {
-            setHoverTrigger()
-            setOpen(true)
-          }
-        }}
-        onMouseLeave={() => triggerMethod === 'hover' && handleLeave(true)}
-        asChild={asChild}
-      >
-        {children}
-      </PortalToFollowElemTrigger>
-      <PortalToFollowElemContent
-        className="z-[9999]"
-      >
-        <div
-          className={cn(
-            'relative px-3 py-2 text-xs font-normal text-gray-700 bg-white rounded-md shadow-lg',
-            popupClassName,
-          )}
-          onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()}
-          onMouseLeave={() => triggerMethod === 'hover' && handleLeave(false)}
-        >
-          {popupContent}
-          {!hideArrow && arrow}
-        </div>
-      </PortalToFollowElemContent>
-    </PortalToFollowElem>
-  )
-}
-
-export default React.memo(Tooltip)

+ 98 - 38
web/app/components/base/tooltip/index.tsx

@@ -1,52 +1,112 @@
 'use client'
 import type { FC } from 'react'
-import React from 'react'
-import { Tooltip as ReactTooltip } from 'react-tooltip' // fixed version to 5.8.3 https://github.com/ReactTooltip/react-tooltip/issues/972
-import classNames from '@/utils/classnames'
-import 'react-tooltip/dist/react-tooltip.css'
-
-type TooltipProps = {
-  selector: string
-  content?: string
+import React, { useEffect, useRef, useState } from 'react'
+import { useBoolean } from 'ahooks'
+import type { OffsetOptions, Placement } from '@floating-ui/react'
+import { RiQuestionLine } from '@remixicon/react'
+import cn from '@/utils/classnames'
+import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem'
+export type TooltipProps = {
+  position?: Placement
+  triggerMethod?: 'hover' | 'click'
+  triggerClassName?: string
   disabled?: boolean
-  htmlContent?: React.ReactNode
-  className?: string // This should use !impornant to override the default styles eg: '!bg-white'
-  position?: 'top' | 'right' | 'bottom' | 'left'
-  clickable?: boolean
-  children: React.ReactNode
-  noArrow?: boolean
+  popupContent?: React.ReactNode
+  children?: React.ReactNode
+  popupClassName?: string
+  offset?: OffsetOptions
+  needsDelay?: boolean
+  asChild?: boolean
 }
 
 const Tooltip: FC<TooltipProps> = ({
-  selector,
-  content,
-  disabled,
   position = 'top',
+  triggerMethod = 'hover',
+  triggerClassName,
+  disabled = false,
+  popupContent,
   children,
-  htmlContent,
-  className,
-  clickable,
-  noArrow,
+  popupClassName,
+  offset,
+  asChild = true,
+  needsDelay = false,
 }) => {
+  const [open, setOpen] = useState(false)
+  const [isHoverPopup, {
+    setTrue: setHoverPopup,
+    setFalse: setNotHoverPopup,
+  }] = useBoolean(false)
+
+  const isHoverPopupRef = useRef(isHoverPopup)
+  useEffect(() => {
+    isHoverPopupRef.current = isHoverPopup
+  }, [isHoverPopup])
+
+  const [isHoverTrigger, {
+    setTrue: setHoverTrigger,
+    setFalse: setNotHoverTrigger,
+  }] = useBoolean(false)
+
+  const isHoverTriggerRef = useRef(isHoverTrigger)
+  useEffect(() => {
+    isHoverTriggerRef.current = isHoverTrigger
+  }, [isHoverTrigger])
+
+  const handleLeave = (isTrigger: boolean) => {
+    if (isTrigger)
+      setNotHoverTrigger()
+
+    else
+      setNotHoverPopup()
+
+    // give time to move to the popup
+    if (needsDelay) {
+      setTimeout(() => {
+        if (!isHoverPopupRef.current && !isHoverTriggerRef.current)
+          setOpen(false)
+      }, 500)
+    }
+    else {
+      setOpen(false)
+    }
+  }
+
   return (
-    <div className='tooltip-container'>
-      {React.cloneElement(children as React.ReactElement, {
-        'data-tooltip-id': selector,
-      })
-      }
-      <ReactTooltip
-        id={selector}
-        content={content}
-        className={classNames('!z-[999] !bg-white !text-xs !font-normal !text-gray-700 !shadow-lg !opacity-100', className)}
-        place={position}
-        clickable={clickable}
-        isOpen={disabled ? false : undefined}
-        noArrow={noArrow}
+    <PortalToFollowElem
+      open={disabled ? false : open}
+      onOpenChange={setOpen}
+      placement={position}
+      offset={offset ?? 8}
+    >
+      <PortalToFollowElemTrigger
+        onClick={() => triggerMethod === 'click' && setOpen(v => !v)}
+        onMouseEnter={() => {
+          if (triggerMethod === 'hover') {
+            setHoverTrigger()
+            setOpen(true)
+          }
+        }}
+        onMouseLeave={() => triggerMethod === 'hover' && handleLeave(true)}
+        asChild={asChild}
+      >
+        {children || <div className={triggerClassName || 'p-[1px] w-3.5 h-3.5 shrink-0'}><RiQuestionLine className='text-text-quaternary hover:text-text-tertiary w-full h-full' /></div>}
+      </PortalToFollowElemTrigger>
+      <PortalToFollowElemContent
+        className="z-[9999]"
       >
-        {htmlContent && htmlContent}
-      </ReactTooltip>
-    </div>
+        {popupContent && (<div
+          className={cn(
+            'relative px-3 py-2 text-xs font-normal text-gray-700 bg-white rounded-md shadow-lg break-words',
+            popupClassName,
+          )}
+          onMouseEnter={() => triggerMethod === 'hover' && setHoverPopup()}
+          onMouseLeave={() => triggerMethod === 'hover' && handleLeave(false)}
+        >
+          {popupContent}
+        </div>)}
+      </PortalToFollowElemContent>
+    </PortalToFollowElem>
   )
 }
 
-export default Tooltip
+export default React.memo(Tooltip)

+ 7 - 16
web/app/components/billing/pricing/plan-item.tsx

@@ -2,14 +2,11 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import { useContext } from 'use-context-selector'
 import { Plan } from '../type'
 import { ALL_PLANS, NUM_INFINITE, contactSalesUrl, contractSales, unAvailable } from '../config'
 import Toast from '../../base/toast'
-import TooltipPlus from '../../base/tooltip-plus'
+import Tooltip from '../../base/tooltip'
 import { PlanRange } from './select-plan-range'
 import cn from '@/utils/classnames'
 import { useAppContext } from '@/context/app-context'
@@ -30,13 +27,11 @@ const KeyValue = ({ label, value, tooltip }: { label: string; value: string | nu
       <div className='flex items-center text-gray-500 space-x-1'>
         <div>{label}</div>
         {tooltip && (
-          <TooltipPlus
+          <Tooltip
             popupContent={
               <div className='w-[200px]'>{tooltip}</div>
             }
-          >
-            <RiQuestionLine className='w-3 h-3 text-gray-400' />
-          </TooltipPlus>
+          />
         )}
       </div>
       <div className='mt-0.5 text-gray-900'>{value}</div>
@@ -136,25 +131,21 @@ const PlanItem: FC<Props> = ({
             <div className='mt-3.5 flex items-center space-x-1'>
               <span>+ </span>
               <div>{t('billing.plansCommon.supportItems.llmLoadingBalancing')}</div>
-              <TooltipPlus
+              <Tooltip
                 popupContent={
                   <div className='w-[200px]'>{t('billing.plansCommon.supportItems.llmLoadingBalancingTooltip')}</div>
                 }
-              >
-                <RiQuestionLine className='w-3 h-3 text-gray-400' />
-              </TooltipPlus>
+              />
             </div>
             <div className='mt-3.5 flex items-center space-x-1'>
               <div className='flex items-center'>
                 +
                 <div className='mr-0.5'>&nbsp;{t('billing.plansCommon.supportItems.ragAPIRequest')}</div>
-                <TooltipPlus
+                <Tooltip
                   popupContent={
                     <div className='w-[200px]'>{t('billing.plansCommon.ragAPIRequestTooltip')}</div>
                   }
-                >
-                  <RiQuestionLine className='w-3 h-3 text-gray-400' />
-                </TooltipPlus>
+                />
               </div>
               <div>{comingSoon}</div>
             </div>

+ 3 - 3
web/app/components/billing/priority-label/index.tsx

@@ -9,7 +9,7 @@ import {
   ZapFast,
   ZapNarrow,
 } from '@/app/components/base/icons/src/vender/solid/general'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 const PriorityLabel = () => {
   const { t } = useTranslation()
@@ -27,7 +27,7 @@ const PriorityLabel = () => {
   }, [plan])
 
   return (
-    <TooltipPlus popupContent={
+    <Tooltip popupContent={
       <div>
         <div className='mb-1 text-xs font-semibold text-gray-700'>{`${t('billing.plansCommon.documentProcessingPriority')}: ${t(`billing.plansCommon.priority.${priority}`)}`}</div>
         {
@@ -53,7 +53,7 @@ const PriorityLabel = () => {
         }
         {t(`billing.plansCommon.priority.${priority}`)}
       </span>
-    </TooltipPlus>
+    </Tooltip>
   )
 }
 

+ 7 - 6
web/app/components/billing/usage-info/index.tsx

@@ -2,7 +2,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import { InfoCircle } from '../../base/icons/src/vender/line/general'
 import ProgressBar from '../progress-bar'
 import { NUM_INFINITE } from '../config'
 import Tooltip from '@/app/components/base/tooltip'
@@ -48,11 +47,13 @@ const UsageInfo: FC<Props> = ({
           <Icon className='w-4 h-4 text-gray-700' />
           <div className='mx-1 leading-5 text-sm font-medium text-gray-700'>{name}</div>
           {tooltip && (
-            <Tooltip htmlContent={<div className='w-[180px]'>
-              {tooltip}
-            </div>} selector='config-var-tooltip'>
-              <InfoCircle className='w-[14px] h-[14px] text-gray-400' />
-            </Tooltip>
+            <Tooltip
+              popupContent={
+                <div className='w-[180px]'>
+                  {tooltip}
+                </div>
+              }
+            />
           )}
         </div>
         <div className='flex items-center leading-[18px] text-[13px] font-normal'>

+ 9 - 11
web/app/components/datasets/common/retrieval-param-config/index.tsx

@@ -2,15 +2,13 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
+
 import cn from '@/utils/classnames'
 import TopKItem from '@/app/components/base/param-item/top-k-item'
 import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
 import { RETRIEVE_METHOD } from '@/types/app'
 import Switch from '@/app/components/base/switch'
-import Tooltip from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import type { RetrievalConfig } from '@/types/app'
 import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
 import { useModelListAndDefaultModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
@@ -114,9 +112,11 @@ const RetrievalParamConfig: FC<Props> = ({
             )}
             <div className='flex items-center'>
               <span className='mr-0.5'>{t('common.modelProvider.rerankModel.key')}</span>
-              <Tooltip popupContent={<div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>}>
-                <RiQuestionLine className='w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+              <Tooltip
+                popupContent={
+                  <div className="w-[200px]">{t('common.modelProvider.rerankModel.tip')}</div>
+                }
+              />
             </div>
           </div>
           <ModelSelector
@@ -191,10 +191,8 @@ const RetrievalParamConfig: FC<Props> = ({
                     <div className='truncate'>{option.label}</div>
                     <Tooltip
                       popupContent={<div className='w-[200px]'>{option.tips}</div>}
-                      hideArrow
-                    >
-                      <RiQuestionLine className='ml-0.5 w-3.5 h-4.5 text-text-quaternary' />
-                    </Tooltip>
+                      triggerClassName='ml-0.5 w-3.5 h-4.5'
+                    />
                   </div>
                 ))
               }

+ 9 - 7
web/app/components/datasets/create/embedding-process/index.tsx

@@ -22,7 +22,7 @@ import { Plan } from '@/app/components/billing/type'
 import { ZapFast } from '@/app/components/base/icons/src/vender/solid/general'
 import UpgradeBtn from '@/app/components/billing/upgrade-btn'
 import { useProviderContext } from '@/context/provider-context'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { sleep } from '@/utils'
 
 type Props = {
@@ -259,16 +259,18 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
                 <div className={s.percent}>{`${getSourcePercent(indexingStatusDetail)}%`}</div>
               )}
               {indexingStatusDetail.indexing_status === 'error' && indexingStatusDetail.error && (
-                <TooltipPlus popupContent={(
-                  <div className='max-w-[400px]'>
-                    {indexingStatusDetail.error}
-                  </div>
-                )}>
+                <Tooltip
+                  popupContent={(
+                    <div className='max-w-[400px]'>
+                      {indexingStatusDetail.error}
+                    </div>
+                  )}
+                >
                   <div className={cn(s.percent, s.error, 'flex items-center')}>
                     Error
                     <RiErrorWarningFill className='ml-1 w-4 h-4' />
                   </div>
-                </TooltipPlus>
+                </Tooltip>
               )}
               {indexingStatusDetail.indexing_status === 'error' && !indexingStatusDetail.error && (
                 <div className={cn(s.percent, s.error, 'flex items-center')}>

+ 8 - 10
web/app/components/datasets/create/step-two/index.tsx

@@ -7,7 +7,6 @@ import { XMarkIcon } from '@heroicons/react/20/solid'
 import { RocketLaunchIcon } from '@heroicons/react/24/outline'
 import {
   RiCloseLine,
-  RiQuestionLine,
 } from '@remixicon/react'
 import Link from 'next/link'
 import { groupBy } from 'lodash-es'
@@ -43,7 +42,6 @@ import { IS_CE_EDITION } from '@/config'
 import { RETRIEVE_METHOD } from '@/types/app'
 import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 import Tooltip from '@/app/components/base/tooltip'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
 import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
 import { LanguagesSupported } from '@/i18n/language'
 import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
@@ -556,7 +554,7 @@ const StepTwo = ({
               className='border-[0.5px] !h-8 hover:outline hover:outline-[0.5px] hover:outline-gray-300 text-gray-700 font-medium bg-white shadow-[0px_1px_2px_0px_rgba(16,24,40,0.05)]'
               onClick={setShowPreview}
             >
-              <Tooltip selector='data-preview-toggle'>
+              <Tooltip>
                 <div className="flex flex-row items-center">
                   <RocketLaunchIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" />
                   <span className="text-[13px]">{t('datasetCreation.stepTwo.previewTitleButton')}</span>
@@ -628,13 +626,13 @@ const StepTwo = ({
                     <div className='w-full'>
                       <div className={s.label}>
                         {t('datasetCreation.stepTwo.overlap')}
-                        <TooltipPlus popupContent={
-                          <div className='max-w-[200px]'>
-                            {t('datasetCreation.stepTwo.overlapTip')}
-                          </div>
-                        }>
-                          <RiQuestionLine className='ml-1 w-3.5 h-3.5 text-gray-400' />
-                        </TooltipPlus>
+                        <Tooltip
+                          popupContent={
+                            <div className='max-w-[200px]'>
+                              {t('datasetCreation.stepTwo.overlapTip')}
+                            </div>
+                          }
+                        />
                       </div>
                       <input
                         type="number"

+ 7 - 9
web/app/components/datasets/create/website/firecrawl/base/field.tsx

@@ -1,12 +1,9 @@
 'use client'
 import type { FC } from 'react'
 import React from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import Input from './input'
 import cn from '@/utils/classnames'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type Props = {
   className?: string
@@ -37,11 +34,12 @@ const Field: FC<Props> = ({
         <div className={cn(labelClassName, 'flex items-center h-[18px] text-[13px] font-medium text-gray-900')}>{label} </div>
         {isRequired && <span className='ml-0.5 text-xs font-semibold text-[#D92D20]'>*</span>}
         {tooltip && (
-          <TooltipPlus popupContent={
-            <div className='w-[200px]'>{tooltip}</div>
-          }>
-            <RiQuestionLine className='relative top-[3px] w-3 h-3 ml-1 text-gray-500' />
-          </TooltipPlus>
+          <Tooltip
+            popupContent={
+              <div className='w-[200px]'>{tooltip}</div>
+            }
+            popupClassName='relative top-[3px] w-3 h-3 ml-1'
+          />
         )}
       </div>
       <Input

+ 3 - 1
web/app/components/datasets/documents/detail/metadata/index.tsx

@@ -102,7 +102,9 @@ const IconButton: FC<{
   const metadataMap = useMetadataMap()
 
   return (
-    <Tooltip content={metadataMap[type].text} selector={`doc-metadata-${type}`}>
+    <Tooltip
+      popupContent={metadataMap[type].text}
+    >
       <button className={cn(s.iconWrapper, 'group', isChecked ? s.iconCheck : '')}>
         <TypeIcon
           iconName={metadataMap[type].iconName || ''}

+ 15 - 13
web/app/components/datasets/documents/list.tsx

@@ -7,14 +7,12 @@ import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline'
 import { pick } from 'lodash-es'
 import {
   RiMoreFill,
-  RiQuestionLine,
 } from '@remixicon/react'
 import { useContext } from 'use-context-selector'
 import { useRouter } from 'next/navigation'
 import { useTranslation } from 'react-i18next'
 import dayjs from 'dayjs'
 import { Edit03 } from '../../base/icons/src/vender/solid/general'
-import TooltipPlus from '../../base/tooltip-plus'
 import { Globe01 } from '../../base/icons/src/vender/line/mapsAndTravel'
 import s from './style.module.css'
 import RenameModal from './rename-modal'
@@ -94,13 +92,11 @@ export const StatusItem: FC<{
     {
       errorMessage && (
         <Tooltip
-          selector='dataset-document-detail-item-status'
-          htmlContent={
+          popupContent={
             <div className='max-w-[260px] break-all'>{errorMessage}</div>
           }
-        >
-          <RiQuestionLine className='ml-1 w-[14px] h-[14px] text-gray-700' />
-        </Tooltip>
+          triggerClassName='ml-1 w-4 h-4'
+        />
       )
     }
   </div>
@@ -201,7 +197,11 @@ export const OperationAction: FC<{
     {isListScene && embeddingAvailable && (
       <>
         {archived
-          ? <Tooltip selector={`list-switch-${id}`} content={t('datasetDocuments.list.action.enableWarning') as string} className='!font-semibold'>
+          ? <Tooltip
+            popupContent={t('datasetDocuments.list.action.enableWarning')}
+            popupClassName='!font-semibold'
+            needsDelay
+          >
             <div>
               <Switch defaultValue={false} onChange={() => { }} disabled={true} size='md' />
             </div>
@@ -221,9 +221,9 @@ export const OperationAction: FC<{
                   {!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')}
                 </span>
                 <Tooltip
-                  selector={`detail-switch-${id}`}
-                  content={t('datasetDocuments.list.action.enableWarning') as string}
-                  className='!font-semibold'
+                  popupContent={t('datasetDocuments.list.action.enableWarning')}
+                  popupClassName='!font-semibold'
+                  needsDelay
                   disabled={!archived}
                 >
                   <div>
@@ -426,7 +426,9 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
                     }
                   </span>
                   <div className='group-hover:flex hidden'>
-                    <TooltipPlus popupContent={t('datasetDocuments.list.table.rename')}>
+                    <Tooltip
+                      popupContent={t('datasetDocuments.list.table.rename')}
+                    >
                       <div
                         className='p-1 rounded-md cursor-pointer hover:bg-black/5'
                         onClick={(e) => {
@@ -436,7 +438,7 @@ const DocumentList: FC<IDocumentListProps> = ({ embeddingAvailable, documents =
                       >
                         <Edit03 className='w-4 h-4 text-gray-500' />
                       </div>
-                    </TooltipPlus>
+                    </Tooltip>
                   </div>
                 </div>
 

+ 3 - 5
web/app/components/datasets/hit-testing/textarea.tsx

@@ -1,9 +1,9 @@
 import { useTranslation } from 'react-i18next'
 import Button from '../../base/button'
 import Tag from '../../base/tag'
-import Tooltip from '../../base/tooltip'
 import { getIcon } from '../common/retrieval-method-info'
 import s from './style.module.css'
+import Tooltip from '@/app/components/base/tooltip'
 import cn from '@/utils/classnames'
 import type { HitTestingResponse } from '@/models/datasets'
 import { hitTesting } from '@/service/datasets'
@@ -74,8 +74,7 @@ const TextAreaWithButton = ({
               {t('datasetHitTesting.input.title')}
             </span>
             <Tooltip
-              selector={'change-retrieval-method'}
-              htmlContent={t('dataset.retrieval.changeRetrievalMethod')}
+              popupContent={t('dataset.retrieval.changeRetrievalMethod')}
             >
               <div
                 onClick={onClickRetrievalMethod}
@@ -99,8 +98,7 @@ const TextAreaWithButton = ({
             {text?.length > 200
               ? (
                 <Tooltip
-                  content={t('datasetHitTesting.input.countWarning') as string}
-                  selector="hit-testing-warning"
+                  popupContent={t('datasetHitTesting.input.countWarning')}
                 >
                   <div>
                     <Tag color="red" className="!text-red-600">

+ 14 - 17
web/app/components/develop/secret-key/input-copy.tsx

@@ -1,9 +1,8 @@
 'use client'
-import React, { useEffect, useRef, useState } from 'react'
+import React, { useEffect, useState } from 'react'
 import copy from 'copy-to-clipboard'
 import { t } from 'i18next'
 import s from './style.module.css'
-import { randomString } from '@/utils'
 import Tooltip from '@/app/components/base/tooltip'
 
 type IInputCopyProps = {
@@ -21,8 +20,6 @@ const InputCopy = ({
 }: IInputCopyProps) => {
   const [isCopied, setIsCopied] = useState(false)
 
-  const selector = useRef(`input-tooltip-${randomString(4)}`)
-
   useEffect(() => {
     if (isCopied) {
       const timeout = setTimeout(() => {
@@ -40,22 +37,22 @@ const InputCopy = ({
       <div className="flex items-center flex-grow h-5">
         {children}
         <div className='flex-grow bg-gray-50 text-[13px] relative h-full'>
-          <Tooltip
-            selector={selector.current}
-            content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
-            className='z-10'
-          >
-            <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => {
-              copy(value)
-              setIsCopied(true)
-            }}>{value}</div>
-          </Tooltip>
+          <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => {
+            copy(value)
+            setIsCopied(true)
+          }}>
+            <Tooltip
+              popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
+              position='bottom'
+            >
+              {value}
+            </Tooltip>
+          </div>
         </div>
         <div className="flex-shrink-0 h-4 bg-gray-200 border" />
         <Tooltip
-          selector={selector.current}
-          content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
-          className='z-10'
+          popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
+          position='bottom'
         >
           <div className="px-0.5 flex-shrink-0">
             <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => {

+ 2 - 3
web/app/components/develop/secret-key/secret-key-modal.tsx

@@ -118,9 +118,8 @@ const SecretKeyModal = ({
                   <div className='flex-shrink-0 px-3 truncate w-[200px]'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div>
                   <div className='flex flex-grow px-3'>
                     <Tooltip
-                      selector={`key-${api.token}`}
-                      content={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
-                      className='z-10'
+                      popupContent={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
+                      popupClassName='mr-1'
                     >
                       <div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-gray-100 ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => {
                         // setIsCopied(true)

+ 4 - 4
web/app/components/header/account-setting/members-page/invited-modal/index.tsx

@@ -1,5 +1,6 @@
 import { CheckCircleIcon } from '@heroicons/react/24/solid'
-import { QuestionMarkCircleIcon, XMarkIcon } from '@heroicons/react/24/outline'
+import { XMarkIcon } from '@heroicons/react/24/outline'
+import { RiQuestionLine } from '@remixicon/react'
 import { useTranslation } from 'react-i18next'
 import { useMemo } from 'react'
 import InvitationLink from './invitation-link'
@@ -64,12 +65,11 @@ const InvitedModal = ({
                       failedInvationResults.map(item =>
                         <div key={item.email} className='flex justify-center border border-red-300 rounded-md px-1 bg-orange-50'>
                           <Tooltip
-                            selector={`invitation-tag-${item.email}`}
-                            htmlContent={item.message}
+                            popupContent={item.message}
                           >
                             <div className='flex justify-center items-center text-sm gap-1'>
                               {item.email}
-                              <QuestionMarkCircleIcon className='w-4 h-4 text-red-300' />
+                              <RiQuestionLine className='w-4 h-4 text-red-300' />
                             </div>
                           </Tooltip>
                         </div>,

+ 2 - 6
web/app/components/header/account-setting/members-page/invited-modal/invitation-link.tsx

@@ -39,18 +39,14 @@ const InvitationLink = ({
       <div className="flex items-center flex-grow h-5">
         <div className='flex-grow bg-gray-100 text-[13px] relative h-full'>
           <Tooltip
-            selector={selector.current}
-            content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
-            className='z-10'
+            popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
           >
             <div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={copyHandle}>{value.url}</div>
           </Tooltip>
         </div>
         <div className="flex-shrink-0 h-4 bg-gray-200 border" />
         <Tooltip
-          selector={selector.current}
-          content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
-          className='z-10'
+          popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
         >
           <div className="px-0.5 flex-shrink-0">
             <div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={copyHandle}>

+ 2 - 4
web/app/components/header/account-setting/model-provider-page/model-modal/Form.tsx

@@ -1,8 +1,6 @@
 import { Fragment, useState } from 'react'
 import type { FC } from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
+import { RiQuestionLine } from '@remixicon/react'
 import { ValidatingTip } from '../../key-validator/ValidateStatus'
 import type {
   CredentialFormSchema,
@@ -18,7 +16,7 @@ import { useLanguage } from '../hooks'
 import Input from './Input'
 import cn from '@/utils/classnames'
 import { SimpleSelect } from '@/app/components/base/select'
-import Tooltip from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import Radio from '@/app/components/base/radio'
 type FormProps = {
   className?: string

+ 5 - 8
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx

@@ -1,8 +1,5 @@
 import type { FC } from 'react'
 import { useEffect, useRef, useState } from 'react'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import type { ModelParameterRule } from '../declarations'
 import { useLanguage } from '../hooks'
 import { isNullOrUndefined } from '../utils'
@@ -241,18 +238,18 @@ const ParameterItem: FC<ParameterItemProps> = ({
           {
             parameterRule.help && (
               <Tooltip
-                selector={`model-parameter-rule-${parameterRule.name}`}
-                htmlContent={(
+                popupContent={(
                   <div className='w-[200px] whitespace-pre-wrap'>{parameterRule.help[language] || parameterRule.help.en_US}</div>
                 )}
-              >
-                <RiQuestionLine className='mr-1.5 w-3.5 h-3.5 text-gray-400' />
-              </Tooltip>
+                popupClassName='mr-1'
+                triggerClassName='mr-1 w-4 h-4 shrink-0'
+              />
             )
           }
           {
             !parameterRule.required && parameterRule.name !== 'stop' && (
               <Switch
+                className='mr-1'
                 defaultValue={!isNullOrUndefined(value)}
                 onChange={handleSwitch}
                 size='md'

+ 3 - 3
web/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger.tsx

@@ -14,7 +14,7 @@ import cn from '@/utils/classnames'
 import { useProviderContext } from '@/context/provider-context'
 import { SlidersH } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 export type TriggerProps = {
   open?: boolean
@@ -90,7 +90,7 @@ const Trigger: FC<TriggerProps> = ({
       {
         disabled
           ? (
-            <TooltipPlus
+            <Tooltip
               popupContent={
                 hasDeprecated
                   ? t('common.modelProvider.deprecated')
@@ -100,7 +100,7 @@ const Trigger: FC<TriggerProps> = ({
               }
             >
               <AlertTriangle className='w-4 h-4 text-[#F79009]' />
-            </TooltipPlus>
+            </Tooltip>
           )
           : (
             <SlidersH className={cn(!isInWorkflow ? 'text-indigo-600' : 'text-gray-500', 'shrink-0 w-4 h-4')} />

+ 3 - 3
web/app/components/header/account-setting/model-provider-page/model-selector/deprecated-model-trigger.tsx

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
 import ModelIcon from '../model-icon'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
 import { useProviderContext } from '@/context/provider-context'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type ModelTriggerProps = {
   modelName: string
@@ -35,9 +35,9 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
         {modelName}
       </div>
       <div className='shrink-0 flex items-center justify-center w-4 h-4'>
-        <TooltipPlus popupContent={t('common.modelProvider.deprecated')}>
+        <Tooltip popupContent={t('common.modelProvider.deprecated')}>
           <AlertTriangle className='w-4 h-4 text-[#F79009]' />
-        </TooltipPlus>
+        </Tooltip>
       </div>
     </div>
   )

+ 14 - 12
web/app/components/header/account-setting/model-provider-page/model-selector/feature-icon.tsx

@@ -11,7 +11,7 @@ import {
   // MagicWand,
   // Robot,
 } from '@/app/components/base/icons/src/vender/solid/mediaAndDevices'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type FeatureIconProps = {
   feature: ModelFeatureEnum
@@ -25,49 +25,51 @@ const FeatureIcon: FC<FeatureIconProps> = ({
 
   // if (feature === ModelFeatureEnum.agentThought) {
   //   return (
-  //     <TooltipPlus
+  //     <Tooltip
   //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.agentThought })}
   //     >
   //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
   //         <Robot className='w-3 h-3' />
   //       </ModelBadge>
-  //     </TooltipPlus>
+  //     </Tooltip>
   //   )
   // }
 
   // if (feature === ModelFeatureEnum.toolCall) {
   //   return (
-  //     <TooltipPlus
+  //     <Tooltip
   //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.toolCall })}
   //     >
   //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
   //         <MagicWand className='w-3 h-3' />
   //       </ModelBadge>
-  //     </TooltipPlus>
+  //     </Tooltip>
   //   )
   // }
 
   // if (feature === ModelFeatureEnum.multiToolCall) {
   //   return (
-  //     <TooltipPlus
+  //     <Tooltip
   //       popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.multiToolCall })}
   //     >
   //       <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
   //         <MagicBox className='w-3 h-3' />
   //       </ModelBadge>
-  //     </TooltipPlus>
+  //     </Tooltip>
   //   )
   // }
 
   if (feature === ModelFeatureEnum.vision) {
     return (
-      <TooltipPlus
+      <Tooltip
         popupContent={t('common.modelProvider.featureSupported', { feature: ModelFeatureTextEnum.vision })}
       >
-        <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
-          <MagicEyes className='w-3 h-3' />
-        </ModelBadge>
-      </TooltipPlus>
+        <div className='inline-block cursor-help'>
+          <ModelBadge className={`mr-0.5 !px-0 w-[18px] justify-center text-gray-500 ${className}`}>
+            <MagicEyes className='w-3 h-3' />
+          </ModelBadge>
+        </div>
+      </Tooltip>
     )
   }
 

+ 3 - 3
web/app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx

@@ -12,7 +12,7 @@ import { useLanguage } from '../hooks'
 import ModelIcon from '../model-icon'
 import ModelName from '../model-name'
 import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type ModelTriggerProps = {
   open: boolean
@@ -56,9 +56,9 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
           {
             model.status !== ModelStatusEnum.active
               ? (
-                <TooltipPlus popupContent={MODEL_STATUS_TEXT[model.status][language]}>
+                <Tooltip popupContent={MODEL_STATUS_TEXT[model.status][language]}>
                   <AlertTriangle className='w-4 h-4 text-[#F79009]' />
-                </TooltipPlus>
+                </Tooltip>
               )
               : (
                 <RiArrowDownSLine

+ 1 - 2
web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx

@@ -70,9 +70,8 @@ const PopupItem: FC<PopupItemProps> = ({
       {
         model.models.map(modelItem => (
           <Tooltip
-            selector={`${modelItem.model}-${modelItem.status}`}
             key={modelItem.model}
-            content={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined}
+            popupContent={modelItem.status !== ModelStatusEnum.active ? MODEL_STATUS_TEXT[modelItem.status][language] : undefined}
             position='right'
           >
             <div

+ 3 - 3
web/app/components/header/account-setting/model-provider-page/provider-added-card/cooldown-timer.tsx

@@ -2,7 +2,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useLatest } from 'ahooks'
 import SimplePieChart from '@/app/components/base/simple-pie-chart'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 export type CooldownTimerProps = {
   secondsRemaining?: number
@@ -54,9 +54,9 @@ const CooldownTimer = ({ secondsRemaining, onFinish }: CooldownTimerProps) => {
 
   return displayTime
     ? (
-      <TooltipPlus popupContent={t('common.modelProvider.apiKeyRateLimit', { seconds: displayTime })}>
+      <Tooltip popupContent={t('common.modelProvider.apiKeyRateLimit', { seconds: displayTime })}>
         <SimplePieChart percentage={Math.round(displayTime / 60 * 100)} className='w-3 h-3' />
-      </TooltipPlus>
+      </Tooltip>
     )
     : null
 }

+ 8 - 3
web/app/components/header/account-setting/model-provider-page/provider-added-card/model-list-item.tsx

@@ -11,7 +11,7 @@ import Button from '@/app/components/base/button'
 import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
 import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
 import Switch from '@/app/components/base/switch'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { useProviderContext, useProviderContextSelector } from '@/context/provider-context'
 import { disableModel, enableModel } from '@/service/common'
 import { Plan } from '@/app/components/billing/type'
@@ -99,9 +99,14 @@ const ModelListItem = ({ model, provider, isConfigurable, onConfig, onModifyLoad
         {
           model.deprecated
             ? (
-              <TooltipPlus popupContent={<span className='font-semibold'>{t('common.modelProvider.modelHasBeenDeprecated')}</span>} offset={{ mainAxis: 4 }}>
+              <Tooltip
+                popupContent={
+                  <span className='font-semibold'>{t('common.modelProvider.modelHasBeenDeprecated')}</span>} offset={{ mainAxis: 4 }
+                }
+                needsDelay
+              >
                 <Switch defaultValue={false} disabled size='md' />
-              </TooltipPlus>
+              </Tooltip>
             )
             : (isCurrentWorkspaceManager && (
               <Switch

+ 8 - 7
web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx

@@ -3,13 +3,12 @@ import { useCallback } from 'react'
 import { useTranslation } from 'react-i18next'
 import {
   RiDeleteBinLine,
-  RiQuestionLine,
 } from '@remixicon/react'
 import type { ConfigurationMethodEnum, CustomConfigurationModelFixedFields, ModelLoadBalancingConfig, ModelLoadBalancingConfigEntry, ModelProvider } from '../declarations'
 import Indicator from '../../../indicator'
 import CooldownTimer from './cooldown-timer'
 import classNames from '@/utils/classnames'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import Switch from '@/app/components/base/switch'
 import { Balance } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
 import { Edit02, Plus02 } from '@/app/components/base/icons/src/vender/line/general'
@@ -160,9 +159,11 @@ const ModelLoadBalancingConfigs = ({
           <div className='grow'>
             <div className='flex items-center gap-1 text-sm'>
               {t('common.modelProvider.loadBalancing')}
-              <TooltipPlus popupContent={t('common.modelProvider.loadBalancingInfo')} popupClassName='max-w-[300px]'>
-                <RiQuestionLine className='w-3 h-3 text-gray-400' />
-              </TooltipPlus>
+              <Tooltip
+                popupContent={t('common.modelProvider.loadBalancingInfo')}
+                popupClassName='max-w-[300px]'
+                triggerClassName='w-3 h-3'
+              />
             </div>
             <div className='text-xs text-gray-500'>{t('common.modelProvider.loadBalancingDescription')}</div>
           </div>
@@ -191,9 +192,9 @@ const ModelLoadBalancingConfigs = ({
                           <CooldownTimer secondsRemaining={config.ttl} onFinish={() => clearCountdown(index)} />
                         )
                         : (
-                          <TooltipPlus popupContent={t('common.modelProvider.apiKeyStatusNormal')}>
+                          <Tooltip popupContent={t('common.modelProvider.apiKeyStatusNormal')}>
                             <Indicator color='green' />
-                          </TooltipPlus>
+                          </Tooltip>
                         )}
                     </div>
                     <div className='text-[13px] mr-1'>

+ 1 - 2
web/app/components/header/account-setting/model-provider-page/provider-added-card/priority-use-tip.tsx

@@ -7,8 +7,7 @@ const PriorityUseTip = () => {
 
   return (
     <Tooltip
-      selector='provider-quota-credential-priority-using'
-      content={t('common.modelProvider.priorityUsing') || ''}
+      popupContent={t('common.modelProvider.priorityUsing') || ''}
     >
       <div className='absolute -right-[5px] -top-[5px] bg-indigo-50 rounded-[5px] border-[0.5px] border-indigo-100 cursor-pointer'>
         <ChevronDownDouble className='rotate-180 w-3 h-3 text-indigo-600' />

+ 4 - 6
web/app/components/header/account-setting/model-provider-page/provider-added-card/quota-panel.tsx

@@ -10,8 +10,7 @@ import {
   MODEL_PROVIDER_QUOTA_GET_PAID,
 } from '../utils'
 import PriorityUseTip from './priority-use-tip'
-import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { formatNumber } from '@/utils/format'
 
 type QuotaPanelProps = {
@@ -32,13 +31,12 @@ const QuotaPanel: FC<QuotaPanelProps> = ({
     <div className='group relative shrink-0 min-w-[112px] px-3 py-2 rounded-lg bg-white/[0.3] border-[0.5px] border-black/5'>
       <div className='flex items-center mb-2 h-4 text-xs font-medium text-gray-500'>
         {t('common.modelProvider.quota')}
-        <TooltipPlus popupContent={
+        <Tooltip popupContent={
           openaiOrAnthropic
             ? t('common.modelProvider.card.tip')
             : t('common.modelProvider.quotaTip')
-        }>
-          <InfoCircle className='ml-0.5 w-3 h-3 text-gray-400' />
-        </TooltipPlus>
+        }
+        />
       </div>
       {
         currentQuota && (

+ 33 - 33
web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx

@@ -1,9 +1,6 @@
 import type { FC } from 'react'
 import { useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import ModelSelector from '../model-selector'
 import {
   useModelList,
@@ -146,13 +143,13 @@ const SystemModel: FC<SystemModelSelectorProps> = ({
             <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
               {t('common.modelProvider.systemReasoningModel.key')}
               <Tooltip
-                selector='model-page-system-reasoning-model-tip'
-                htmlContent={
-                  <div className='w-[261px] text-gray-500'>{t('common.modelProvider.systemReasoningModel.tip')}</div>
+                popupContent={
+                  <div className='w-[261px] text-gray-500'>
+                    {t('common.modelProvider.systemReasoningModel.tip')}
+                  </div>
                 }
-              >
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+                triggerClassName='ml-0.5'
+              />
             </div>
             <div>
               <ModelSelector
@@ -166,13 +163,14 @@ const SystemModel: FC<SystemModelSelectorProps> = ({
             <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
               {t('common.modelProvider.embeddingModel.key')}
               <Tooltip
-                selector='model-page-system-embedding-model-tip'
-                htmlContent={
-                  <div className='w-[261px] text-gray-500'>{t('common.modelProvider.embeddingModel.tip')}</div>
+                popupContent={
+                  <div className='w-[261px] text-gray-500'>
+                    {t('common.modelProvider.embeddingModel.tip')}
+                  </div>
                 }
-              >
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+                needsDelay={false}
+                triggerClassName='ml-0.5'
+              />
             </div>
             <div>
               <ModelSelector
@@ -186,13 +184,14 @@ const SystemModel: FC<SystemModelSelectorProps> = ({
             <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
               {t('common.modelProvider.rerankModel.key')}
               <Tooltip
-                selector='model-page-system-rerankModel-model-tip'
-                htmlContent={
-                  <div className='w-[261px] text-gray-500'>{t('common.modelProvider.rerankModel.tip')}</div>
+                popupContent={
+                  <div className='w-[261px] text-gray-500'>
+                    {t('common.modelProvider.rerankModel.tip')}
+                  </div>
                 }
-              >
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+                needsDelay={false}
+                triggerClassName='ml-0.5'
+              />
             </div>
             <div>
               <ModelSelector
@@ -206,13 +205,14 @@ const SystemModel: FC<SystemModelSelectorProps> = ({
             <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
               {t('common.modelProvider.speechToTextModel.key')}
               <Tooltip
-                selector='model-page-system-speechToText-model-tip'
-                htmlContent={
-                  <div className='w-[261px] text-gray-500'>{t('common.modelProvider.speechToTextModel.tip')}</div>
+                popupContent={
+                  <div className='w-[261px] text-gray-500'>
+                    {t('common.modelProvider.speechToTextModel.tip')}
+                  </div>
                 }
-              >
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+                needsDelay={false}
+                triggerClassName='ml-0.5'
+              />
             </div>
             <div>
               <ModelSelector
@@ -226,13 +226,13 @@ const SystemModel: FC<SystemModelSelectorProps> = ({
             <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
               {t('common.modelProvider.ttsModel.key')}
               <Tooltip
-                selector='model-page-system-tts-model-tip'
-                htmlContent={
-                  <div className='w-[261px] text-gray-500'>{t('common.modelProvider.ttsModel.tip')}</div>
+                popupContent={
+                  <div className='w-[261px] text-gray-500'>
+                    {t('common.modelProvider.ttsModel.tip')}
+                  </div>
                 }
-              >
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-              </Tooltip>
+                triggerClassName='ml-0.5'
+              />
             </div>
             <div>
               <ModelSelector

+ 6 - 8
web/app/components/share/text-generation/result/header.tsx

@@ -42,8 +42,7 @@ const Header: FC<IResultHeaderProps> = ({
 
         {showFeedback && feedback.rating && feedback.rating === 'like' && (
           <Tooltip
-            selector="undo-feedback-like"
-            content="Undo Great Rating"
+            popupContent="Undo Great Rating"
           >
             <div
               onClick={() => {
@@ -59,8 +58,7 @@ const Header: FC<IResultHeaderProps> = ({
 
         {showFeedback && feedback.rating && feedback.rating === 'dislike' && (
           <Tooltip
-            selector="undo-feedback-dislike"
-            content="Undo Undesirable Response"
+            popupContent="Undo Undesirable Response"
           >
             <div
               onClick={() => {
@@ -77,8 +75,8 @@ const Header: FC<IResultHeaderProps> = ({
         {showFeedback && !feedback.rating && (
           <div className='flex rounded-lg border border-gray-200 p-[1px] space-x-1'>
             <Tooltip
-              selector="feedback-like"
-              content="Great Rating"
+              popupContent="Great Rating"
+              needsDelay={false}
             >
               <div
                 onClick={() => {
@@ -91,8 +89,8 @@ const Header: FC<IResultHeaderProps> = ({
               </div>
             </Tooltip>
             <Tooltip
-              selector="feedback-dislike"
-              content="Undesirable Response"
+              popupContent="Undesirable Response"
+              needsDelay={false}
             >
               <div
                 onClick={() => {

+ 3 - 4
web/app/components/tools/add-tool-modal/tools.tsx

@@ -68,10 +68,9 @@ const Blocks = ({
           return (
             <Tooltip
               key={tool.name}
-              selector={`workflow-block-tool-${tool.name}`}
               position='bottom'
-              className='!p-0 !px-3 !py-2.5 !w-[210px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg translate-x-[108px]'
-              htmlContent={(
+              popupClassName='!p-0 !px-3 !py-2.5 !w-[210px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg translate-x-[108px]'
+              popupContent={(
                 <div>
                   <BlockIcon
                     size='md'
@@ -91,7 +90,7 @@ const Blocks = ({
                   )}
                 </div>
               )}
-              noArrow
+              needsDelay
             >
               <div className='group/item flex items-center w-full pl-3 pr-1 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'>
                 <BlockIcon

+ 4 - 9
web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx

@@ -2,10 +2,7 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
-import Tooltip from '../../base/tooltip'
+import Tooltip from '@/app/components/base/tooltip'
 import cn from '@/utils/classnames'
 import type { Credential } from '@/app/components/tools/types'
 import Drawer from '@/app/components/base/drawer-plus'
@@ -112,15 +109,13 @@ const ConfigCredential: FC<Props> = ({
                   <div className='flex items-center h-8 text-[13px] font-medium text-gray-900'>
                     {t('tools.createTool.authMethod.key')}
                     <Tooltip
-                      selector='model-page-system-reasoning-model-tip'
-                      htmlContent={
+                      popupContent={
                         <div className='w-[261px] text-gray-500'>
                           {t('tools.createTool.authMethod.keyTooltip')}
                         </div>
                       }
-                    >
-                      <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-gray-400' />
-                    </Tooltip>
+                      triggerClassName='ml-0.5'
+                    />
                   </div>
                   <input
                     value={tempCredential.api_key_header}

+ 2 - 8
web/app/components/tools/workflow-tool/index.tsx

@@ -2,9 +2,6 @@
 import type { FC } from 'react'
 import React, { useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import produce from 'immer'
 import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types'
 import cn from '@/utils/classnames'
@@ -148,15 +145,12 @@ const WorkflowToolAsModal: FC<Props> = ({
                 <div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'>
                   {t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span>
                   <Tooltip
-                    htmlContent={
+                    popupContent={
                       <div className='w-[180px]'>
                         {t('tools.createTool.nameForToolCallPlaceHolder')}
                       </div>
                     }
-                    selector='workflow-tool-modal-tooltip'
-                  >
-                    <RiQuestionLine className='ml-2 w-[14px] h-[14px] text-gray-400' />
-                  </Tooltip>
+                  />
                 </div>
                 <input
                   type='text'

+ 2 - 4
web/app/components/workflow/block-selector/blocks.tsx

@@ -67,10 +67,9 @@ const Blocks = ({
           list.map(block => (
             <Tooltip
               key={block.type}
-              selector={`workflow-block-${block.type}`}
               position='right'
-              className='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
-              htmlContent={(
+              popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
+              popupContent={(
                 <div>
                   <BlockIcon
                     size='md'
@@ -81,7 +80,6 @@ const Blocks = ({
                   <div className='text-xs text-gray-700 leading-[18px]'>{nodesExtraData[block.type].about}</div>
                 </div>
               )}
-              noArrow
             >
               <div
                 key={block.type}

+ 3 - 5
web/app/components/workflow/block-selector/tools.tsx

@@ -44,10 +44,9 @@ const Blocks = ({
           list.map(tool => (
             <Tooltip
               key={tool.name}
-              selector={`workflow-block-tool-${tool.name}`}
               position='right'
-              className='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
-              htmlContent={(
+              popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg'
+              popupContent={(
                 <div>
                   <BlockIcon
                     size='md'
@@ -59,7 +58,6 @@ const Blocks = ({
                   <div className='text-xs text-gray-700 leading-[18px]'>{tool.description[language]}</div>
                 </div>
               )}
-              noArrow
             >
               <div
                 className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
@@ -77,7 +75,7 @@ const Blocks = ({
                   type={BlockEnum.Tool}
                   toolIcon={toolWithProvider.icon}
                 />
-                <div className='text-sm text-gray-900 truncate'>{tool.label[language]}</div>
+                <div className='text-sm text-gray-900 flex-1 min-w-0 truncate'>{tool.label[language]}</div>
               </div>
             </Tooltip>
           ))

+ 3 - 3
web/app/components/workflow/header/view-history.tsx

@@ -24,7 +24,7 @@ import {
   PortalToFollowElemContent,
   PortalToFollowElemTrigger,
 } from '@/app/components/base/portal-to-follow-elem'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { useStore as useAppStore } from '@/app/components/app/store'
 import {
   ClockPlay,
@@ -100,7 +100,7 @@ const ViewHistory = ({
           }
           {
             !withText && (
-              <TooltipPlus
+              <Tooltip
                 popupContent={t('workflow.common.viewRunHistory')}
               >
                 <div
@@ -112,7 +112,7 @@ const ViewHistory = ({
                 >
                   <ClockPlay className={cn('w-4 h-4 group-hover:text-components-button-secondary-accent-text', open ? 'text-components-button-secondary-accent-text' : 'text-components-button-ghost-text')} />
                 </div>
-              </TooltipPlus>
+              </Tooltip>
             )
           }
         </PortalToFollowElemTrigger>

+ 6 - 8
web/app/components/workflow/nodes/_base/components/field.tsx

@@ -3,12 +3,11 @@ import type { FC } from 'react'
 import React from 'react'
 import {
   RiArrowDownSLine,
-  RiQuestionLine,
 } from '@remixicon/react'
 import { useBoolean } from 'ahooks'
 import type { DefaultTFuncReturn } from 'i18next'
 import cn from '@/utils/classnames'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type Props = {
   className?: string
@@ -40,12 +39,11 @@ const Filed: FC<Props> = ({
         <div className='flex items-center h-6'>
           <div className='system-sm-semibold-uppercase text-text-secondary'>{title}</div>
           {tooltip && (
-            <TooltipPlus popupContent={
-              <div className='w-[120px]'>
-                {tooltip}
-              </div>}>
-              <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-text-quaternary' />
-            </TooltipPlus>
+            <Tooltip
+              popupContent={tooltip}
+              popupClassName='ml-1'
+              triggerClassName='w-4 h-4 ml-1'
+            />
           )}
 
         </div>

+ 4 - 2
web/app/components/workflow/nodes/_base/components/help-link.tsx

@@ -2,7 +2,7 @@ import { memo } from 'react'
 import { useTranslation } from 'react-i18next'
 import { RiBookOpenLine } from '@remixicon/react'
 import { useNodeHelpLink } from '../hooks/use-node-help-link'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import TooltipPlus from '@/app/components/base/tooltip'
 import type { BlockEnum } from '@/app/components/workflow/types'
 
 type HelpLinkProps = {
@@ -15,7 +15,9 @@ const HelpLink = ({
   const link = useNodeHelpLink(nodeType)
 
   return (
-    <TooltipPlus popupContent={t('common.userProfile.helpCenter')}>
+    <TooltipPlus
+      popupContent={t('common.userProfile.helpCenter')}
+    >
       <a
         href={link}
         target='_blank'

+ 3 - 3
web/app/components/workflow/nodes/_base/components/input-support-select-var.tsx

@@ -11,7 +11,7 @@ import type {
 import { BlockEnum } from '@/app/components/workflow/types'
 import PromptEditor from '@/app/components/base/prompt-editor'
 import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type Props = {
   instanceId?: string
@@ -109,13 +109,13 @@ const Editor: FC<Props> = ({
         {readOnly && <div className='absolute inset-0 z-10'></div>}
         {isFocus && (
           <div className={cn('absolute z-10', insertVarTipToLeft ? 'top-1.5 left-[-12px]' : ' top-[-9px] right-1')}>
-            <TooltipPlus
+            <Tooltip
               popupContent={`${t('workflow.common.insertVarTip')}`}
             >
               <div className='p-0.5 rounded-[5px] shadow-lg cursor-pointer bg-white hover:bg-gray-100 border-[0.5px] border-black/5'>
                 <Variable02 className='w-3.5 h-3.5 text-components-button-secondary-accent-text' />
               </div>
-            </TooltipPlus>
+            </Tooltip>
           </div>
         )}
       </>

+ 4 - 3
web/app/components/workflow/nodes/_base/components/node-control.tsx

@@ -19,7 +19,7 @@ import PanelOperator from './panel-operator'
 import {
   Stop,
 } from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type NodeControlProps = Pick<Node, 'id' | 'data'>
 const NodeControl: FC<NodeControlProps> = ({
@@ -68,11 +68,12 @@ const NodeControl: FC<NodeControlProps> = ({
                 data._isSingleRun
                   ? <Stop className='w-3 h-3' />
                   : (
-                    <TooltipPlus
+                    <Tooltip
                       popupContent={t('workflow.panel.runThisStep')}
+                      asChild={false}
                     >
                       <RiPlayLargeLine className='w-3 h-3' />
-                    </TooltipPlus>
+                    </Tooltip>
                   )
               }
             </div>

+ 10 - 9
web/app/components/workflow/nodes/_base/components/option-card.tsx

@@ -3,9 +3,8 @@ import type { FC } from 'react'
 import React, { useCallback } from 'react'
 import type { VariantProps } from 'class-variance-authority'
 import { cva } from 'class-variance-authority'
-import { RiQuestionLine } from '@remixicon/react'
 import cn from '@/utils/classnames'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 const variants = cva([], {
   variants: {
@@ -59,13 +58,15 @@ const OptionCard: FC<Props> = ({
       onClick={handleSelect}
     >
       <span>{title}</span>
-      {tooltip && <TooltipPlus
-        popupContent={<div className='w-[240px]'>
-          {tooltip}
-        </div>}
-      >
-        <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-text-quaternary' />
-      </TooltipPlus>}
+      {tooltip
+        && <Tooltip
+          popupContent={
+            <div className='w-[240px]'>
+              {tooltip}
+            </div>
+          }
+        />
+      }
     </div>
   )
 }

+ 6 - 7
web/app/components/workflow/nodes/_base/components/prompt/editor.tsx

@@ -31,7 +31,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
 import { PROMPT_EDITOR_INSERT_QUICKLY } from '@/app/components/base/prompt-editor/plugins/update-block'
 import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development'
 import ActionButton from '@/app/components/base/action-button'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars'
 import Switch from '@/app/components/base/switch'
 import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
@@ -141,14 +141,14 @@ const Editor: FC<Props> = ({
               {/* Operations */}
               <div className='flex items-center space-x-[2px]'>
                 {isSupportJinja && (
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={
                       <div>
                         <div>{t('workflow.common.enableJinja')}</div>
                         <a className='text-[#155EEF]' target='_blank' href='https://jinja.palletsprojects.com/en/2.10.x/'>{t('workflow.common.learnMore')}</a>
                       </div>
                     }
-                    hideArrow
+                    needsDelay
                   >
                     <div className={cn(editionType === EditionType.jinja2 && 'border-black/5 bg-white', 'flex h-[22px] items-center px-1.5 rounded-[5px] border border-transparent hover:border-black/5 space-x-0.5')}>
                       <Jinja className='w-6 h-3 text-gray-300' />
@@ -160,18 +160,17 @@ const Editor: FC<Props> = ({
                         }}
                       />
                     </div>
-                  </TooltipPlus>
+                  </Tooltip>
 
                 )}
                 {!readOnly && (
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={`${t('workflow.common.insertVarTip')}`}
-                    asChild
                   >
                     <ActionButton onClick={handleInsertVariable}>
                       <Variable02 className='w-4 h-4' />
                     </ActionButton>
-                  </TooltipPlus>
+                  </Tooltip>
                 )}
                 {showRemove && (
                   <ActionButton onClick={onRemove}>

+ 4 - 3
web/app/components/workflow/nodes/_base/panel.tsx

@@ -35,7 +35,7 @@ import {
   useWorkflowHistory,
 } from '@/app/components/workflow/hooks'
 import { canRunBySingle } from '@/app/components/workflow/utils'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import type { Node } from '@/app/components/workflow/types'
 import { useStore as useAppStore } from '@/app/components/app/store'
 import { useStore } from '@/app/components/workflow/store'
@@ -127,8 +127,9 @@ const BasePanel: FC<BasePanelProps> = ({
             <div className='shrink-0 flex items-center text-gray-500'>
               {
                 canRunBySingle(data.type) && !nodesReadOnly && (
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={t('workflow.panel.runThisStep')}
+                    popupClassName='mr-1'
                   >
                     <div
                       className='flex items-center justify-center mr-1 w-6 h-6 rounded-md hover:bg-black/5 cursor-pointer'
@@ -139,7 +140,7 @@ const BasePanel: FC<BasePanelProps> = ({
                     >
                       <RiPlayLargeLine className='w-4 h-4 text-text-tertiary' />
                     </div>
-                  </TooltipPlus>
+                  </Tooltip>
                 )
               }
               <HelpLink nodeType={data.type} />

+ 3 - 3
web/app/components/workflow/nodes/iteration/add-block.tsx

@@ -29,7 +29,7 @@ import type {
 import {
   BlockEnum,
 } from '@/app/components/workflow/types'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type AddBlockProps = {
   iterationNodeId: string
@@ -99,11 +99,11 @@ const AddBlock = ({
 
   return (
     <div className='absolute top-12 left-6 flex items-center h-8 z-10'>
-      <TooltipPlus popupContent={t('workflow.blocks.iteration-start')}>
+      <Tooltip popupContent={t('workflow.blocks.iteration-start')}>
         <div className='flex items-center justify-center w-6 h-6 rounded-full border-[0.5px] border-black/[0.02] shadow-md bg-primary-500'>
           <IterationStart className='w-4 h-4 text-white' />
         </div>
-      </TooltipPlus>
+      </Tooltip>
       <div className='group/insert relative w-16 h-0.5 bg-gray-300'>
         {
           iterationNodeData.startNodeType && (

+ 4 - 6
web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx

@@ -3,13 +3,12 @@ import type { FC } from 'react'
 import React, { useCallback, useEffect, useState } from 'react'
 import { uniqueId } from 'lodash-es'
 import { useTranslation } from 'react-i18next'
-import { RiQuestionLine } from '@remixicon/react'
 import type { ModelConfig, PromptItem, Variable } from '../../../types'
 import { EditionType } from '../../../types'
 import { useWorkflowStore } from '../../../store'
 import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
 import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { PromptRole } from '@/models/debug'
 
 const i18nPrefix = 'workflow.nodes.llm'
@@ -118,13 +117,12 @@ const ConfigPromptItem: FC<Props> = ({
               />
             )}
 
-          <TooltipPlus
+          <Tooltip
             popupContent={
               <div className='max-w-[180px]'>{t(`${i18nPrefix}.roleDescription.${payload.role}`)}</div>
             }
-          >
-            <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-          </TooltipPlus>
+            triggerClassName='w-4 h-4'
+          />
         </div>
       }
       value={payload.edition_type === EditionType.jinja2 ? (payload.jinja2_text || '') : payload.text}

+ 7 - 10
web/app/components/workflow/nodes/llm/panel.tsx

@@ -1,7 +1,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import { RiQuestionLine } from '@remixicon/react'
 import MemoryConfig from '../_base/components/memory-config'
 import VarReferencePicker from '../_base/components/variable/var-reference-picker'
 import useConfig from './use-config'
@@ -19,7 +18,7 @@ import { InputVarType, type NodePanelProps } from '@/app/components/workflow/typ
 import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
 import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
 import ResultPanel from '@/app/components/workflow/run/result-panel'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
 import Switch from '@/app/components/base/switch'
 const i18nPrefix = 'workflow.nodes.llm'
@@ -206,11 +205,10 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
             <div className='flex justify-between items-center h-8 pl-3 pr-2 rounded-lg bg-gray-100'>
               <div className='flex items-center space-x-1'>
                 <div className='text-xs font-semibold text-gray-700 uppercase'>{t('workflow.nodes.common.memories.title')}</div>
-                <TooltipPlus
+                <Tooltip
                   popupContent={t('workflow.nodes.common.memories.tip')}
-                >
-                  <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-                </TooltipPlus>
+                  triggerClassName='w-4 h-4'
+                />
               </div>
               <div className='flex items-center h-[18px] px-1 rounded-[5px] border border-black/8 text-xs font-semibold text-gray-500 uppercase'>{t('workflow.nodes.common.memories.builtIn')}</div>
             </div>
@@ -219,13 +217,12 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
               <Editor
                 title={<div className='flex items-center space-x-1'>
                   <div className='text-xs font-semibold text-gray-700 uppercase'>user</div>
-                  <TooltipPlus
+                  <Tooltip
                     popupContent={
                       <div className='max-w-[180px]'>{t('workflow.nodes.llm.roleDescription.user')}</div>
                     }
-                  >
-                    <RiQuestionLine className='w-3.5 h-3.5 text-gray-400' />
-                  </TooltipPlus>
+                    triggerClassName='w-4 h-4'
+                  />
                 </div>}
                 value={inputs.memory.query_prompt_template || '{{#sys.query#}}'}
                 onChange={handleSyeQueryChange}

+ 9 - 10
web/app/components/workflow/nodes/parameter-extractor/panel.tsx

@@ -1,9 +1,6 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import MemoryConfig from '../_base/components/memory-config'
 import VarReferencePicker from '../_base/components/variable/var-reference-picker'
 import Editor from '../_base/components/prompt/editor'
@@ -19,7 +16,7 @@ import Split from '@/app/components/workflow/nodes/_base/components/split'
 import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
 import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
 import { InputVarType, type NodePanelProps } from '@/app/components/workflow/types'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import BeforeRunForm from '@/app/components/workflow/nodes/_base/components/before-run-form'
 import { VarType } from '@/app/components/workflow/types'
 
@@ -126,12 +123,14 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
           title={
             <div className='flex items-center space-x-1'>
               <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span>
-              <TooltipPlus popupContent={
-                <div className='w-[120px]'>
-                  {t(`${i18nPrefix}.instructionTip`)}
-                </div>}>
-                <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-gray-400' />
-              </TooltipPlus>
+              <Tooltip
+                popupContent={
+                  <div className='w-[120px]'>
+                    {t(`${i18nPrefix}.instructionTip`)}
+                  </div>
+                }
+                triggerClassName='w-3.5 h-3.5 ml-0.5'
+              />
             </div>
           }
           value={inputs.instruction}

+ 9 - 10
web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx

@@ -2,13 +2,10 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiQuestionLine,
-} from '@remixicon/react'
 import MemoryConfig from '../../_base/components/memory-config'
 import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
 import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 const i18nPrefix = 'workflow.nodes.questionClassifiers'
 
 type Props = {
@@ -50,12 +47,14 @@ const AdvancedSetting: FC<Props> = ({
         title={
           <div className='flex items-center space-x-1'>
             <span className='uppercase'>{t(`${i18nPrefix}.instruction`)}</span>
-            <TooltipPlus popupContent={
-              <div className='w-[120px]'>
-                {t(`${i18nPrefix}.instructionTip`)}
-              </div>}>
-              <RiQuestionLine className='w-3.5 h-3.5 ml-0.5 text-gray-400' />
-            </TooltipPlus>
+            <Tooltip
+              popupContent={
+                <div className='w-[120px]'>
+                  {t(`${i18nPrefix}.instructionTip`)}
+                </div>
+              }
+              triggerClassName='w-3.5 h-3.5 ml-0.5'
+            />
           </div>
         }
         value={instruction}

+ 5 - 3
web/app/components/workflow/note-node/note-editor/toolbar/command.tsx

@@ -13,7 +13,7 @@ import {
 import { useStore } from '../store'
 import { useCommand } from './hooks'
 import cn from '@/utils/classnames'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type CommandProps = {
   type: 'bold' | 'italic' | 'strikethrough' | 'link' | 'bullet'
@@ -60,7 +60,9 @@ const Command = ({
   }, [type, t])
 
   return (
-    <TooltipPlus popupContent={tip}>
+    <Tooltip
+      popupContent={tip}
+    >
       <div
         className={cn(
           'flex items-center justify-center w-8 h-8 cursor-pointer rounded-md text-gray-500 hover:text-gray-800 hover:bg-black/5',
@@ -74,7 +76,7 @@ const Command = ({
       >
         {icon}
       </div>
-    </TooltipPlus>
+    </Tooltip>
   )
 }
 

+ 3 - 4
web/app/components/workflow/operator/tip-popup.tsx

@@ -1,6 +1,6 @@
 import { memo } from 'react'
 import ShortcutsName from '../shortcuts-name'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 
 type TipPopupProps = {
   title: string
@@ -13,9 +13,8 @@ const TipPopup = ({
   shortcuts,
 }: TipPopupProps) => {
   return (
-    <TooltipPlus
+    <Tooltip
       offset={4}
-      hideArrow
       popupClassName='!p-0 !bg-gray-25'
       popupContent={
         <div className='flex items-center gap-1 px-2 h-6 text-xs font-medium text-gray-700 rounded-lg border-[0.5px] border-black/5'>
@@ -27,7 +26,7 @@ const TipPopup = ({
       }
     >
       {children}
-    </TooltipPlus>
+    </Tooltip>
   )
 }
 

+ 7 - 7
web/app/components/workflow/panel/debug-and-preview/index.tsx

@@ -18,7 +18,7 @@ import ChatWrapper from './chat-wrapper'
 import cn from '@/utils/classnames'
 import { RefreshCcw01 } from '@/app/components/base/icons/src/vender/line/arrows'
 import { BubbleX } from '@/app/components/base/icons/src/vender/line/others'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
 import { useStore } from '@/app/components/workflow/store'
 
@@ -63,31 +63,31 @@ const DebugAndPreview = () => {
       <div className='shrink-0 flex items-center justify-between px-4 pt-3 pb-2 text-text-primary system-xl-semibold'>
         <div className='h-8'>{t('workflow.common.debugAndPreview').toLocaleUpperCase()}</div>
         <div className='flex items-center gap-1'>
-          <TooltipPlus
+          <Tooltip
             popupContent={t('common.operation.refresh')}
           >
             <ActionButton onClick={() => handleRestartChat()}>
               <RefreshCcw01 className='w-4 h-4' />
             </ActionButton>
-          </TooltipPlus>
+          </Tooltip>
           {varList.length > 0 && (
-            <TooltipPlus
+            <Tooltip
               popupContent={t('workflow.chatVariable.panelTitle')}
             >
               <ActionButton onClick={() => setShowConversationVariableModal(true)}>
                 <BubbleX className='w-4 h-4' />
               </ActionButton>
-            </TooltipPlus>
+            </Tooltip>
           )}
           {variables.length > 0 && (
             <div className='relative'>
-              <TooltipPlus
+              <Tooltip
                 popupContent={t('workflow.panel.userInputField')}
               >
                 <ActionButton state={expanded ? ActionButtonState.Active : undefined} onClick={() => setExpanded(!expanded)}>
                   <RiEqualizer2Line className='w-4 h-4' />
                 </ActionButton>
-              </TooltipPlus>
+              </Tooltip>
               {expanded && <div className='absolute z-10 bottom-[-17px] right-[5px] w-3 h-3 bg-components-panel-on-panel-item-bg border-l-[0.5px] border-t-[0.5px] border-components-panel-border-subtle rotate-45'/>}
             </div>
           )}

+ 10 - 9
web/app/components/workflow/panel/env-panel/variable-modal.tsx

@@ -1,10 +1,10 @@
 import React, { useEffect } from 'react'
 import { useTranslation } from 'react-i18next'
 import { v4 as uuid4 } from 'uuid'
-import { RiCloseLine, RiQuestionLine } from '@remixicon/react'
+import { RiCloseLine } from '@remixicon/react'
 import { useContext } from 'use-context-selector'
 import Button from '@/app/components/base/button'
-import TooltipPlus from '@/app/components/base/tooltip-plus'
+import Tooltip from '@/app/components/base/tooltip'
 import { ToastContext } from '@/app/components/base/toast'
 import { useStore } from '@/app/components/workflow/store'
 import type { EnvironmentVariable } from '@/app/components/workflow/types'
@@ -102,13 +102,14 @@ const VariableModal = ({
               type === 'secret' && 'text-text-primary font-medium border-[1.5px] shadow-xs bg-components-option-card-option-selected-bg border-components-option-card-option-selected-border hover:border-components-option-card-option-selected-border',
             )} onClick={() => setType('secret')}>
               <span>Secret</span>
-              <TooltipPlus popupContent={
-                <div className='w-[240px]'>
-                  {t('workflow.env.modal.secretTip')}
-                </div>
-              }>
-                <RiQuestionLine className='ml-0.5 w-[14px] h-[14px] text-text-quaternary' />
-              </TooltipPlus>
+              <Tooltip
+                popupContent={
+                  <div className='w-[240px]'>
+                    {t('workflow.env.modal.secretTip')}
+                  </div>
+                }
+                triggerClassName='ml-0.5 w-3.5 h-3.5'
+              />
             </div>
           </div>
         </div>

+ 3 - 5
web/app/signin/oneMoreStep.tsx

@@ -6,8 +6,7 @@ import useSWR from 'swr'
 import { useRouter } from 'next/navigation'
 // import { useContext } from 'use-context-selector'
 import Button from '@/app/components/base/button'
-import Tooltip from '@/app/components/base/tooltip/index'
-
+import Tooltip from '@/app/components/base/tooltip'
 import { SimpleSelect } from '@/app/components/base/select'
 import { timezones } from '@/utils/timezone'
 import { LanguagesSupported, languages } from '@/i18n/language'
@@ -88,9 +87,7 @@ const OneMoreStep = () => {
             <label className="my-2 flex items-center justify-between text-sm font-medium text-gray-900">
               {t('login.invitationCode')}
               <Tooltip
-                clickable
-                selector='dont-have'
-                htmlContent={
+                popupContent={
                   <div className='w-[256px] text-xs font-medium'>
                     <div className='font-medium'>{t('login.sendUsMail')}</div>
                     <div className='text-xs font-medium cursor-pointer text-primary-600'>
@@ -98,6 +95,7 @@ const OneMoreStep = () => {
                     </div>
                   </div>
                 }
+                needsDelay
               >
                 <span className='cursor-pointer text-primary-600'>{t('login.donthave')}</span>
               </Tooltip>