From bfcd0fdb39db577d12479f98d77254da51edb42e Mon Sep 17 00:00:00 2001
From: yyh <92089059+lyzno1@users.noreply.github.com>
Date: Tue, 22 Sep 2026 03:09:18 +0000
Subject: [PATCH] refactor(ui): expose compound Infotip primitives and migrate
consumers (#42681)
---
packages/dify-ui/README.md | 2 +-
packages/dify-ui/package.json | 4 +
.../src/infotip/__tests__/index.spec.tsx | 47 ++++++++
.../dify-ui/src/infotip/__tests__/types.tsx | 47 ++++++++
.../dify-ui/src/infotip/index.stories.tsx | 105 ++++++++++++++++
packages/dify-ui/src/infotip/index.tsx | 112 ++++++++++++++++++
web/AGENTS.md | 2 +-
.../access-control-form.tsx | 27 +++--
.../specific-groups-or-members.tsx | 15 +--
.../config-prompt/advanced-prompt-input.tsx | 19 +--
.../config-prompt/simple-prompt-input.tsx | 19 +--
.../config-var/config-modal/form-fields.tsx | 35 +++---
.../app/configuration/config-var/index.tsx | 15 ++-
.../app/configuration/config-vision/index.tsx | 44 ++++---
.../config-vision/param-config-content.tsx | 31 +++--
.../config/agent/agent-setting/item-panel.tsx | 9 +-
.../config/agent/agent-tools/index.tsx | 49 ++++----
.../app/configuration/config/config-audio.tsx | 17 ++-
.../configuration/config/config-document.tsx | 17 ++-
.../dataset-config/context-var/index.tsx | 17 ++-
.../params-config/config-content.tsx | 43 ++++---
web/app/components/app/overview/app-chart.tsx | 9 +-
.../base/chat/chat/chat-input-area/index.tsx | 21 ++--
.../annotation-reply/config-param.tsx | 9 +-
.../conversation-opener/modal.tsx | 25 ++--
.../new-feature-panel/feature-card.tsx | 15 ++-
.../text-to-speech/param-config-content.tsx | 25 ++--
.../base/form/components/base/base-field.tsx | 9 +-
.../form/components/field/upload-method.tsx | 13 +-
.../components/base/form/components/label.tsx | 9 +-
.../base/infotip/__tests__/index.spec.tsx | 53 ---------
web/app/components/base/infotip/index.tsx | 106 -----------------
web/app/components/base/param-item/index.tsx | 9 +-
.../billing/priority-label/index.tsx | 29 +++--
.../components/billing/usage-info/index.tsx | 9 +-
.../common/retrieval-param-config/index.tsx | 17 ++-
.../list/template-card/details/index.tsx | 17 ++-
.../indexing-progress-item.tsx | 25 ++--
.../components/general-chunking-options.tsx | 17 ++-
.../create/step-two/components/inputs.tsx | 32 +++--
.../website/base/checkbox-with-label.tsx | 9 +-
.../datasets/create/website/base/field.tsx | 9 +-
.../base/checkbox-with-label.tsx | 9 +-
.../datasets/documents/status-item/index.tsx | 13 +-
.../metadata/edit-metadata-batch/modal.tsx | 25 ++--
.../dataset-metadata-drawer.tsx | 21 +++-
.../metadata/metadata-document/info-group.tsx | 9 +-
.../settings/index-method/keyword-number.tsx | 7 +-
.../settings/summary-index-setting.tsx | 17 ++-
.../model-provider-page/model-modal/Form.tsx | 9 +-
.../model-parameter-modal/parameter-item.tsx | 19 +--
.../usage-priority-section.tsx | 7 +-
.../model-load-balancing-configs.tsx | 19 +--
.../system-model-selector/index.tsx | 13 +-
.../workflow-log-archives-page/index.tsx | 19 +--
.../multiple-tool-selector/index.tsx | 15 ++-
.../subscription-list/create/index.tsx | 23 ++--
.../subscription-list/list-view.tsx | 17 ++-
.../subscription-list/selector-view.tsx | 17 ++-
.../components/reasoning-config-form.tsx | 9 +-
.../components/panel/input-field/index.tsx | 23 ++--
.../label-right-content/global-inputs.tsx | 21 +++-
.../config-credentials.tsx | 52 +++++---
.../components/tools/workflow-tool/index.tsx | 68 ++++++-----
.../components/agent-strategy-selector.tsx | 41 ++++---
.../error-handle/error-handle-on-panel.tsx | 13 +-
.../workflow/nodes/_base/components/field.tsx | 7 +-
.../_base/components/layout/field-title.tsx | 7 +-
.../nodes/_base/components/option-card.tsx | 9 +-
.../workflow/nodes/_base/node-sections.tsx | 24 ++--
.../agent-v2/components/agent-task-field.tsx | 29 +++--
.../components/delivery-method/index.tsx | 15 ++-
.../workflow/nodes/human-input/panel.tsx | 28 +++--
.../components/index-method.tsx | 9 +-
.../search-method-option.tsx | 10 +-
.../top-k-and-score-threshold.tsx | 12 +-
.../metadata/metadata-filter/index.tsx | 17 ++-
.../llm/components/config-prompt-item.tsx | 9 +-
.../json-schema-generator/prompt-editor.tsx | 17 ++-
.../llm/components/panel-memory-section.tsx | 28 +++--
.../llm/components/panel-output-section.tsx | 46 ++++---
.../nodes/parameter-extractor/panel.tsx | 19 +--
.../components/advanced-setting.tsx | 19 +--
.../nodes/tool/components/tool-form/item.tsx | 13 +-
.../components/trigger-form/item.tsx | 16 +--
.../components/monthly-days-selector.tsx | 25 ++--
.../panel/env-panel/variable-modal.tsx | 19 +--
.../__tests__/agent-prompt-editor.spec.tsx | 5 -
.../components/orchestrate/common/section.tsx | 13 +-
.../components/orchestrate/files/index.tsx | 39 +++---
.../orchestrate/prompt-editor/index.tsx | 9 +-
.../preview/working-directory-panel.tsx | 30 +++--
.../agent-detail/monitoring/chart.tsx | 9 +-
web/plugins/eslint/tooltip-content.test.ts | 4 +-
94 files changed, 1329 insertions(+), 787 deletions(-)
create mode 100644 packages/dify-ui/src/infotip/__tests__/index.spec.tsx
create mode 100644 packages/dify-ui/src/infotip/__tests__/types.tsx
create mode 100644 packages/dify-ui/src/infotip/index.stories.tsx
create mode 100644 packages/dify-ui/src/infotip/index.tsx
delete mode 100644 web/app/components/base/infotip/__tests__/index.spec.tsx
delete mode 100644 web/app/components/base/infotip/index.tsx
diff --git a/packages/dify-ui/README.md b/packages/dify-ui/README.md
index 1dfb3941078..3d344e59101 100644
--- a/packages/dify-ui/README.md
+++ b/packages/dify-ui/README.md
@@ -44,7 +44,7 @@ Import `styles.css` once from the consumer's root stylesheet or entrypoint.
| Layout | `./scroll-area`, `./separator` |
| Media | `./avatar` |
| Navigation | `./breadcrumb`, `./file-tree`, `./pagination`, `./tabs` |
-| Overlay and menu | `./alert-dialog`, `./context-menu`, `./dialog`, `./drawer`, `./dropdown-menu`, `./popover`, `./preview-card`, `./tooltip` |
+| Overlay and menu | `./alert-dialog`, `./context-menu`, `./dialog`, `./drawer`, `./dropdown-menu`, `./infotip`, `./popover`, `./preview-card`, `./tooltip` |
| Search and pick | `./autocomplete`, `./combobox`, `./select` |
Utilities:
diff --git a/packages/dify-ui/package.json b/packages/dify-ui/package.json
index f1af6b2cc79..1cc708878b7 100644
--- a/packages/dify-ui/package.json
+++ b/packages/dify-ui/package.json
@@ -172,6 +172,10 @@
"./separator": {
"types": "./src/separator/index.tsx",
"import": "./src/separator/index.tsx"
+ },
+ "./infotip": {
+ "types": "./src/infotip/index.tsx",
+ "import": "./src/infotip/index.tsx"
}
},
"scripts": {
diff --git a/packages/dify-ui/src/infotip/__tests__/index.spec.tsx b/packages/dify-ui/src/infotip/__tests__/index.spec.tsx
new file mode 100644
index 00000000000..2b6ee89cafc
--- /dev/null
+++ b/packages/dify-ui/src/infotip/__tests__/index.spec.tsx
@@ -0,0 +1,47 @@
+import * as React from 'react'
+import { createPortal } from 'react-dom'
+import { render } from 'vitest-browser-react'
+import { Infotip, InfotipContent, InfotipTrigger } from '..'
+
+describe('Infotip composition', () => {
+ it('preserves caller handlers and prevents an enclosing action from firing', async () => {
+ const parentClick = vi.fn()
+ const triggerClick = vi.fn()
+ const triggerRef = React.createRef()
+ const screen = await render(
+ ,
+ )
+ await screen.getByRole('button', { name: 'Details' }).click()
+ await expect
+ .element(screen.getByRole('dialog', { name: 'Details' }))
+ .toHaveTextContent('Explanation')
+ expect(triggerRef.current?.tagName).toBe('BUTTON')
+ expect(triggerClick).toHaveBeenCalledOnce()
+ expect(parentClick).not.toHaveBeenCalled()
+ })
+
+ it('lets a caller cancel opening without losing trigger event composition', async () => {
+ const onOpenChange = vi.fn()
+ const screen = await render(
+
+ event.preventBaseUIHandler()}
+ />
+ Explanation
+ ,
+ )
+ await screen.getByRole('button', { name: 'Unavailable details' }).click()
+ expect(onOpenChange).not.toHaveBeenCalled()
+ })
+})
diff --git a/packages/dify-ui/src/infotip/__tests__/types.tsx b/packages/dify-ui/src/infotip/__tests__/types.tsx
new file mode 100644
index 00000000000..dbf62af4c08
--- /dev/null
+++ b/packages/dify-ui/src/infotip/__tests__/types.tsx
@@ -0,0 +1,47 @@
+import type * as React from 'react'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
+
+export function infotipTypeContracts(
+ triggerRef: React.Ref,
+ popupRef: React.Ref,
+) {
+ const composition = (
+ >
+ {({ payload }) => (
+ <>
+ (state.open ? 'text-text-accent' : undefined)}
+ style={(state) => ({ opacity: state.disabled ? 0.5 : 1 })}
+ />
+ (side === 'top' ? 4 : 8)}
+ className={(state) => (state.open ? 'w-60' : undefined)}
+ style={(state) => ({ opacity: state.open ? 1 : 0 })}
+ >
+ {payload?.title}
+
+ >
+ )}
+
+ )
+ const labelledTrigger =
+ // @ts-expect-error An icon-only trigger requires an accessible name.
+ const unnamed =
+ // @ts-expect-error The icon is owned by InfotipTrigger.
+ const children = Custom trigger
+ // @ts-expect-error InfotipTrigger always renders a native button.
+ const render = } />
+ const state = (
+ // @ts-expect-error Popup state is separate from trigger state.
+ String(state.disabled)}>Details
+ )
+ return { composition, labelledTrigger, unnamed, children, render, state }
+}
diff --git a/packages/dify-ui/src/infotip/index.stories.tsx b/packages/dify-ui/src/infotip/index.stories.tsx
new file mode 100644
index 00000000000..21512303eb7
--- /dev/null
+++ b/packages/dify-ui/src/infotip/index.stories.tsx
@@ -0,0 +1,105 @@
+import type { Meta, StoryObj } from '@storybook/react-vite'
+import * as React from 'react'
+import { expect, userEvent, waitFor, within } from 'storybook/test'
+import { Infotip, InfotipContent, InfotipTrigger } from '.'
+import { Button } from '../button'
+
+const meta = {
+ title: 'Base/UI/Infotip',
+ component: Infotip,
+ parameters: {
+ layout: 'centered',
+ docs: {
+ description: {
+ component:
+ 'An information button that opens explanatory content using Popover semantics. Compose the root, icon trigger, and content. Name the trigger and the dialog; use aria-labelledby when a visible heading exists. The popup remains available to keyboard and touch users and may contain links.',
+ },
+ },
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ render: () => (
+
+ Document processing
+
+
+
+ Documents are processed in the order they are received. Larger files can take longer to
+ finish indexing.
+
+
+
+ ),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement)
+ const body = within(canvasElement.ownerDocument.body)
+ const trigger = canvas.getByRole('button', { name: 'Document processing' })
+ await userEvent.hover(trigger)
+ const popup = await body.findByRole('dialog', { name: 'Document processing' })
+ await userEvent.hover(popup)
+ await waitFor(() => expect(popup).toBeVisible())
+ await userEvent.keyboard('{Escape}')
+ await waitFor(() => expect(body.queryByRole('dialog')).not.toBeInTheDocument())
+ },
+}
+
+export const WithLink: Story = {
+ render: () => (
+
+
+
+ Describe the agent’s task and the rules it should follow.{' '}
+
+ Read the documentation
+
+
+
+ ),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement)
+ const body = within(canvasElement.ownerDocument.body)
+ const trigger = canvas.getByRole('button', { name: 'Agent instructions' })
+ trigger.focus()
+ await userEvent.keyboard('{Enter}')
+ const popup = await body.findByRole('dialog', { name: 'Agent instructions' })
+ await waitFor(() =>
+ expect(within(popup).getByRole('link', { name: 'Read the documentation' })).toHaveFocus(),
+ )
+ await userEvent.keyboard('{Escape}')
+ await waitFor(() => expect(body.queryByRole('dialog')).not.toBeInTheDocument())
+ expect(trigger).toHaveFocus()
+ },
+}
+
+function ControlledExample() {
+ const [open, setOpen] = React.useState(false)
+ return (
+
+
+
+
+
+ The file could not be processed. Review its contents before trying again.
+
+
+
+ )
+}
+
+export const Controlled: Story = {
+ render: () => ,
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement)
+ const body = within(canvasElement.ownerDocument.body)
+ await userEvent.click(canvas.getByRole('button', { name: 'Show explanation' }))
+ await waitFor(() =>
+ expect(body.getByRole('dialog', { name: 'Processing error' })).toBeVisible(),
+ )
+ await userEvent.keyboard('{Escape}')
+ await waitFor(() => expect(body.queryByRole('dialog')).not.toBeInTheDocument())
+ },
+}
diff --git a/packages/dify-ui/src/infotip/index.tsx b/packages/dify-ui/src/infotip/index.tsx
new file mode 100644
index 00000000000..cfe90ede469
--- /dev/null
+++ b/packages/dify-ui/src/infotip/index.tsx
@@ -0,0 +1,112 @@
+'use client'
+
+import type * as React from 'react'
+import type { Placement } from '../placement'
+import { Popover as BasePopover } from '@base-ui/react/popover'
+import { cn } from '../cn'
+import { iconButtonVariants } from '../icon-button'
+import { resolveClassName } from '../internals/resolve-class-name'
+import { floatingPopupAnimationClassName } from '../overlay-shared'
+import { parsePlacement } from '../placement'
+
+const iconClassNames = {
+ question: 'i-ri-question-line',
+ information: 'i-ri-information-line',
+ warning: 'i-ri-error-warning-line',
+} as const
+
+const iconSizeClassNames = {
+ small: 'size-3',
+ medium: 'size-3.5',
+ large: 'size-4',
+} as const
+
+const Infotip = BasePopover.Root
+type InfotipProps = BasePopover.Root.Props
+
+type InfotipTriggerProps = Omit<
+ BasePopover.Trigger.Props,
+ 'children' | 'render' | 'nativeButton' | 'aria-label' | 'aria-labelledby'
+> &
+ (
+ | { 'aria-label': string; 'aria-labelledby'?: never }
+ | { 'aria-label'?: never; 'aria-labelledby': string }
+ ) & {
+ iconVariant?: keyof typeof iconClassNames
+ iconSize?: keyof typeof iconSizeClassNames
+ }
+
+function InfotipTrigger({
+ className,
+ iconVariant = 'question',
+ iconSize = 'medium',
+ openOnHover = true,
+ delay = 300,
+ closeDelay = 200,
+ onClick,
+ ...props
+}: InfotipTriggerProps) {
+ return (
+ {
+ event.stopPropagation()
+ onClick?.(event)
+ }}
+ className={(state) =>
+ cn(
+ iconButtonVariants({ variant: null, size: 'xs' }),
+ 'shrink-0 border-0 bg-transparent text-text-quaternary outline-hidden hover:text-text-tertiary',
+ resolveClassName(className, state),
+ )
+ }
+ >
+
+
+ )
+}
+
+type InfotipContentProps = Omit &
+ Pick & {
+ children: React.ReactNode
+ placement?: Placement
+ }
+
+function InfotipContent({
+ placement = 'top',
+ sideOffset = 8,
+ alignOffset = 0,
+ className,
+ ...props
+}: InfotipContentProps) {
+ const { side, align } = parsePlacement(placement)
+ return (
+
+
+
+ cn(
+ 'outline-hidden focus:outline-hidden focus-visible:outline-hidden',
+ floatingPopupAnimationClassName,
+ 'max-w-75 rounded-lg border-[0.5px] border-components-panel-border bg-components-tooltip-bg px-3 py-2 system-xs-regular text-text-secondary shadow-[0px_12px_16px_-4px_var(--color-shadow-shadow-5),0px_4px_6px_-2px_var(--color-shadow-shadow-1)] backdrop-blur-[5px]',
+ resolveClassName(className, state),
+ )
+ }
+ />
+
+
+ )
+}
+
+export { Infotip, InfotipContent, InfotipTrigger }
+export type { InfotipContentProps, InfotipProps, InfotipTriggerProps }
diff --git a/web/AGENTS.md b/web/AGENTS.md
index c4226a6fdba..7dfce633dae 100644
--- a/web/AGENTS.md
+++ b/web/AGENTS.md
@@ -17,7 +17,7 @@ Web owns application-specific requirements and consumes shared architecture guid
- Give save and submit flows a real form boundary with visible labels and accessible errors. Use Dify UI `Form` when its structured submission and validation contract is the owner; otherwise use a native form. Follow the canonical [form contract].
- Follow the canonical [Button contract] and [IconButton contract] for action semantics, loading, accessible names, and primitive composition. Do not add a Web wrapper that hides those contracts.
- Follow [Accessible names and descriptions] when choosing or changing visible labels, ARIA naming, descriptions, or visually hidden text. Web owns localization and feature-specific status announcements; do not redefine the Dify UI naming contract locally.
-- Follow the [Dify UI overlay contract] for primitive selection, portals, focus, and layering. Reuse the Web `Infotip` composite for an info glyph that opens explanatory content. Do not introduce a generic Web wrapper that recreates Dify UI overlay behavior.
+- Follow the [Dify UI overlay contract] for primitive selection, portals, focus, and layering. Use `@langgenius/dify-ui/infotip` for an info glyph that opens explanatory content. Do not introduce a generic Web wrapper that recreates Dify UI overlay behavior.
- For custom SVG icons, follow `../packages/iconify-collections/README.md`; do not add generated React icons under `app/components/base/icons/src/`.
- `docs/test.md` is the single source of truth for Web automated-test policy. Skills may route and execute that policy but must not redefine it.
diff --git a/web/app/components/app/app-access-control/access-control-form.tsx b/web/app/components/app/app-access-control/access-control-form.tsx
index 62dd36cfe9b..14e466147b0 100644
--- a/web/app/components/app/app-access-control/access-control-form.tsx
+++ b/web/app/components/app/app-access-control/access-control-form.tsx
@@ -7,11 +7,11 @@ import type {
import type { AccessMode } from '@/models/access-control'
import { Button } from '@langgenius/dify-ui/button'
import { DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { useId } from 'react'
import { useTranslation } from 'react-i18next'
import { AccessMode as AccessModeValue } from '@/models/access-control'
-import { Infotip } from '../../base/infotip'
import AccessControlDialog from './access-control-dialog'
import AccessControlItem from './access-control-item'
import SpecificGroupsOrMembers, { WebAppSSONotEnabledTip } from './specific-groups-or-members'
@@ -111,15 +111,22 @@ export function AccessControlForm({
{t(($) => $['accessControlDialog.accessItems.anyone'], { ns: 'app' })}
{publicAccessDisabled && (
- $['accessControlDialog.webAppPublicAccessDisabledTip'], {
- ns: 'app',
- })}
- className="h-4 w-4 shrink-0 text-text-warning-secondary hover:text-text-warning-secondary"
- >
- {t(($) => $['accessControlDialog.webAppPublicAccessDisabledTip'], {
- ns: 'app',
- })}
+
+ $['accessControlDialog.webAppPublicAccessDisabledTip'], {
+ ns: 'app',
+ })}
+ className="h-4 w-4 shrink-0 text-text-warning-secondary hover:text-text-warning-secondary"
+ />
+ $['accessControlDialog.webAppPublicAccessDisabledTip'], {
+ ns: 'app',
+ })}
+ >
+ {t(($) => $['accessControlDialog.webAppPublicAccessDisabledTip'], {
+ ns: 'app',
+ })}
+
)}
diff --git a/web/app/components/app/app-access-control/specific-groups-or-members.tsx b/web/app/components/app/app-access-control/specific-groups-or-members.tsx
index cb8a70aaf74..2607df37e25 100644
--- a/web/app/components/app/app-access-control/specific-groups-or-members.tsx
+++ b/web/app/components/app/app-access-control/specific-groups-or-members.tsx
@@ -3,10 +3,10 @@ import type { AccessControlAccount, AccessControlGroup } from '@/models/access-c
import { Avatar } from '@langgenius/dify-ui/avatar'
import { Button } from '@langgenius/dify-ui/button'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useTranslation } from 'react-i18next'
import { LoadingPlaceholder } from '@/app/components/base/loading-placeholder'
import { AccessMode } from '@/models/access-control'
-import { Infotip } from '../../base/infotip'
import AddMemberOrGroupDialog from './add-member-or-group-pop'
export type AccessControlSubjects = {
@@ -222,12 +222,13 @@ export function WebAppSSONotEnabledTip() {
const tip = t(($) => $['accessControlDialog.webAppSSONotEnabledTip'], { ns: 'app' })
return (
-
- {tip}
+
+
+ {tip}
)
}
diff --git a/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx b/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx
index fa8a951ecdd..b730c897ca8 100644
--- a/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx
+++ b/web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx
@@ -4,6 +4,7 @@ import type { ExternalDataTool } from '@/models/common'
import type { PromptRole, PromptVariable } from '@/models/debug'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RiDeleteBinLine, RiErrorWarningFill } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import copy from 'copy-to-clipboard'
@@ -14,7 +15,6 @@ import { useContext } from 'use-context-selector'
import { ADD_EXTERNAL_DATA_TOOL } from '@/app/components/app/configuration/config-var'
import { toast } from '@/app/components/app/configuration/toast'
import { Copy, CopyCheck } from '@/app/components/base/icons/src/vender/line/files'
-import { Infotip } from '@/app/components/base/infotip'
import PromptEditor from '@/app/components/base/prompt-editor'
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
import ConfigContext from '@/context/debug-configuration'
@@ -189,12 +189,17 @@ const AdvancedPromptInput: FC = ({
{t(($) => $['pageTitle.line1'], { ns: 'appDebug' })}
- $.promptTip, { ns: 'appDebug' })}
- className="ml-1"
- popupClassName="w-[180px]"
- >
- {t(($) => $.promptTip, { ns: 'appDebug' })}
+
+ $.promptTip, { ns: 'appDebug' })}
+ className="ml-1"
+ />
+ $.promptTip, { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $.promptTip, { ns: 'appDebug' })}
+
)}
diff --git a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx
index 443d8943d65..d2329f1e29c 100644
--- a/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx
+++ b/web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx
@@ -4,6 +4,7 @@ import type { ExternalDataTool } from '@/models/common'
import type { PromptVariable } from '@/models/debug'
import type { GenRes } from '@/service/debug'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useBoolean } from 'ahooks'
import { noop } from 'es-toolkit/function'
import { produce } from 'immer'
@@ -16,7 +17,6 @@ import AutomaticBtn from '@/app/components/app/configuration/config/automatic/au
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
import { toast } from '@/app/components/app/configuration/toast'
import { useFeaturesStore } from '@/app/components/base/features/hooks'
-import { Infotip } from '@/app/components/base/infotip'
import PromptEditor from '@/app/components/base/prompt-editor'
import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '@/app/components/base/prompt-editor/plugins/update-block'
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
@@ -206,12 +206,17 @@ const Prompt: FC = ({
{title}
{!readonly && (
- $.promptTip, { ns: 'appDebug' })}
- className="ml-1"
- popupClassName="w-[180px]"
- >
- {t(($) => $.promptTip, { ns: 'appDebug' })}
+
+ $.promptTip, { ns: 'appDebug' })}
+ className="ml-1"
+ />
+ $.promptTip, { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $.promptTip, { ns: 'appDebug' })}
+
)}
diff --git a/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx b/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
index d97ac099cce..eb844a55e99 100644
--- a/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
+++ b/web/app/components/app/configuration/config-var/config-modal/form-fields.tsx
@@ -6,6 +6,7 @@ import type { SelectorTranslate } from '@/app/components/app/configuration/utils
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import type { InputVar, UploadFileSetting } from '@/app/components/workflow/types'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import { NumberField, NumberFieldGroup, NumberFieldInput } from '@langgenius/dify-ui/number-field'
import {
@@ -26,7 +27,6 @@ import * as React from 'react'
import { Trans } from 'react-i18next'
import { getStringSelectorTranslate } from '@/app/components/app/configuration/utils'
import { FileUploaderInAttachmentWrapper } from '@/app/components/base/file-uploader'
-import { Infotip } from '@/app/components/base/infotip'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import FileUploadSetting from '@/app/components/workflow/nodes/_base/components/file-upload-setting'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
@@ -409,21 +409,24 @@ const ConfigModalFormFields: FC = ({
-
- $['variableConfig.hiddenDescription']}
- ns="appDebug"
- components={{
- docLink: (
-
- ),
- }}
- />
+
+
+
+ $['variableConfig.hiddenDescription']}
+ ns="appDebug"
+ components={{
+ docLink: (
+
+ ),
+ }}
+ />
+
diff --git a/web/app/components/app/configuration/config-var/index.tsx b/web/app/components/app/configuration/config-var/index.tsx
index 3b85d5b2728..56fbf5e4c02 100644
--- a/web/app/components/app/configuration/config-var/index.tsx
+++ b/web/app/components/app/configuration/config-var/index.tsx
@@ -13,6 +13,7 @@ import {
AlertDialogTitle,
} from '@langgenius/dify-ui/alert-dialog'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useBoolean } from 'ahooks'
import { produce } from 'immer'
import * as React from 'react'
@@ -21,7 +22,6 @@ import { useTranslation } from 'react-i18next'
import { ReactSortable } from 'react-sortablejs'
import { useContext } from 'use-context-selector'
import { toast } from '@/app/components/app/configuration/toast'
-import { Infotip } from '@/app/components/base/infotip'
import { useKeyboardSortable } from '@/app/components/base/keyboard-sortable/use-keyboard-sortable'
import { InputVarType } from '@/app/components/workflow/types'
import ConfigContext from '@/context/debug-configuration'
@@ -315,11 +315,14 @@ const ConfigVar: FC = ({ promptVariables, readonly, onPromptVar
{t(($) => $.variableTitle, { ns: 'appDebug' })}
{!readonly && (
- $.variableTip, { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $.variableTip, { ns: 'appDebug' })}
+
+ $.variableTip, { ns: 'appDebug' })} />
+ $.variableTip, { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $.variableTip, { ns: 'appDebug' })}
+
)}
diff --git a/web/app/components/app/configuration/config-vision/index.tsx b/web/app/components/app/configuration/config-vision/index.tsx
index a4963f45c15..ce199d3ecac 100644
--- a/web/app/components/app/configuration/config-vision/index.tsx
+++ b/web/app/components/app/configuration/config-vision/index.tsx
@@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Switch } from '@langgenius/dify-ui/switch'
import { noop } from 'es-toolkit/function'
import { produce } from 'immer'
@@ -11,7 +12,6 @@ import { useContext } from 'use-context-selector'
// import { Resolution } from '@/types/app'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
import { Vision } from '@/app/components/base/icons/src/vender/features'
-import { Infotip } from '@/app/components/base/infotip'
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
// import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
@@ -75,11 +75,14 @@ const ConfigVision: FC = () => {
{t(($) => $['vision.name'], { ns: 'appDebug' })}
- $['vision.description'], { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['vision.description'], { ns: 'appDebug' })}
+
+ $['vision.description'], { ns: 'appDebug' })} />
+ $['vision.description'], { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['vision.description'], { ns: 'appDebug' })}
+
@@ -89,17 +92,24 @@ const ConfigVision: FC = () => {
{t(($) => $['vision.visionSettings.resolution'], { ns: 'appDebug' })}
-
$['vision.visionSettings.resolutionTooltip'], {
- ns: 'appDebug',
- })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['vision.visionSettings.resolutionTooltip'], { ns: 'appDebug' })
- .split('\n')
- .map((item) => (
- {item}
- ))}
+
+ $['vision.visionSettings.resolutionTooltip'], {
+ ns: 'appDebug',
+ })}
+ />
+ $['vision.visionSettings.resolutionTooltip'], {
+ ns: 'appDebug',
+ })}
+ className="w-[180px]"
+ >
+ {t(($) => $['vision.visionSettings.resolutionTooltip'], { ns: 'appDebug' })
+ .split('\n')
+ .map((item) => (
+ {item}
+ ))}
+
diff --git a/web/app/components/app/configuration/config-vision/param-config-content.tsx b/web/app/components/app/configuration/config-vision/param-config-content.tsx
index ca8fa6548ea..894803e5dee 100644
--- a/web/app/components/app/configuration/config-vision/param-config-content.tsx
+++ b/web/app/components/app/configuration/config-vision/param-config-content.tsx
@@ -3,13 +3,13 @@ import type { FC } from 'react'
import type { FileUpload } from '@/app/components/base/features/types'
import { Field, FieldItem } from '@langgenius/dify-ui/field'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RadioGroup, RadioItem } from '@langgenius/dify-ui/radio-group'
import { produce } from 'immer'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
-import { Infotip } from '@/app/components/base/infotip'
import ParamItem from '@/app/components/base/param-item'
import { Resolution, TransferMethod } from '@/types/app'
@@ -70,17 +70,24 @@ const ParamConfigContent: FC = () => {
{t(($) => $['vision.visionSettings.resolution'], { ns: 'appDebug' })}
-
$['vision.visionSettings.resolutionTooltip'], {
- ns: 'appDebug',
- })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['vision.visionSettings.resolutionTooltip'], { ns: 'appDebug' })
- .split('\n')
- .map((item) => (
- {item}
- ))}
+
+ $['vision.visionSettings.resolutionTooltip'], {
+ ns: 'appDebug',
+ })}
+ />
+ $['vision.visionSettings.resolutionTooltip'], {
+ ns: 'appDebug',
+ })}
+ className="w-[180px]"
+ >
+ {t(($) => $['vision.visionSettings.resolutionTooltip'], { ns: 'appDebug' })
+ .split('\n')
+ .map((item) => (
+ {item}
+ ))}
+
diff --git a/web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx b/web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx
index 50b697af0ca..f898ccb870a 100644
--- a/web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx
+++ b/web/app/components/app/configuration/config/agent/agent-setting/item-panel.tsx
@@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
-import { Infotip } from '@/app/components/base/infotip'
type Props = Readonly<{
className?: string
@@ -23,8 +23,11 @@ const ItemPanel: FC
= ({ className, icon, name, description, children })
{icon}
{name}
-
- {description}
+
+
+
+ {description}
+
{children}
diff --git a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
index 6efe0f31e88..7f0e4cd2ef6 100644
--- a/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
+++ b/web/app/components/app/configuration/config/agent/agent-tools/index.tsx
@@ -6,6 +6,7 @@ import type { ToolWithProvider } from '@/app/components/workflow/types'
import type { AgentTool } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Switch } from '@langgenius/dify-ui/switch'
@@ -21,7 +22,6 @@ import { OperationButton } from '@/app/components/app/configuration/base/operati
import AppIcon from '@/app/components/base/app-icon'
import { DefaultToolIcon } from '@/app/components/base/icons/src/public/other'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
-import { Infotip } from '@/app/components/base/infotip'
import { parseToolProviderType } from '@/app/components/tools/provider-type'
import { CollectionType } from '@/app/components/tools/types'
import {
@@ -163,8 +163,15 @@ const AgentTools: FC = () => {
title={
{t(($) => $['agent.tools.name'], { ns: 'appDebug' })}
- $['agent.tools.description'], { ns: 'appDebug' })}>
- {t(($) => $['agent.tools.description'], { ns: 'appDebug' })}
+
+ $['agent.tools.description'], { ns: 'appDebug' })}
+ />
+ $['agent.tools.description'], { ns: 'appDebug' })}
+ >
+ {t(($) => $['agent.tools.description'], { ns: 'appDebug' })}
+
}
@@ -239,24 +246,26 @@ const AgentTools: FC = () => {
{item.tool_label}
{!item.isDeleted && !readonly && (
-
-
-
{item.tool_name}
-
- {t(($) => $.toolNameUsageTip, { ns: 'tools' })}
+
+
+
+
+
{item.tool_name}
+
+ {t(($) => $.toolNameUsageTip, { ns: 'tools' })}
+
+
-
-
+
)}
diff --git a/web/app/components/app/configuration/config/config-audio.tsx b/web/app/components/app/configuration/config/config-audio.tsx
index 436595c2a5a..ca671abc21b 100644
--- a/web/app/components/app/configuration/config/config-audio.tsx
+++ b/web/app/components/app/configuration/config/config-audio.tsx
@@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Switch } from '@langgenius/dify-ui/switch'
import { produce } from 'immer'
import * as React from 'react'
@@ -8,7 +9,6 @@ import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
import { Microphone01 } from '@/app/components/base/icons/src/vender/features'
-import { Infotip } from '@/app/components/base/infotip'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import ConfigContext from '@/context/debug-configuration'
@@ -54,11 +54,16 @@ const ConfigAudio: FC = () => {
{t(($) => $['feature.audioUpload.title'], { ns: 'appDebug' })}
- $['feature.audioUpload.description'], { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['feature.audioUpload.description'], { ns: 'appDebug' })}
+
+ $['feature.audioUpload.description'], { ns: 'appDebug' })}
+ />
+ $['feature.audioUpload.description'], { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['feature.audioUpload.description'], { ns: 'appDebug' })}
+
{!readonly && (
diff --git a/web/app/components/app/configuration/config/config-document.tsx b/web/app/components/app/configuration/config/config-document.tsx
index 33c81eb34b6..381e7081c63 100644
--- a/web/app/components/app/configuration/config/config-document.tsx
+++ b/web/app/components/app/configuration/config/config-document.tsx
@@ -1,5 +1,6 @@
'use client'
import type { FC } from 'react'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Switch } from '@langgenius/dify-ui/switch'
import { produce } from 'immer'
import * as React from 'react'
@@ -8,7 +9,6 @@ import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
import { Document } from '@/app/components/base/icons/src/vender/features'
-import { Infotip } from '@/app/components/base/infotip'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import ConfigContext from '@/context/debug-configuration'
@@ -55,11 +55,16 @@ const ConfigDocument: FC = () => {
{t(($) => $['feature.documentUpload.title'], { ns: 'appDebug' })}
- $['feature.documentUpload.description'], { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['feature.documentUpload.description'], { ns: 'appDebug' })}
+
+ $['feature.documentUpload.description'], { ns: 'appDebug' })}
+ />
+ $['feature.documentUpload.description'], { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['feature.documentUpload.description'], { ns: 'appDebug' })}
+
{!readonly && (
diff --git a/web/app/components/app/configuration/dataset-config/context-var/index.tsx b/web/app/components/app/configuration/dataset-config/context-var/index.tsx
index 29933eb27ff..8bb5926953c 100644
--- a/web/app/components/app/configuration/dataset-config/context-var/index.tsx
+++ b/web/app/components/app/configuration/dataset-config/context-var/index.tsx
@@ -2,10 +2,10 @@
import type { FC } from 'react'
import type { Props } from './var-picker'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { BracketsX } from '@/app/components/base/icons/src/vender/line/development'
-import { Infotip } from '@/app/components/base/infotip'
import VarPicker from './var-picker'
const ContextVar: FC = (props) => {
@@ -29,11 +29,16 @@ const ContextVar: FC = (props) => {
{t(($) => $['feature.dataSet.queryVariable.title'], { ns: 'appDebug' })}
- $['feature.dataSet.queryVariable.tip'], { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['feature.dataSet.queryVariable.tip'], { ns: 'appDebug' })}
+
+ $['feature.dataSet.queryVariable.tip'], { ns: 'appDebug' })}
+ />
+ $['feature.dataSet.queryVariable.tip'], { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['feature.dataSet.queryVariable.tip'], { ns: 'appDebug' })}
+
diff --git a/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx b/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx
index 0dd96d4e13b..beae8668451 100644
--- a/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx
+++ b/web/app/components/app/configuration/dataset-config/params-config/config-content.tsx
@@ -6,12 +6,12 @@ import type { ModelConfig } from '@/app/components/workflow/types'
import type { DataSet } from '@/models/datasets'
import type { DatasetConfigs } from '@/models/debug'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { Switch } from '@langgenius/dify-ui/switch'
import { memo, useCallback, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from '@/app/components/app/configuration/toast'
-import { Infotip } from '@/app/components/base/infotip'
import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
import TopKItem from '@/app/components/base/param-item/top-k-item'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
@@ -244,12 +244,11 @@ const ConfigContent: FC = ({
onClick={() => handleRerankModeChange(option.value)}
>
{option.label}
-
- {option.tips}
+
+
+
+ {option.tips}
+
))}
@@ -268,12 +267,17 @@ const ConfigContent: FC = ({
{t(($) => $['modelProvider.rerankModel.key'], { ns: 'common' })}
- $['modelProvider.rerankModel.tip'], { ns: 'common' })}
- className="ml-1"
- popupClassName="w-[200px]"
- >
- {t(($) => $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+
+ $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+ className="ml-1"
+ />
+ $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+ className="w-[200px]"
+ >
+ {t(($) => $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+
{showRerankModel && (
@@ -344,10 +348,15 @@ const ConfigContent: FC = ({
{t(($) => $['modelProvider.systemReasoningModel.key'], { ns: 'common' })}
- $['modelProvider.systemReasoningModel.tip'], { ns: 'common' })}
- >
- {t(($) => $['modelProvider.systemReasoningModel.tip'], { ns: 'common' })}
+
+ $['modelProvider.systemReasoningModel.tip'], { ns: 'common' })}
+ />
+ $['modelProvider.systemReasoningModel.tip'], { ns: 'common' })}
+ >
+ {t(($) => $['modelProvider.systemReasoningModel.tip'], { ns: 'common' })}
+
= ({
{title}
{explanation && (
-
- {explanation}
+
+
+
+ {explanation}
+
)}
diff --git a/web/app/components/base/chat/chat/chat-input-area/index.tsx b/web/app/components/base/chat/chat/chat-input-area/index.tsx
index f404e9025a8..f0758ea7817 100644
--- a/web/app/components/base/chat/chat/chat-input-area/index.tsx
+++ b/web/app/components/base/chat/chat/chat-input-area/index.tsx
@@ -5,6 +5,7 @@ import type { InputForm } from '../type'
import type { FileUpload } from '@/app/components/base/features/types'
import type { SpeechToTextTarget } from '@/app/components/base/voice-input/types'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { noop } from 'es-toolkit/function'
import { decode } from 'html-entities'
import { useCallback, useRef, useState } from 'react'
@@ -14,7 +15,6 @@ import FeatureBar from '@/app/components/base/features/new-feature-panel/feature
import { FileListInChatInput } from '@/app/components/base/file-uploader'
import { useFile } from '@/app/components/base/file-uploader/hooks'
import { FileContextProvider, useFileStore } from '@/app/components/base/file-uploader/store'
-import { Infotip } from '@/app/components/base/infotip'
import VoiceInput from '@/app/components/base/voice-input'
import { toast } from '@/app/notifications'
import { TransferMethod } from '@/types/app'
@@ -379,13 +379,18 @@ const ChatInputArea = ({
{footerNotice}
{shouldShowFooterNoticeTooltip && (
-
- {footerNoticeTooltip}
+
+
+
+ {footerNoticeTooltip}
+
)}
diff --git a/web/app/components/base/features/new-feature-panel/annotation-reply/config-param.tsx b/web/app/components/base/features/new-feature-panel/annotation-reply/config-param.tsx
index 2915ed62470..e55173791f1 100644
--- a/web/app/components/base/features/new-feature-panel/annotation-reply/config-param.tsx
+++ b/web/app/components/base/features/new-feature-panel/annotation-reply/config-param.tsx
@@ -1,7 +1,7 @@
'use client'
import type { FC } from 'react'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
-import { Infotip } from '@/app/components/base/infotip'
export const Item: FC<{ title: string; tooltip: string; children: React.JSX.Element }> = ({
title,
@@ -12,8 +12,11 @@ export const Item: FC<{ title: string; tooltip: string; children: React.JSX.Elem
{title}
-
- {tooltip}
+
+
+
+ {tooltip}
+
{children}
diff --git a/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx b/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
index 743d0a3a1e4..2860dcc139f 100644
--- a/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
+++ b/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
@@ -5,6 +5,7 @@ import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { Dialog, DialogContent } from '@langgenius/dify-ui/dialog'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { useBoolean } from 'ahooks'
import { produce } from 'immer'
@@ -14,7 +15,6 @@ import { useTranslation } from 'react-i18next'
import { ReactSortable } from 'react-sortablejs'
import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var'
import { getInputKeys } from '@/app/components/base/block-input'
-import { Infotip } from '@/app/components/base/infotip'
import { useKeyboardSortable } from '@/app/components/base/keyboard-sortable/use-keyboard-sortable'
import PromptEditor from '@/app/components/base/prompt-editor'
import { checkKeys, getNewVar } from '@/utils/var'
@@ -147,14 +147,21 @@ const OpeningSettingModal = ({
{t(($) => $['openingStatement.openingQuestion'], { ns: 'appDebug' })}
-
$['openingStatement.openingQuestionDescription'], {
- ns: 'appDebug',
- })}
- className="size-3.5"
- popupClassName="max-w-[220px] system-sm-regular"
- >
- {t(($) => $['openingStatement.openingQuestionDescription'], { ns: 'appDebug' })}
+
+ $['openingStatement.openingQuestionDescription'], {
+ ns: 'appDebug',
+ })}
+ className="size-3.5"
+ />
+ $['openingStatement.openingQuestionDescription'], {
+ ns: 'appDebug',
+ })}
+ className="max-w-[220px] system-sm-regular"
+ >
+ {t(($) => $['openingStatement.openingQuestionDescription'], { ns: 'appDebug' })}
+
diff --git a/web/app/components/base/features/new-feature-panel/feature-card.tsx b/web/app/components/base/features/new-feature-panel/feature-card.tsx
index b5deed9e23d..8ab0bb2ef55 100644
--- a/web/app/components/base/features/new-feature-panel/feature-card.tsx
+++ b/web/app/components/base/features/new-feature-panel/feature-card.tsx
@@ -1,6 +1,6 @@
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Switch } from '@langgenius/dify-ui/switch'
import * as React from 'react'
-import { Infotip } from '@/app/components/base/infotip'
type Props = Readonly<{
icon: React.ReactNode
@@ -40,11 +40,14 @@ const FeatureCard = ({
{title}
{!!tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
index 22c8389616c..d74fc5e4d8a 100644
--- a/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
+++ b/web/app/components/base/features/new-feature-panel/text-to-speech/param-config-content.tsx
@@ -1,6 +1,7 @@
'use client'
import type { OnFeaturesChange } from '@/app/components/base/features/types'
import type { I18nKeysWithPrefix } from '@/types/i18n'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
Select,
SelectItem,
@@ -19,7 +20,6 @@ import { useTranslation } from 'react-i18next'
import { replace } from 'string-ts'
import { AudioBtn } from '@/app/components/base/audio-btn'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
-import { Infotip } from '@/app/components/base/infotip'
import { languages } from '@/i18n/language'
import { useParams } from '@/next/navigation'
import { consoleQuery } from '@/service/console'
@@ -107,15 +107,20 @@ const VoiceParamConfig = ({ onClose, onChange }: VoiceParamConfigProps) => {
{t(($) => $['voice.voiceSettings.language'], { ns: 'appDebug' })}
-
$['voice.voiceSettings.resolutionTooltip'], { ns: 'appDebug' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['voice.voiceSettings.resolutionTooltip'], { ns: 'appDebug' })
- .split('\n')
- .map((item) => (
- {item}
- ))}
+
+ $['voice.voiceSettings.resolutionTooltip'], { ns: 'appDebug' })}
+ />
+ $['voice.voiceSettings.resolutionTooltip'], { ns: 'appDebug' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['voice.voiceSettings.resolutionTooltip'], { ns: 'appDebug' })
+ .split('\n')
+ .map((item) => (
+ {item}
+ ))}
+
diff --git a/web/app/components/base/form/components/field/upload-method.tsx b/web/app/components/base/form/components/field/upload-method.tsx
index b086e532342..86c9303f190 100644
--- a/web/app/components/base/form/components/field/upload-method.tsx
+++ b/web/app/components/base/form/components/field/upload-method.tsx
@@ -2,10 +2,10 @@ import type { LabelProps } from '../label'
import { cn } from '@langgenius/dify-ui/cn'
import { Field, FieldItem, FieldLabel } from '@langgenius/dify-ui/field'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RadioGroup, RadioItem } from '@langgenius/dify-ui/radio-group'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { TransferMethod } from '@/types/app'
import { useFieldContext } from '../..'
@@ -72,12 +72,11 @@ const UploadMethodField = ({ label, labelOptions, className }: UploadMethodField
*
)}
{labelOptions?.tooltip && (
-
- {labelOptions.tooltip}
+
+
+
+ {labelOptions.tooltip}
+
)}
diff --git a/web/app/components/base/form/components/label.tsx b/web/app/components/base/form/components/label.tsx
index 60f3d35028f..1b9dc4863c7 100644
--- a/web/app/components/base/form/components/label.tsx
+++ b/web/app/components/base/form/components/label.tsx
@@ -1,6 +1,6 @@
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '../../infotip'
export type LabelProps = {
htmlFor: string
@@ -28,8 +28,11 @@ const Label = ({ htmlFor, label, isRequired, showOptional, tooltip, className }:
*
)}
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/base/infotip/__tests__/index.spec.tsx b/web/app/components/base/infotip/__tests__/index.spec.tsx
deleted file mode 100644
index 94505531f93..00000000000
--- a/web/app/components/base/infotip/__tests__/index.spec.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import type { ReactNode } from 'react'
-import { render, screen, waitFor } from '@testing-library/react'
-import userEvent from '@testing-library/user-event'
-import { createPortal } from 'react-dom'
-import { Infotip } from '../index'
-
-function ClickBoundary({ children, onClick }: { children: ReactNode; onClick: () => void }) {
- return (
-
- )
-}
-
-describe('Infotip', () => {
- it('should open with keyboard activation', async () => {
- const user = userEvent.setup()
- render(Rate limit details)
-
- screen.getByRole('button', { name: 'Rate limits' }).focus()
- await user.keyboard('{Enter}')
-
- expect(await screen.findByRole('dialog')).toHaveTextContent('Rate limit details')
- })
-
- it('should close the dialog with Escape', async () => {
- const user = userEvent.setup()
- render(Rate limit details)
-
- await user.click(screen.getByRole('button', { name: 'Rate limits' }))
- expect(await screen.findByRole('dialog')).toBeInTheDocument()
-
- await user.keyboard('{Escape}')
-
- await waitFor(() => {
- expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
- })
- })
-
- it('should not propagate trigger clicks', async () => {
- const user = userEvent.setup()
- const parentClick = vi.fn()
- render(
-
- Rate limit details
- ,
- )
-
- await user.click(screen.getByRole('button', { name: 'Rate limits' }))
-
- expect(parentClick).not.toHaveBeenCalled()
- })
-})
diff --git a/web/app/components/base/infotip/index.tsx b/web/app/components/base/infotip/index.tsx
deleted file mode 100644
index b7d3d9e9665..00000000000
--- a/web/app/components/base/infotip/index.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-'use client'
-
-import type { MouseEvent, ReactNode } from 'react'
-import { cn } from '@langgenius/dify-ui/cn'
-import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
-
-const iconClassNames = {
- question: 'i-ri-question-line',
- information: 'i-ri-information-line',
- warning: 'i-ri-error-warning-line',
-} as const
-
-const iconSizeClassNames = {
- small: 'size-3',
- medium: 'size-3.5',
- large: 'size-4',
-} as const
-
-type InfotipIconVariant = keyof typeof iconClassNames
-type InfotipIconSize = keyof typeof iconSizeClassNames
-
-/**
- * Infotip — an info glyph that reveals a long-form explanation on hover / keyboard activation / tap.
- *
- * Implements the pattern Base UI calls an "infotip":
- * https://base-ui.com/react/components/tooltip#infotips
- *
- * > "Popups that open when hovering an info icon should use Popover with the
- * > `openOnHover` prop on the trigger instead of a tooltip. This way, touch
- * > users and screen reader users can access the content."
- *
- * Use whenever the trigger is an info glyph whose sole purpose is to open a
- * popup (help text, documentation-style explanation). Do NOT use `Tooltip` for
- * this — Tooltip is reserved for ephemeral, non-interactive visual labels that
- * are unreachable on touch devices and by screen readers.
- *
- * Base UI rule of thumb:
- *
- * > "If the trigger's purpose is to open the popup itself, it's a popover.
- * > If the trigger's purpose is unrelated to opening the popup, it's a tooltip."
- *
- * For hover-revealed supplementary previews of a link / row trigger that has
- * its own primary click destination, use `PreviewCard` instead.
- */
-
-type InfotipProps = {
- /** Popup content. Rich nodes are allowed. */
- children: ReactNode
- /** Accessible name for the icon-only trigger. */
- 'aria-label': string
- /** Extra classes on the trigger for contextual layout and color. */
- className?: string
- /** Icon glyph. Defaults to `question`. */
- iconVariant?: InfotipIconVariant
- /** Icon size. Defaults to `medium` (14px). */
- iconSize?: InfotipIconSize
- /** Extra classes on the popup body (width / padding / whitespace overrides). */
- popupClassName?: string
- /** Distance between the trigger and popup. */
- sideOffset?: number
-}
-
-export function Infotip({
- children,
- 'aria-label': ariaLabel,
- className,
- iconVariant = 'question',
- iconSize = 'medium',
- popupClassName,
- sideOffset,
-}: InfotipProps) {
- const handleClick = (event: MouseEvent) => {
- event.stopPropagation()
- }
-
- return (
-
-
-
-
-
- {children}
-
-
- )
-}
diff --git a/web/app/components/base/param-item/index.tsx b/web/app/components/base/param-item/index.tsx
index c9469e81313..2d4bb0ba583 100644
--- a/web/app/components/base/param-item/index.tsx
+++ b/web/app/components/base/param-item/index.tsx
@@ -1,6 +1,7 @@
'use client'
import type { FC } from 'react'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
NumberField,
NumberFieldControls,
@@ -18,7 +19,6 @@ import {
SliderTrack,
} from '@langgenius/dify-ui/slider'
import { Switch } from '@langgenius/dify-ui/switch'
-import { Infotip } from '@/app/components/base/infotip'
type Props = Readonly<{
className?: string
@@ -71,8 +71,11 @@ const ParamItem: FC = ({
)}
{name}
{!noTooltip && tip && (
-
- {tip}
+
+
+
+ {tip}
+
)}
diff --git a/web/app/components/billing/priority-label/index.tsx b/web/app/components/billing/priority-label/index.tsx
index e5be6dd8d7c..530b3ff228c 100644
--- a/web/app/components/billing/priority-label/index.tsx
+++ b/web/app/components/billing/priority-label/index.tsx
@@ -1,9 +1,10 @@
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RiAedFill } from '@remixicon/react'
import { useQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
+import { useId } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { deploymentEditionAtom } from '@/features/system-features/state'
import { consoleQuery } from '@/service/console'
@@ -13,6 +14,7 @@ type PriorityLabelProps = {
const PriorityLabel = ({ className }: PriorityLabelProps) => {
const { t } = useTranslation()
+ const titleId = useId()
const deploymentEdition = useAtomValue(deploymentEditionAtom)
const { data: plan } = useQuery(
consoleQuery.features.get.queryOptions({
@@ -33,18 +35,21 @@ const PriorityLabel = ({ className }: PriorityLabelProps) => {
)}
{t(($) => $[`plansCommon.priority.${label}`], { ns: 'billing' })}
- $['plansCommon.documentProcessingPriority'], { ns: 'billing' })}
- >
-
- {t(($) => $['plansCommon.documentProcessingPriority'], { ns: 'billing' })}:{' '}
- {t(($) => $[`plansCommon.priority.${label}`], { ns: 'billing' })}
-
- {label !== 'top-priority' && (
-
- {t(($) => $['plansCommon.documentProcessingPriorityTip'], { ns: 'billing' })}
+
+ $['plansCommon.documentProcessingPriority'], { ns: 'billing' })}
+ />
+
+
+ {t(($) => $['plansCommon.documentProcessingPriority'], { ns: 'billing' })}:{' '}
+ {t(($) => $[`plansCommon.priority.${label}`], { ns: 'billing' })}
- )}
+ {label !== 'top-priority' && (
+
+ {t(($) => $['plansCommon.documentProcessingPriorityTip'], { ns: 'billing' })}
+
+ )}
+
)
diff --git a/web/app/components/billing/usage-info/index.tsx b/web/app/components/billing/usage-info/index.tsx
index 3aed8589b50..b218c759f34 100644
--- a/web/app/components/billing/usage-info/index.tsx
+++ b/web/app/components/billing/usage-info/index.tsx
@@ -2,11 +2,11 @@
import type { MeterTone } from '@langgenius/dify-ui/meter'
import type { ComponentType, FC, ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Meter, MeterIndicator, MeterTrack } from '@langgenius/dify-ui/meter'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { NUM_INFINITE } from '../config'
type Props = Readonly<{
@@ -167,8 +167,11 @@ const UsageInfo: FC = ({
{name}
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/datasets/common/retrieval-param-config/index.tsx b/web/app/components/datasets/common/retrieval-param-config/index.tsx
index 12095534151..bfb79e78d97 100644
--- a/web/app/components/datasets/common/retrieval-param-config/index.tsx
+++ b/web/app/components/datasets/common/retrieval-param-config/index.tsx
@@ -2,6 +2,7 @@
import type { FC } from 'react'
import type { RetrievalConfig } from '@/types/app'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { Switch } from '@langgenius/dify-ui/switch'
import * as React from 'react'
@@ -9,7 +10,6 @@ import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import WeightedScore from '@/app/components/app/configuration/dataset-config/params-config/weighted-score'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
-import { Infotip } from '@/app/components/base/infotip'
import ScoreThresholdItem from '@/app/components/base/param-item/score-threshold-item'
import TopKItem from '@/app/components/base/param-item/top-k-item'
import RadioCard from '@/app/components/base/radio-card'
@@ -128,11 +128,16 @@ const RetrievalParamConfig: FC = ({
{t(($) => $['modelProvider.rerankModel.key'], { ns: 'common' })}
- $['modelProvider.rerankModel.tip'], { ns: 'common' })}
- popupClassName="w-[200px]"
- >
- {t(($) => $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+
+ $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+ />
+ $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+ className="w-[200px]"
+ >
+ {t(($) => $['modelProvider.rerankModel.tip'], { ns: 'common' })}
+
diff --git a/web/app/components/datasets/create-from-pipeline/list/template-card/details/index.tsx b/web/app/components/datasets/create-from-pipeline/list/template-card/details/index.tsx
index a366e0c2283..86c8348e0e8 100644
--- a/web/app/components/datasets/create-from-pipeline/list/template-card/details/index.tsx
+++ b/web/app/components/datasets/create-from-pipeline/list/template-card/details/index.tsx
@@ -1,11 +1,11 @@
import type { AppIconType } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RiAddLine, RiCloseLine } from '@remixicon/react'
import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import AppIcon from '@/app/components/base/app-icon'
-import { Infotip } from '@/app/components/base/infotip'
import { LoadingPlaceholder } from '@/app/components/base/loading-placeholder'
import WorkflowPreview from '@/app/components/workflow/workflow-preview'
import { usePipelineTemplateById } from '@/service/use-pipeline'
@@ -99,11 +99,16 @@ const Details = ({ id, type, onApplyTemplate, onClose }: DetailsProps) => {
{t(($) => $['details.structure'], { ns: 'datasetPipeline' })}
- $['details.structureTooltip'], { ns: 'datasetPipeline' })}
- popupClassName="max-w-[240px]"
- >
- {t(($) => $['details.structureTooltip'], { ns: 'datasetPipeline' })}
+
+ $['details.structureTooltip'], { ns: 'datasetPipeline' })}
+ />
+ $['details.structureTooltip'], { ns: 'datasetPipeline' })}
+ className="max-w-[240px]"
+ >
+ {t(($) => $['details.structureTooltip'], { ns: 'datasetPipeline' })}
+
diff --git a/web/app/components/datasets/create/embedding-process/indexing-progress-item.tsx b/web/app/components/datasets/create/embedding-process/indexing-progress-item.tsx
index bcd57b541dc..a44c49f49df 100644
--- a/web/app/components/datasets/create/embedding-process/indexing-progress-item.tsx
+++ b/web/app/components/datasets/create/embedding-process/indexing-progress-item.tsx
@@ -1,9 +1,9 @@
import type { FC } from 'react'
import type { IndexingStatusResponse } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RiCheckboxCircleFill } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import NotionIcon from '@/app/components/base/notion-icon'
import PriorityLabel from '@/app/components/billing/priority-label'
import { DataSourceType } from '@/models/datasets'
@@ -28,15 +28,20 @@ const StatusIcon: FC<{ status: string; error?: string }> = ({ status, error }) =
const errorLabel = error || t(($) => $.error, { ns: 'common' })
return (
- $.error, { ns: 'common' })}
- iconVariant="warning"
- iconSize="large"
- className="text-text-destructive"
- popupClassName="wrap-anywhere whitespace-pre-wrap"
- sideOffset={4}
- >
- {errorLabel}
+
+ $.error, { ns: 'common' })}
+ iconVariant="warning"
+ iconSize="large"
+ className="text-text-destructive"
+ />
+ $.error, { ns: 'common' })}
+ className="wrap-anywhere whitespace-pre-wrap"
+ sideOffset={4}
+ >
+ {errorLabel}
+
)
}
diff --git a/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx b/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx
index be4521f4074..320d6566435 100644
--- a/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx
+++ b/web/app/components/datasets/create/step-two/components/general-chunking-options.tsx
@@ -7,11 +7,11 @@ import type {
} from '@/models/datasets'
import { Button } from '@langgenius/dify-ui/button'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { RiAlertFill, RiSearchEyeLine } from '@remixicon/react'
import { useSuspenseQuery } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import SummaryIndexSetting from '@/app/components/datasets/settings/summary-index-setting'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
import { ChunkingMode } from '@/models/datasets'
@@ -189,11 +189,16 @@ export const GeneralChunkingOptions: FC = ({
onSelect={onDocLanguageChange}
disabled={currentDocForm !== ChunkingMode.qa}
/>
- $['stepTwo.QATip'], { ns: 'datasetCreation' })}
- className="size-3.5"
- >
- {t(($) => $['stepTwo.QATip'], { ns: 'datasetCreation' })}
+
+ $['stepTwo.QATip'], { ns: 'datasetCreation' })}
+ className="size-3.5"
+ />
+ $['stepTwo.QATip'], { ns: 'datasetCreation' })}
+ >
+ {t(($) => $['stepTwo.QATip'], { ns: 'datasetCreation' })}
+
{currentDocForm === ChunkingMode.qa && (
diff --git a/web/app/components/datasets/create/step-two/components/inputs.tsx b/web/app/components/datasets/create/step-two/components/inputs.tsx
index 2f6cfc3595b..6e540da8a7c 100644
--- a/web/app/components/datasets/create/step-two/components/inputs.tsx
+++ b/web/app/components/datasets/create/step-two/components/inputs.tsx
@@ -6,6 +6,7 @@ import type {
} from '@langgenius/dify-ui/number-field'
import type { FC, PropsWithChildren, ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import {
NumberField,
@@ -18,7 +19,6 @@ import {
} from '@langgenius/dify-ui/number-field'
import { useId, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { env } from '@/env'
const FormField: FC> = (props) => {
@@ -54,11 +54,16 @@ export const DelimiterInput: FC<
- $['stepTwo.separatorTip'], { ns: 'datasetCreation' })}
- popupClassName="max-w-[200px]"
- >
- {tooltip || t(($) => $['stepTwo.separatorTip'], { ns: 'datasetCreation' })}
+
+ $['stepTwo.separatorTip'], { ns: 'datasetCreation' })}
+ />
+ $['stepTwo.separatorTip'], { ns: 'datasetCreation' })}
+ className="max-w-[200px]"
+ >
+ {tooltip || t(($) => $['stepTwo.separatorTip'], { ns: 'datasetCreation' })}
+
}
@@ -185,11 +190,16 @@ export const OverlapInput: FC = (props) => {
label={
{label}
- $['stepTwo.overlapTip'], { ns: 'datasetCreation' })}
- popupClassName="max-w-[200px]"
- >
- {t(($) => $['stepTwo.overlapTip'], { ns: 'datasetCreation' })}
+
+ $['stepTwo.overlapTip'], { ns: 'datasetCreation' })}
+ />
+ $['stepTwo.overlapTip'], { ns: 'datasetCreation' })}
+ className="max-w-[200px]"
+ >
+ {t(($) => $['stepTwo.overlapTip'], { ns: 'datasetCreation' })}
+
}
diff --git a/web/app/components/datasets/create/website/base/checkbox-with-label.tsx b/web/app/components/datasets/create/website/base/checkbox-with-label.tsx
index b41a9b408b1..d657c1dc4f4 100644
--- a/web/app/components/datasets/create/website/base/checkbox-with-label.tsx
+++ b/web/app/components/datasets/create/website/base/checkbox-with-label.tsx
@@ -1,7 +1,7 @@
'use client'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
import { cn } from '@langgenius/dify-ui/cn'
-import { Infotip } from '@/app/components/base/infotip'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
type Props = Readonly<{
className?: string
@@ -35,8 +35,11 @@ export default function CheckboxWithLabel({
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/datasets/create/website/base/field.tsx b/web/app/components/datasets/create/website/base/field.tsx
index 24d9421d7a4..817ec0e00a3 100644
--- a/web/app/components/datasets/create/website/base/field.tsx
+++ b/web/app/components/datasets/create/website/base/field.tsx
@@ -1,8 +1,8 @@
'use client'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
-import { Infotip } from '@/app/components/base/infotip'
import Input from './text-input'
type Props = Readonly<{
@@ -43,8 +43,11 @@ const Field: FC = ({
*
)}
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/checkbox-with-label.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/checkbox-with-label.tsx
index d2a414fd40f..c92ad55a703 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/checkbox-with-label.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/checkbox-with-label.tsx
@@ -1,7 +1,7 @@
'use client'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
import { cn } from '@langgenius/dify-ui/cn'
-import { Infotip } from '@/app/components/base/infotip'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
type CheckboxWithLabelProps = {
className?: string
@@ -35,8 +35,11 @@ export default function CheckboxWithLabel({
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/datasets/documents/status-item/index.tsx b/web/app/components/datasets/documents/status-item/index.tsx
index a6451799d8a..ef304ba00aa 100644
--- a/web/app/components/datasets/documents/status-item/index.tsx
+++ b/web/app/components/datasets/documents/status-item/index.tsx
@@ -3,6 +3,7 @@ import type { OperationName } from '../types'
import type { CommonResponse } from '@/models/common'
import type { DocumentDisplayStatus } from '@/models/datasets'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Switch } from '@langgenius/dify-ui/switch'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
@@ -10,7 +11,6 @@ import { useDebounceFn } from 'ahooks'
import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { toast } from '@/app/notifications'
import {
useDocumentDelete,
@@ -109,12 +109,11 @@ const StatusItem = ({
{statusItem.text}
{errorMessage && (
-
- {errorMessage}
+
+
+
+ {errorMessage}
+
)}
{scene === 'detail' && (
diff --git a/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx b/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx
index 3f4d93e8dd2..406dbac2ced 100644
--- a/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx
+++ b/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx
@@ -5,6 +5,7 @@ import { Button } from '@langgenius/dify-ui/button'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
import { Dialog, DialogClose, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { produce } from 'immer'
import * as React from 'react'
@@ -12,7 +13,6 @@ import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from '@/app/notifications'
import { useCreateMetaData } from '@/service/knowledge/use-metadata'
-import { Infotip } from '../../../base/infotip'
import useCheckMetadataName from '../hooks/use-check-metadata-name'
import { DatasetMetadataPicker } from '../metadata-dataset/dataset-metadata-picker'
import { UpdateType } from '../types'
@@ -204,14 +204,21 @@ const EditMetadataBatchModal: FC = ({
{t(($) => $[`${i18nPrefix}.applyToAllSelectDocument`], { ns: 'dataset' })}
- $[`${i18nPrefix}.applyToAllSelectDocumentTip`], {
- ns: 'dataset',
- })}
- className="p-px text-text-tertiary"
- popupClassName="max-w-[240px]"
- >
- {t(($) => $[`${i18nPrefix}.applyToAllSelectDocumentTip`], { ns: 'dataset' })}
+
+ $[`${i18nPrefix}.applyToAllSelectDocumentTip`], {
+ ns: 'dataset',
+ })}
+ className="p-px text-text-tertiary"
+ />
+ $[`${i18nPrefix}.applyToAllSelectDocumentTip`], {
+ ns: 'dataset',
+ })}
+ className="max-w-[240px]"
+ >
+ {t(($) => $[`${i18nPrefix}.applyToAllSelectDocumentTip`], { ns: 'dataset' })}
+
diff --git a/web/app/components/datasets/metadata/metadata-dataset/dataset-metadata-drawer.tsx b/web/app/components/datasets/metadata/metadata-dataset/dataset-metadata-drawer.tsx
index 4098b01dc05..71892727050 100644
--- a/web/app/components/datasets/metadata/metadata-dataset/dataset-metadata-drawer.tsx
+++ b/web/app/components/datasets/metadata/metadata-dataset/dataset-metadata-drawer.tsx
@@ -23,6 +23,7 @@ import {
DrawerTitle,
DrawerViewport,
} from '@langgenius/dify-ui/drawer'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import { Switch } from '@langgenius/dify-ui/switch'
import { RiAddLine, RiDeleteBinLine, RiEditLine } from '@remixicon/react'
@@ -30,7 +31,6 @@ import { useBoolean, useHover } from 'ahooks'
import * as React from 'react'
import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { CreateMetadataModal } from '@/app/components/datasets/metadata/metadata-dataset/create-metadata-modal'
import { toast } from '@/app/notifications'
import { getIconClassName } from '../utils/get-icon'
@@ -265,11 +265,20 @@ const DatasetMetadataDrawer: FC
= ({
{t(($) => $[`${i18nPrefix}.builtIn`], { ns: 'dataset' })}
- $[`${i18nPrefix}.builtInDescription`], { ns: 'dataset' })}
- popupClassName="max-w-[100px]"
- >
- {t(($) => $[`${i18nPrefix}.builtInDescription`], { ns: 'dataset' })}
+
+ $[`${i18nPrefix}.builtInDescription`], {
+ ns: 'dataset',
+ })}
+ />
+ $[`${i18nPrefix}.builtInDescription`], {
+ ns: 'dataset',
+ })}
+ className="max-w-[100px]"
+ >
+ {t(($) => $[`${i18nPrefix}.builtInDescription`], { ns: 'dataset' })}
+
diff --git a/web/app/components/datasets/metadata/metadata-document/info-group.tsx b/web/app/components/datasets/metadata/metadata-document/info-group.tsx
index aa355122f58..971acc619c5 100644
--- a/web/app/components/datasets/metadata/metadata-document/info-group.tsx
+++ b/web/app/components/datasets/metadata/metadata-document/info-group.tsx
@@ -2,11 +2,11 @@
import type { FC } from 'react'
import type { BuiltInMetadataItem, MetadataItemWithValue } from '../types'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { RiDeleteBinLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import useTimestamp from '@/hooks/use-timestamp'
import { useRouter } from '@/next/navigation'
import InputCombined from '../edit-metadata-batch/input-combined'
@@ -70,8 +70,11 @@ const InfoGroup: FC = ({
{title}
{titleTooltip && (
-
- {titleTooltip}
+
+
+
+ {titleTooltip}
+
)}
diff --git a/web/app/components/datasets/settings/index-method/keyword-number.tsx b/web/app/components/datasets/settings/index-method/keyword-number.tsx
index 8af9e74c07c..495f904cd57 100644
--- a/web/app/components/datasets/settings/index-method/keyword-number.tsx
+++ b/web/app/components/datasets/settings/index-method/keyword-number.tsx
@@ -1,4 +1,5 @@
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
NumberField,
NumberFieldControls,
@@ -18,7 +19,6 @@ import {
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
const MIN_KEYWORD_NUMBER = 0
const MAX_KEYWORD_NUMBER = 50
@@ -44,8 +44,9 @@ const KeyWordNumber = ({ keywordNumber, onKeywordNumberChange }: KeyWordNumberPr
{label}
{label}
-
- {label}
+
+
+ {label}
{t(($) => $['form.summaryAutoGen'], { ns: 'datasetSettings' })}
- $['form.summaryAutoGenTip'], { ns: 'datasetSettings' })}
- className="ml-1"
- >
- {t(($) => $['form.summaryAutoGenTip'], { ns: 'datasetSettings' })}
+
+ $['form.summaryAutoGenTip'], { ns: 'datasetSettings' })}
+ className="ml-1"
+ />
+ $['form.summaryAutoGenTip'], { ns: 'datasetSettings' })}
+ >
+ {t(($) => $['form.summaryAutoGenTip'], { ns: 'datasetSettings' })}
+
- {infotipText}
+
+
+
+ {infotipText}
+
)
if (override) {
diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx
index 141d5874d38..09fd7eb2695 100644
--- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/parameter-item.tsx
@@ -3,6 +3,7 @@ import type { Node, NodeOutPutVar } from '@/app/components/workflow/types'
import { cn } from '@langgenius/dify-ui/cn'
import { Field, FieldItem, FieldLabel } from '@langgenius/dify-ui/field'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Radio, RadioGroup } from '@langgenius/dify-ui/radio-group'
import {
Select,
@@ -25,7 +26,6 @@ import {
import { Switch } from '@langgenius/dify-ui/switch'
import { useEffect, useId, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import PromptEditor from '@/app/components/base/prompt-editor'
import TagInput from '@/app/components/base/tag-input'
import { BlockEnum } from '@/app/components/workflow/types'
@@ -447,12 +447,17 @@ function ParameterItem({
{sliderLabel}
{parameterRule.help && (
-
- {parameterRule.help[language] || parameterRule.help.en_US}
+
+
+
+ {parameterRule.help[language] || parameterRule.help.en_US}
+
)}
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.tsx
index 9b2907be3cd..0379621c5ed 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/usage-priority-section.tsx
@@ -1,7 +1,7 @@
import type { UsagePriority } from '../use-credential-panel-state'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { PreferredProviderTypeEnum } from '../../declarations'
type UsagePrioritySectionProps = {
@@ -38,7 +38,10 @@ export default function UsagePrioritySection({
{t(($) => $['modelProvider.card.usagePriority'], { ns: 'common' })}
- {usagePriorityTip}
+
+
+ {usagePriorityTip}
+
{options.map((option) => {
diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
index 1507159d665..ee5933c17df 100644
--- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx
@@ -9,6 +9,7 @@ import type {
ModelProvider,
} from '../declarations'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { StatusDot } from '@langgenius/dify-ui/status-dot'
import { Switch } from '@langgenius/dify-ui/switch'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
@@ -17,7 +18,6 @@ import { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge/index'
import GridMask from '@/app/components/base/grid-mask'
-import { Infotip } from '@/app/components/base/infotip'
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
import s from '@/app/components/custom/style.module.css'
import { AddCredentialInLoadBalancing } from '@/app/components/header/account-setting/model-provider-page/model-auth'
@@ -188,12 +188,17 @@ const ModelLoadBalancingConfigs = ({
{t(($) => $['modelProvider.loadBalancing'], { ns: 'common' })}
- $['modelProvider.loadBalancingInfo'], { ns: 'common' })}
- className="size-3"
- iconSize="small"
- >
- {t(($) => $['modelProvider.loadBalancingInfo'], { ns: 'common' })}
+
+ $['modelProvider.loadBalancingInfo'], { ns: 'common' })}
+ className="size-3"
+ iconSize="small"
+ />
+ $['modelProvider.loadBalancingInfo'], { ns: 'common' })}
+ >
+ {t(($) => $['modelProvider.loadBalancingInfo'], { ns: 'common' })}
+
diff --git a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
index ae2af7f9d1b..d79abe96bcd 100644
--- a/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
+++ b/web/app/components/header/account-setting/model-provider-page/system-model-selector/index.tsx
@@ -4,12 +4,12 @@ import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { Dialog, DialogClose, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useQuery } from '@tanstack/react-query'
import { useAtomValue } from 'jotai'
import { parseAsStringLiteral, useQueryState } from 'nuqs'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { toast } from '@/app/notifications'
import { workspacePermissionKeysAtom } from '@/context/permission-state'
import { consoleClient, consoleQuery } from '@/service/console'
@@ -214,12 +214,11 @@ const SystemModel: FC
= ({
return (
{t(($) => $[labelKey], { ns: 'common' })}
-
- {tipText}
+
+
+
+ {tipText}
+
)
diff --git a/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx b/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
index 4ee940a67b1..c7165289b28 100644
--- a/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
+++ b/web/app/components/header/account-setting/workflow-log-archives-page/index.tsx
@@ -7,11 +7,11 @@ import type {
} from '@dify/contracts/api/console/workflow-run-archives/types.gen'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { skipToken, useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { useQueryState } from 'nuqs'
import { useEffect, useId, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { SkeletonRectangle } from '@/app/components/base/skeleton'
import {
pricingQueryParamName,
@@ -422,12 +422,17 @@ function WorkflowArchiveMonthRow({ archive }: { archive: WorkflowRunArchiveMonth
)}
{buttonContent}
- $['operation.learnMore'], { ns: 'common' })}: ${archiveMonth}`}
- iconVariant={isFailed ? 'warning' : 'information'}
- popupClassName="wrap-anywhere whitespace-pre-wrap"
- >
- {downloadHint}
+
+ $['operation.learnMore'], { ns: 'common' })}: ${archiveMonth}`}
+ iconVariant={isFailed ? 'warning' : 'information'}
+ />
+ $['operation.learnMore'], { ns: 'common' })}: ${archiveMonth}`}
+ className="wrap-anywhere whitespace-pre-wrap"
+ >
+ {downloadHint}
+
diff --git a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx
index dbc39b7b9f8..d353a23cb88 100644
--- a/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/multiple-tool-selector/index.tsx
@@ -4,10 +4,10 @@ import type { NodeOutPutVar } from '@/app/components/workflow/types'
import { cn } from '@langgenius/dify-ui/cn'
import { Collapsible, CollapsiblePanel, CollapsibleTrigger } from '@langgenius/dify-ui/collapsible'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-selector'
import { useMCPToolAvailability } from '@/app/components/workflow/nodes/_base/components/mcp-tool-availability'
import { useRefWithInit } from '@/hooks/use-ref-with-init'
@@ -153,11 +153,14 @@ const MultipleToolSelector = ({
>
)}
{tooltip ? (
-
- {tooltip}
+
+
+
+ {tooltip}
+
) : null}
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx
index 60e9fd8d294..803e74bf5aa 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx
@@ -2,6 +2,7 @@ import type { TriggerSubscriptionBuilder } from '@/app/components/workflow/block
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
Select,
SelectContent,
@@ -14,7 +15,6 @@ import { useBoolean } from 'ahooks'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Badge from '@/app/components/base/badge'
-import { Infotip } from '@/app/components/base/infotip'
import { toast } from '@/app/notifications'
import { openOAuthPopup } from '@/hooks/use-oauth'
import {
@@ -184,13 +184,20 @@ export const CreateSubscriptionButton = ({
ns: 'pluginTrigger',
}),
extra: (
-
$['subscription.addType.options.manual.tip'], {
- ns: 'pluginTrigger',
- })}
- className="size-3.5"
- >
- {t(($) => $['subscription.addType.options.manual.tip'], { ns: 'pluginTrigger' })}
+
+ $['subscription.addType.options.manual.tip'], {
+ ns: 'pluginTrigger',
+ })}
+ className="size-3.5"
+ />
+ $['subscription.addType.options.manual.tip'], {
+ ns: 'pluginTrigger',
+ })}
+ >
+ {t(($) => $['subscription.addType.options.manual.tip'], { ns: 'pluginTrigger' })}
+
),
show: supportedMethods.includes(SupportedCreationMethods.MANUAL),
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx
index 8a17186c7b7..dbbff0a3136 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/list-view.tsx
@@ -1,9 +1,9 @@
'use client'
import type { PluginDetail } from '@/app/components/plugins/types'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { CreateSubscriptionButton } from './create'
import { CreateButtonType } from './create/types'
import SubscriptionCard from './subscription-card'
@@ -31,11 +31,16 @@ export const SubscriptionListView: React.FC = ({
{t(($) => $['subscription.listNum'], { ns: 'pluginTrigger', num: subscriptionCount })}
- $['subscription.list.tip'], { ns: 'pluginTrigger' })}
- className="size-3.5"
- >
- {t(($) => $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+
+ $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+ className="size-3.5"
+ />
+ $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+ >
+ {t(($) => $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+
)}
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/selector-view.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/selector-view.tsx
index 781ebd34a91..1003ff8e395 100644
--- a/web/app/components/plugins/plugin-detail-panel/subscription-list/selector-view.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/selector-view.tsx
@@ -2,10 +2,10 @@
import type { TriggerSubscription } from '@/app/components/workflow/block-selector/types'
import { cn } from '@langgenius/dify-ui/cn'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { CreateSubscriptionButton } from './create'
import { CreateButtonType } from './create/types'
import { DeleteConfirm } from './delete-confirm'
@@ -33,11 +33,16 @@ export const SubscriptionSelectorView: React.FC = ({
{t(($) => $['subscription.listNum'], { ns: 'pluginTrigger', num: subscriptionCount })}
- $['subscription.list.tip'], { ns: 'pluginTrigger' })}
- className="size-3.5"
- >
- {t(($) => $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+
+ $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+ className="size-3.5"
+ />
+ $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+ >
+ {t(($) => $['subscription.list.tip'], { ns: 'pluginTrigger' })}
+
diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
index 4b861b6f07d..29498b87b83 100644
--- a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
+++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx
@@ -4,6 +4,7 @@ import type { ToolFormSchema } from '@/app/components/tools/utils/to-form-schema
import type { SchemaRoot } from '@/app/components/workflow/nodes/llm/types'
import type { NodeOutPutVar, ValueSelector } from '@/app/components/workflow/types'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import {
Select,
@@ -19,7 +20,6 @@ import { useSuspenseQuery } from '@tanstack/react-query'
import { useBoolean } from 'ahooks'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { AppSelector } from '@/app/components/plugins/plugin-detail-panel/app-selector'
@@ -148,8 +148,11 @@ const ReasoningConfigForm: React.FC = ({
const fieldTitle = getFieldTitle(label, language)
const tooltipText = tooltip?.[language] || tooltip?.en_US
const tooltipContent = tooltipText && (
-
- {tooltipText}
+
+
+
+ {tooltipText}
+
)
const varInput = value[variable]!.value
diff --git a/web/app/components/rag-pipeline/components/panel/input-field/index.tsx b/web/app/components/rag-pipeline/components/panel/input-field/index.tsx
index 5eef65f4810..89d4e25c879 100644
--- a/web/app/components/rag-pipeline/components/panel/input-field/index.tsx
+++ b/web/app/components/rag-pipeline/components/panel/input-field/index.tsx
@@ -3,12 +3,12 @@ import type { Node } from '@/app/components/workflow/types'
import type { InputVar, RAGPipelineVariables } from '@/models/pipeline'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import { RiCloseLine, RiEyeLine } from '@remixicon/react'
import { memo, useCallback, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
-import { Infotip } from '@/app/components/base/infotip'
import { useHooksStore } from '@/app/components/workflow/hooks-store'
import { useNodesSyncDraft } from '@/app/components/workflow/hooks/use-nodes-sync-draft'
import { useStore } from '@/app/components/workflow/store'
@@ -133,13 +133,20 @@ const InputFieldPanel = () => {
{t(($) => $['inputFieldPanel.uniqueInputs.title'], { ns: 'datasetPipeline' })}
- $['inputFieldPanel.uniqueInputs.tooltip'], {
- ns: 'datasetPipeline',
- })}
- popupClassName="max-w-[240px]"
- >
- {t(($) => $['inputFieldPanel.uniqueInputs.tooltip'], { ns: 'datasetPipeline' })}
+
+ $['inputFieldPanel.uniqueInputs.tooltip'], {
+ ns: 'datasetPipeline',
+ })}
+ />
+ $['inputFieldPanel.uniqueInputs.tooltip'], {
+ ns: 'datasetPipeline',
+ })}
+ className="max-w-[240px]"
+ >
+ {t(($) => $['inputFieldPanel.uniqueInputs.tooltip'], { ns: 'datasetPipeline' })}
+
diff --git a/web/app/components/rag-pipeline/components/panel/input-field/label-right-content/global-inputs.tsx b/web/app/components/rag-pipeline/components/panel/input-field/label-right-content/global-inputs.tsx
index 77e30b4fd3f..a98cf05a60c 100644
--- a/web/app/components/rag-pipeline/components/panel/input-field/label-right-content/global-inputs.tsx
+++ b/web/app/components/rag-pipeline/components/panel/input-field/label-right-content/global-inputs.tsx
@@ -1,6 +1,6 @@
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
const GlobalInputs = () => {
const { t } = useTranslation()
@@ -10,11 +10,20 @@ const GlobalInputs = () => {
{t(($) => $['inputFieldPanel.globalInputs.title'], { ns: 'datasetPipeline' })}
- $['inputFieldPanel.globalInputs.tooltip'], { ns: 'datasetPipeline' })}
- popupClassName="w-[240px]"
- >
- {t(($) => $['inputFieldPanel.globalInputs.tooltip'], { ns: 'datasetPipeline' })}
+
+ $['inputFieldPanel.globalInputs.tooltip'], {
+ ns: 'datasetPipeline',
+ })}
+ />
+ $['inputFieldPanel.globalInputs.tooltip'], {
+ ns: 'datasetPipeline',
+ })}
+ className="w-[240px]"
+ >
+ {t(($) => $['inputFieldPanel.globalInputs.tooltip'], { ns: 'datasetPipeline' })}
+
)
diff --git a/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx b/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx
index 9f427d0ceff..30560b84db3 100644
--- a/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx
+++ b/web/app/components/tools/edit-custom-collection-modal/config-credentials.tsx
@@ -14,6 +14,7 @@ import {
} from '@langgenius/dify-ui/drawer'
import { Field, FieldItem, FieldLabel } from '@langgenius/dify-ui/field'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import { Radio, RadioGroup } from '@langgenius/dify-ui/radio-group'
import {
@@ -25,7 +26,6 @@ import {
} from '@langgenius/dify-ui/scroll-area'
import { useId, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { AuthHeaderPrefix, AuthType } from '@/app/components/tools/types'
type Props = Readonly<{
@@ -213,14 +213,21 @@ export default function ConfigCredential({ positionCenter, credential, onChange,
- $['createTool.authMethod.keyTooltip'], {
- ns: 'tools',
- })}
- className="ml-0.5 size-4"
- popupClassName="w-[261px] text-text-tertiary"
- >
- {t(($) => $['createTool.authMethod.keyTooltip'], { ns: 'tools' })}
+
+ $['createTool.authMethod.keyTooltip'], {
+ ns: 'tools',
+ })}
+ className="ml-0.5 size-4"
+ />
+ $['createTool.authMethod.keyTooltip'], {
+ ns: 'tools',
+ })}
+ className="w-[261px] text-text-tertiary"
+ >
+ {t(($) => $['createTool.authMethod.keyTooltip'], { ns: 'tools' })}
+
{t(($) => $['createTool.authMethod.queryParam'], { ns: 'tools' })}
- $['createTool.authMethod.queryParamTooltip'], {
- ns: 'tools',
- })}
- className="ml-0.5 size-4"
- popupClassName="w-[261px] text-text-tertiary"
- >
- {t(($) => $['createTool.authMethod.queryParamTooltip'], {
- ns: 'tools',
- })}
+
+ $['createTool.authMethod.queryParamTooltip'], {
+ ns: 'tools',
+ })}
+ className="ml-0.5 size-4"
+ />
+ $['createTool.authMethod.queryParamTooltip'], {
+ ns: 'tools',
+ })}
+ className="w-[261px] text-text-tertiary"
+ >
+ {t(($) => $['createTool.authMethod.queryParamTooltip'], {
+ ns: 'tools',
+ })}
+
{
return (
-
- {children}
+
+
+
+ {children}
+
)
}
@@ -182,33 +185,38 @@ const WorkflowToolOutputName = React.memo(
)}
{hasReservedNameConflict || hasDuplicateNameConflict ? (
-
-
- {hasReservedNameConflict ?
{reservedOutputDuplicateTip}
: null}
- {hasDuplicateNameConflict ? (
-
-
{duplicateOutputTip}
- {sources.length > 0 ? (
-
- {sources.map((source) => {
- const sourceTitle = getSourceNodeDisplayName(source, sources)
- return (
- -
- {sourceNodeLabel}: {sourceTitle}
-
- )
- })}
-
- ) : null}
-
- ) : null}
-
+
+
+
+
+ {hasReservedNameConflict ?
{reservedOutputDuplicateTip}
: null}
+ {hasDuplicateNameConflict ? (
+
+
{duplicateOutputTip}
+ {sources.length > 0 ? (
+
+ {sources.map((source) => {
+ const sourceTitle = getSourceNodeDisplayName(source, sources)
+ return (
+ -
+ {sourceNodeLabel}: {sourceTitle}
+
+ )
+ })}
+
+ ) : null}
+
+ ) : null}
+
+
) : null}
diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx
index 45af349512a..3057b2715ef 100644
--- a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx
+++ b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx
@@ -7,11 +7,11 @@ import type {
ListRef,
} from '@/app/components/workflow/block-selector/marketplace-plugin/list'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
import { useSuspenseQuery } from '@tanstack/react-query'
-import { memo, useEffect, useMemo, useRef, useState } from 'react'
+import { memo, useEffect, useId, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { SearchInput } from '@/app/components/base/search-input'
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
import { useMarketplacePlugins } from '@/app/components/plugins/marketplace/hooks'
@@ -32,25 +32,30 @@ const DEFAULT_TAGS: ListProps['tags'] = []
const NotFoundWarn = (props: { title: string; description: ReactNode }) => {
const { title, description } = props
+ const titleId = useId()
const { t } = useTranslation()
return (
-
-
-
{title}
-
{description}
-
-
- {t(($) => $['nodes.agent.linkToPlugin'], { ns: 'workflow' })}
-
-
-
+
+
+
+
+
+ {title}
+
+
{description}
+
+
+ {t(($) => $['nodes.agent.linkToPlugin'], { ns: 'workflow' })}
+
+
+
+
)
}
diff --git a/web/app/components/workflow/nodes/_base/components/error-handle/error-handle-on-panel.tsx b/web/app/components/workflow/nodes/_base/components/error-handle/error-handle-on-panel.tsx
index b8568cafc3f..fd93567e5e3 100644
--- a/web/app/components/workflow/nodes/_base/components/error-handle/error-handle-on-panel.tsx
+++ b/web/app/components/workflow/nodes/_base/components/error-handle/error-handle-on-panel.tsx
@@ -1,7 +1,7 @@
import type { DefaultValueForm } from './types'
import type { CommonNodeType, Node } from '@/app/components/workflow/types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import {
Collapse,
CollapseActions,
@@ -43,8 +43,15 @@ const ErrorHandle = ({ id, data }: ErrorHandleProps) => {
{!!error_strategy && }
- $['nodes.common.errorHandle.tip'], { ns: 'workflow' })}>
- {t(($) => $['nodes.common.errorHandle.tip'], { ns: 'workflow' })}
+
+ $['nodes.common.errorHandle.tip'], { ns: 'workflow' })}
+ />
+ $['nodes.common.errorHandle.tip'], { ns: 'workflow' })}
+ >
+ {t(($) => $['nodes.common.errorHandle.tip'], { ns: 'workflow' })}
+
diff --git a/web/app/components/workflow/nodes/_base/components/field.tsx b/web/app/components/workflow/nodes/_base/components/field.tsx
index 8e966628c62..fb9bac6b4be 100644
--- a/web/app/components/workflow/nodes/_base/components/field.tsx
+++ b/web/app/components/workflow/nodes/_base/components/field.tsx
@@ -1,10 +1,10 @@
'use client'
import type { FC, ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { RiArrowDownSLine } from '@remixicon/react'
import * as React from 'react'
import { useState } from 'react'
-import { Infotip } from '@/app/components/base/infotip'
type Props = Readonly<{
className?: string
@@ -66,8 +66,9 @@ const Field: FC
= ({
{title} {required && *}
{!!tooltip && !!tooltipLabel && (
-
- {tooltip}
+
+
+ {tooltip}
)}
diff --git a/web/app/components/workflow/nodes/_base/components/layout/field-title.tsx b/web/app/components/workflow/nodes/_base/components/layout/field-title.tsx
index 6aa4b5a1c4b..0f444b684fe 100644
--- a/web/app/components/workflow/nodes/_base/components/layout/field-title.tsx
+++ b/web/app/components/workflow/nodes/_base/components/layout/field-title.tsx
@@ -1,7 +1,7 @@
import type { ReactNode } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { memo, useState } from 'react'
-import { Infotip } from '@/app/components/base/infotip'
export type FieldTitleProps = {
title?: string
@@ -57,8 +57,9 @@ export const FieldTitle = memo(
/>
)}
{tooltip && (
-
- {tooltip}
+
+
+ {tooltip}
)}
diff --git a/web/app/components/workflow/nodes/_base/components/option-card.tsx b/web/app/components/workflow/nodes/_base/components/option-card.tsx
index a478bb26caa..9ba9a83a281 100644
--- a/web/app/components/workflow/nodes/_base/components/option-card.tsx
+++ b/web/app/components/workflow/nodes/_base/components/option-card.tsx
@@ -2,10 +2,10 @@
import type { VariantProps } from 'class-variance-authority'
import type { FC } from 'react'
import { cn } from '@langgenius/dify-ui/cn'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { cva } from 'class-variance-authority'
import * as React from 'react'
import { useCallback } from 'react'
-import { Infotip } from '@/app/components/base/infotip'
const variants = cva([], {
variants: {
@@ -63,8 +63,11 @@ const OptionCard: FC = ({
>
{title}
{tooltip && (
-
- {tooltip}
+
+
+
+ {tooltip}
+
)}
diff --git a/web/app/components/workflow/nodes/_base/node-sections.tsx b/web/app/components/workflow/nodes/_base/node-sections.tsx
index aa1631fa030..c3c84f0a1e0 100644
--- a/web/app/components/workflow/nodes/_base/node-sections.tsx
+++ b/web/app/components/workflow/nodes/_base/node-sections.tsx
@@ -2,7 +2,8 @@ import type { SelectorParam } from 'i18next'
import type { ReactElement } from 'react'
import type { IterationNodeType } from '@/app/components/workflow/nodes/iteration/types'
import type { NodeProps } from '@/app/components/workflow/types'
-import { Infotip } from '@/app/components/base/infotip'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
+import { useId } from 'react'
import { BlockEnum, NodeRunningStatus } from '@/app/components/workflow/types'
type HeaderMetaProps = {
@@ -19,6 +20,7 @@ export type WorkflowTranslator = (
) => string
export const NodeHeaderMeta = ({ data, hasVarValue, isLoading, loopIndex, t }: HeaderMetaProps) => {
+ const titleId = useId()
return (
<>
{data.type === BlockEnum.Iteration && (data as IterationNodeType).is_parallel && (
@@ -26,14 +28,18 @@ export const NodeHeaderMeta = ({ data, hasVarValue, isLoading, loopIndex, t }: H
{t(($) => $['nodes.iteration.parallelModeUpper'], { ns: 'workflow' })}
- $['nodes.iteration.parallelModeEnableTitle'], { ns: 'workflow' })}
- popupClassName="w-45"
- >
-
- {t(($) => $['nodes.iteration.parallelModeEnableTitle'], { ns: 'workflow' })}
-
- {t(($) => $['nodes.iteration.parallelModeEnableDesc'], { ns: 'workflow' })}
+
+ $['nodes.iteration.parallelModeEnableTitle'], {
+ ns: 'workflow',
+ })}
+ />
+
+
+ {t(($) => $['nodes.iteration.parallelModeEnableTitle'], { ns: 'workflow' })}
+
+ {t(($) => $['nodes.iteration.parallelModeEnableDesc'], { ns: 'workflow' })}
+
)}
diff --git a/web/app/components/workflow/nodes/agent-v2/components/agent-task-field.tsx b/web/app/components/workflow/nodes/agent-v2/components/agent-task-field.tsx
index c490f38662f..1da8dd7af19 100644
--- a/web/app/components/workflow/nodes/agent-v2/components/agent-task-field.tsx
+++ b/web/app/components/workflow/nodes/agent-v2/components/agent-task-field.tsx
@@ -4,12 +4,12 @@ import type { AgentOutputTypeOptionValue } from '@/app/components/base/prompt-ed
import type { WorkflowNodesMap } from '@/app/components/base/prompt-editor/types'
import { cn } from '@langgenius/dify-ui/cn'
import { Field, FieldLabel } from '@langgenius/dify-ui/field'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { useBoolean } from 'ahooks'
import { $insertNodes } from 'lexical'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import PromptEditor from '@/app/components/base/prompt-editor'
import { $createCustomTextNode } from '@/app/components/base/prompt-editor/plugins/custom-text/node'
import { useDocLink } from '@/context/i18n'
@@ -97,17 +97,24 @@ export function AgentTaskField({
{t(($) => $[`${i18nPrefix}.task.label`], { ns: 'workflow' })}
- $[`${i18nPrefix}.task.tooltip`], { ns: 'workflow' })}>
- {t(($) => $[`${i18nPrefix}.task.tooltip`], { ns: 'workflow' })}{' '}
-
+ $[`${i18nPrefix}.task.tooltip`], { ns: 'workflow' })}
+ />
+ $[`${i18nPrefix}.task.tooltip`], { ns: 'workflow' })}
>
- {t(($) => $[`${i18nPrefix}.task.learnMore`], { ns: 'workflow' })}
-
-
+ {t(($) => $[`${i18nPrefix}.task.tooltip`], { ns: 'workflow' })}{' '}
+
+ {t(($) => $[`${i18nPrefix}.task.learnMore`], { ns: 'workflow' })}
+
+
+
= ({
{t(($) => $[`${i18nPrefix}.deliveryMethod.title`], { ns: 'workflow' })}
-
$[`${i18nPrefix}.deliveryMethod.tooltip`], { ns: 'workflow' })}
- >
- {t(($) => $[`${i18nPrefix}.deliveryMethod.tooltip`], { ns: 'workflow' })}
+
+ $[`${i18nPrefix}.deliveryMethod.tooltip`], { ns: 'workflow' })}
+ />
+ $[`${i18nPrefix}.deliveryMethod.tooltip`], { ns: 'workflow' })}
+ >
+ {t(($) => $[`${i18nPrefix}.deliveryMethod.tooltip`], { ns: 'workflow' })}
+
{!readonly && (
diff --git a/web/app/components/workflow/nodes/human-input/panel.tsx b/web/app/components/workflow/nodes/human-input/panel.tsx
index 3997f16b962..c5f920085ed 100644
--- a/web/app/components/workflow/nodes/human-input/panel.tsx
+++ b/web/app/components/workflow/nodes/human-input/panel.tsx
@@ -4,6 +4,7 @@ import type { NodePanelProps, Var } from '@/app/components/workflow/types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Separator } from '@langgenius/dify-ui/separator'
import {
RiAddLine,
@@ -16,7 +17,6 @@ import copy from 'copy-to-clipboard'
import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
import Split from '@/app/components/workflow/nodes/_base/components/split'
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
@@ -115,10 +115,15 @@ const Panel: FC> = ({ id, data }) => {
{t(($) => $[`${i18nPrefix}.formContent.title`], { ns: 'workflow' })}
- $[`${i18nPrefix}.formContent.tooltip`], { ns: 'workflow' })}
- >
- {t(($) => $[`${i18nPrefix}.formContent.tooltip`], { ns: 'workflow' })}
+
+ $[`${i18nPrefix}.formContent.tooltip`], { ns: 'workflow' })}
+ />
+ $[`${i18nPrefix}.formContent.tooltip`], { ns: 'workflow' })}
+ >
+ {t(($) => $[`${i18nPrefix}.formContent.tooltip`], { ns: 'workflow' })}
+
{!readOnly && (
@@ -193,10 +198,15 @@ const Panel: FC> = ({ id, data }) => {
{t(($) => $[`${i18nPrefix}.userActions.title`], { ns: 'workflow' })}
- $[`${i18nPrefix}.userActions.tooltip`], { ns: 'workflow' })}
- >
- {t(($) => $[`${i18nPrefix}.userActions.tooltip`], { ns: 'workflow' })}
+
+ $[`${i18nPrefix}.userActions.tooltip`], { ns: 'workflow' })}
+ />
+ $[`${i18nPrefix}.userActions.tooltip`], { ns: 'workflow' })}
+ >
+ {t(($) => $[`${i18nPrefix}.userActions.tooltip`], { ns: 'workflow' })}
+
{!readOnly && (
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
index e7a88756d54..2bc17387b43 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/index-method.tsx
@@ -1,5 +1,6 @@
import { cn } from '@langgenius/dify-ui/cn'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
NumberField,
NumberFieldControls,
@@ -19,7 +20,6 @@ import {
import { memo, useCallback, useId } from 'react'
import { useTranslation } from 'react-i18next'
import { Economic, HighQuality } from '@/app/components/base/icons/src/vender/knowledge'
-import { Infotip } from '@/app/components/base/infotip'
import { Field } from '@/app/components/workflow/nodes/_base/components/layout'
import { ChunkStructureEnum, IndexMethodEnum } from '../types'
import OptionCard from './option-card'
@@ -113,8 +113,11 @@ const IndexMethod = ({
>
{keywordNumberLabel}
-
- {keywordNumberLabel}
+
+
+
+ {keywordNumberLabel}
+
{rerankModelLabel}
-
- {rerankModelTip}
+
+
+ {rerankModelTip}
diff --git a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/top-k-and-score-threshold.tsx b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/top-k-and-score-threshold.tsx
index 2d236fc590c..2c6296cfe71 100644
--- a/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/top-k-and-score-threshold.tsx
+++ b/web/app/components/workflow/nodes/knowledge-base/components/retrieval-setting/top-k-and-score-threshold.tsx
@@ -1,5 +1,6 @@
import { Field, FieldLabel } from '@langgenius/dify-ui/field'
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import {
NumberField,
NumberFieldControls,
@@ -10,7 +11,6 @@ import {
} from '@langgenius/dify-ui/number-field'
import { Switch } from '@langgenius/dify-ui/switch'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import { env } from '@/env'
export type TopKFieldProps = {
@@ -67,8 +67,9 @@ export function TopKAndScoreThreshold({
{topKLabel}
-
- {topKTip}
+
+
+ {topKTip}
{scoreThresholdLabel}
-
- {scoreThresholdTip}
+
+
+ {scoreThresholdTip}
diff --git a/web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/metadata-filter/index.tsx b/web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/metadata-filter/index.tsx
index 36f7d2a1750..2423c75b025 100644
--- a/web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/metadata-filter/index.tsx
+++ b/web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/metadata-filter/index.tsx
@@ -1,8 +1,8 @@
import type { MetadataShape } from '@/app/components/workflow/nodes/knowledge-retrieval/types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { noop } from 'es-toolkit/function'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
import {
Collapse,
@@ -58,11 +58,16 @@ const MetadataFilter = ({
{metadataFilterMode === MetadataFilteringModeEnum.automatic && }
- $['nodes.knowledgeRetrieval.metadata.tip'], { ns: 'workflow' })}
- popupClassName="w-[200px]"
- >
- {t(($) => $['nodes.knowledgeRetrieval.metadata.tip'], { ns: 'workflow' })}
+
+ $['nodes.knowledgeRetrieval.metadata.tip'], { ns: 'workflow' })}
+ />
+ $['nodes.knowledgeRetrieval.metadata.tip'], { ns: 'workflow' })}
+ className="w-[200px]"
+ >
+ {t(($) => $['nodes.knowledgeRetrieval.metadata.tip'], { ns: 'workflow' })}
+
diff --git a/web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx b/web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx
index b1305f9677c..693f2efe885 100644
--- a/web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx
+++ b/web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx
@@ -2,10 +2,10 @@
import type { SelectorParam } from 'i18next'
import type { FC } from 'react'
import type { ModelConfig, Node, NodeOutPutVar, PromptItem, Variable } from '../../../types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
import { PromptRole } from '@/models/debug'
@@ -127,8 +127,11 @@ const ConfigPromptItem: FC
= ({
)}
{roleDescription && (
-
- {roleDescription}
+
+
+
+ {roleDescription}
+
)}
diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/prompt-editor.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/prompt-editor.tsx
index f70cf902533..ffd2b783fe6 100644
--- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/prompt-editor.tsx
+++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/json-schema-generator/prompt-editor.tsx
@@ -2,12 +2,12 @@ import type { FC } from 'react'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type { Model } from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Textarea } from '@langgenius/dify-ui/textarea'
import { RiCloseLine, RiSparklingFill } from '@remixicon/react'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
type ModelInfo = {
@@ -83,11 +83,16 @@ const PromptEditor: FC = ({
{t(($) => $['nodes.llm.jsonSchema.instruction'], { ns: 'workflow' })}
- $['nodes.llm.jsonSchema.promptTooltip'], { ns: 'workflow' })}
- className="size-3.5"
- >
- {t(($) => $['nodes.llm.jsonSchema.promptTooltip'], { ns: 'workflow' })}
+
+ $['nodes.llm.jsonSchema.promptTooltip'], { ns: 'workflow' })}
+ className="size-3.5"
+ />
+ $['nodes.llm.jsonSchema.promptTooltip'], { ns: 'workflow' })}
+ >
+ {t(($) => $['nodes.llm.jsonSchema.promptTooltip'], { ns: 'workflow' })}
+
diff --git a/web/app/components/workflow/nodes/llm/components/panel-memory-section.tsx b/web/app/components/workflow/nodes/llm/components/panel-memory-section.tsx
index 55e10dbc942..ccd1149e402 100644
--- a/web/app/components/workflow/nodes/llm/components/panel-memory-section.tsx
+++ b/web/app/components/workflow/nodes/llm/components/panel-memory-section.tsx
@@ -1,9 +1,9 @@
import type { FC } from 'react'
import type { LLMNodeType } from '../types'
import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import MemoryConfig from '@/app/components/workflow/nodes/_base/components/memory-config'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
import { FlowType } from '@/types/common'
@@ -71,8 +71,15 @@ const PanelMemorySection: FC
= ({
{t(($) => $['nodes.common.memories.title'], { ns: 'workflow' })}
- $['nodes.common.memories.tip'], { ns: 'workflow' })}>
- {t(($) => $['nodes.common.memories.tip'], { ns: 'workflow' })}
+
+ $['nodes.common.memories.tip'], { ns: 'workflow' })}
+ />
+ $['nodes.common.memories.tip'], { ns: 'workflow' })}
+ >
+ {t(($) => $['nodes.common.memories.tip'], { ns: 'workflow' })}
+
@@ -84,11 +91,16 @@ const PanelMemorySection: FC
= ({
title={
user
-
$['nodes.llm.roleDescription.user'], { ns: 'workflow' })}
- popupClassName="w-[180px]"
- >
- {t(($) => $['nodes.llm.roleDescription.user'], { ns: 'workflow' })}
+
+ $['nodes.llm.roleDescription.user'], { ns: 'workflow' })}
+ />
+ $['nodes.llm.roleDescription.user'], { ns: 'workflow' })}
+ className="w-[180px]"
+ >
+ {t(($) => $['nodes.llm.roleDescription.user'], { ns: 'workflow' })}
+
}
diff --git a/web/app/components/workflow/nodes/llm/components/panel-output-section.tsx b/web/app/components/workflow/nodes/llm/components/panel-output-section.tsx
index 084475919bd..dee0d2a75aa 100644
--- a/web/app/components/workflow/nodes/llm/components/panel-output-section.tsx
+++ b/web/app/components/workflow/nodes/llm/components/panel-output-section.tsx
@@ -1,9 +1,9 @@
import type { FC } from 'react'
import type { LLMNodeType, StructuredOutput } from '../types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Switch } from '@langgenius/dify-ui/switch'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
import Split from '@/app/components/workflow/nodes/_base/components/split'
import { StructureOutput } from './structure-output'
@@ -30,6 +30,7 @@ const PanelOutputSection: FC = ({
handleStructureOutputChange,
}) => {
const { t } = useTranslation()
+ const warningTitleId = React.useId()
return (
<>
@@ -40,29 +41,36 @@ const PanelOutputSection: FC = ({
operations={
{!isModelSupportStructuredOutput && !!inputs.structured_output_enabled && (
-
$['structOutput.modelNotSupported'], { ns: 'app' })}
- iconVariant="warning"
- iconSize="large"
- className="mr-1 text-text-warning-secondary"
- popupClassName="w-58"
- >
-
- {t(($) => $['structOutput.modelNotSupported'], { ns: 'app' })}
-
-
- {t(($) => $['structOutput.modelNotSupportedTip'], { ns: 'app' })}
-
+
+ $['structOutput.modelNotSupported'], { ns: 'app' })}
+ iconVariant="warning"
+ iconSize="large"
+ className="mr-1 text-text-warning-secondary"
+ />
+
+
+ {t(($) => $['structOutput.modelNotSupported'], { ns: 'app' })}
+
+
+ {t(($) => $['structOutput.modelNotSupportedTip'], { ns: 'app' })}
+
+
)}
{t(($) => $['structOutput.structured'], { ns: 'app' })}
- $['structOutput.structuredTip'], { ns: 'app' })}
- popupClassName="w-[150px]"
- >
- {t(($) => $['structOutput.structuredTip'], { ns: 'app' })}
+
+ $['structOutput.structuredTip'], { ns: 'app' })}
+ />
+ $['structOutput.structuredTip'], { ns: 'app' })}
+ className="w-[150px]"
+ >
+ {t(($) => $['structOutput.structuredTip'], { ns: 'app' })}
+
> = ({ id, data }) =>
{t(($) => $[`${i18nPrefix}.instruction`], { ns: 'workflow' })}
- $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
- className="ml-0.5 size-3.5"
- popupClassName="w-[120px]"
- >
- {t(($) => $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+
+ $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+ className="ml-0.5 size-3.5"
+ />
+ $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+ className="w-[120px]"
+ >
+ {t(($) => $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+
}
diff --git a/web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx b/web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx
index 1c69fbafe65..c965d39c13c 100644
--- a/web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx
+++ b/web/app/components/workflow/nodes/question-classifier/components/advanced-setting.tsx
@@ -1,9 +1,9 @@
'use client'
import type { FC } from 'react'
import type { Memory, Node, NodeOutPutVar } from '@/app/components/workflow/types'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
import MemoryConfig from '../../_base/components/memory-config'
@@ -50,12 +50,17 @@ const AdvancedSetting: FC = ({
{t(($) => $[`${i18nPrefix}.instruction`], { ns: 'workflow' })}
- $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
- className="ml-0.5 size-3.5"
- popupClassName="w-[120px]"
- >
- {t(($) => $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+
+ $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+ className="ml-0.5 size-3.5"
+ />
+ $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+ className="w-[120px]"
+ >
+ {t(($) => $[`${i18nPrefix}.instructionTip`], { ns: 'workflow' })}
+
}
diff --git a/web/app/components/workflow/nodes/tool/components/tool-form/item.tsx b/web/app/components/workflow/nodes/tool/components/tool-form/item.tsx
index e8c4544f1c5..43ec99c773f 100644
--- a/web/app/components/workflow/nodes/tool/components/tool-form/item.tsx
+++ b/web/app/components/workflow/nodes/tool/components/tool-form/item.tsx
@@ -5,8 +5,8 @@ import type { CredentialFormSchema } from '@/app/components/header/account-setti
import type { Tool } from '@/app/components/tools/types'
import type { ToolWithProvider } from '@/app/components/workflow/types'
import { Button } from '@langgenius/dify-ui/button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useId, useState } from 'react'
-import { Infotip } from '@/app/components/base/infotip'
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { SchemaModal } from '@/app/components/plugins/plugin-detail-panel/tool-selector/components/schema-modal'
@@ -102,12 +102,11 @@ const ToolFormItem: FC
= ({
*
)}
{!showDescription && tooltip && (
-
- {tooltip[language] || tooltip.en_US}
+
+
+
+ {tooltip[language] || tooltip.en_US}
+
)}
{showSchemaButton && (
diff --git a/web/app/components/workflow/nodes/trigger-plugin/components/trigger-form/item.tsx b/web/app/components/workflow/nodes/trigger-plugin/components/trigger-form/item.tsx
index 683b8efc14e..e136cb86fb0 100644
--- a/web/app/components/workflow/nodes/trigger-plugin/components/trigger-form/item.tsx
+++ b/web/app/components/workflow/nodes/trigger-plugin/components/trigger-form/item.tsx
@@ -5,8 +5,8 @@ import type { Event } from '@/app/components/tools/types'
import type { TriggerWithProvider } from '@/app/components/workflow/block-selector/types'
import type { PluginTriggerVarInputs } from '@/app/components/workflow/nodes/trigger-plugin/types'
import { Button } from '@langgenius/dify-ui/button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { useId, useState } from 'react'
-import { Infotip } from '@/app/components/base/infotip'
import { FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { SchemaModal } from '@/app/components/plugins/plugin-detail-panel/tool-selector/components/schema-modal'
@@ -59,12 +59,14 @@ const TriggerFormItem: FC = ({
*
)}
{!showDescription && tooltip && (
-
- {tooltip[language] || tooltip.en_US}
+
+
+
+ {tooltip[language] || tooltip.en_US}
+
)}
{showSchemaButton && (
diff --git a/web/app/components/workflow/nodes/trigger-schedule/components/monthly-days-selector.tsx b/web/app/components/workflow/nodes/trigger-schedule/components/monthly-days-selector.tsx
index 911338b4a3f..214f054be10 100644
--- a/web/app/components/workflow/nodes/trigger-schedule/components/monthly-days-selector.tsx
+++ b/web/app/components/workflow/nodes/trigger-schedule/components/monthly-days-selector.tsx
@@ -1,7 +1,7 @@
import { Fieldset, FieldsetLegend } from '@langgenius/dify-ui/fieldset'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
-import { Infotip } from '@/app/components/base/infotip'
type MonthlyDaysSelectorProps = {
selectedDays: (number | 'last')[]
@@ -55,14 +55,21 @@ const MonthlyDaysSelector = ({ selectedDays, onChange }: MonthlyDaysSelectorProp
>
{t(($) => $['nodes.triggerSchedule.lastDay'], { ns: 'workflow' })}
- $['nodes.triggerSchedule.lastDayTooltip'], {
- ns: 'workflow',
- })}
- className="mr-1 size-3"
- iconSize="small"
- >
- {t(($) => $['nodes.triggerSchedule.lastDayTooltip'], { ns: 'workflow' })}
+
+ $['nodes.triggerSchedule.lastDayTooltip'], {
+ ns: 'workflow',
+ })}
+ className="mr-1 size-3"
+ iconSize="small"
+ />
+ $['nodes.triggerSchedule.lastDayTooltip'], {
+ ns: 'workflow',
+ })}
+ >
+ {t(($) => $['nodes.triggerSchedule.lastDayTooltip'], { ns: 'workflow' })}
+
) : (
diff --git a/web/app/components/workflow/panel/env-panel/variable-modal.tsx b/web/app/components/workflow/panel/env-panel/variable-modal.tsx
index c2619894737..abbd5d96d1c 100644
--- a/web/app/components/workflow/panel/env-panel/variable-modal.tsx
+++ b/web/app/components/workflow/panel/env-panel/variable-modal.tsx
@@ -3,6 +3,7 @@ import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { Field, FieldLabel } from '@langgenius/dify-ui/field'
import { IconButton } from '@langgenius/dify-ui/icon-button'
+import { Infotip, InfotipContent, InfotipTrigger } from '@langgenius/dify-ui/infotip'
import { Input } from '@langgenius/dify-ui/input'
import { NumberField, NumberFieldGroup, NumberFieldInput } from '@langgenius/dify-ui/number-field'
import { Textarea } from '@langgenius/dify-ui/textarea'
@@ -10,7 +11,6 @@ import * as React from 'react'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { v4 as uuid4 } from 'uuid'
-import { Infotip } from '@/app/components/base/infotip'
import { isLLMEnvironmentVariableValue } from '@/app/components/workflow/llm-environment-variable'
import { LLMEnvironmentVariableValueField } from '@/app/components/workflow/llm-environment-variable-value-field'
import { useWorkflowStore } from '@/app/components/workflow/store'
@@ -199,12 +199,17 @@ const VariableModal = ({ env, onClose, onSave }: ModalPropsType) => {
>
Secret
- $['env.modal.secretTip'], { ns: 'workflow' })}
- className="absolute top-1/2 right-1 size-3.5 -translate-y-1/2"
- popupClassName="w-[240px]"
- >
- {t(($) => $['env.modal.secretTip'], { ns: 'workflow' })}
+
+ $['env.modal.secretTip'], { ns: 'workflow' })}
+ className="absolute top-1/2 right-1 size-3.5 -translate-y-1/2"
+ />
+ $['env.modal.secretTip'], { ns: 'workflow' })}
+ className="w-[240px]"
+ >
+ {t(($) => $['env.modal.secretTip'], { ns: 'workflow' })}
+