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}
+ ))} +
{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' })} +