mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
Switch 13 infotip / static-trigger usages of @langgenius/dify-ui/tooltip over to @langgenius/dify-ui/popover with openOnHover, so the descriptive content is reachable on touch and via screen readers. Visual presentation is preserved by setting popupClassName to match the original tooltip styling. Triggers that already own a primary click action (model selector rows, variable chips, online-user avatars, etc.) are intentionally left on Tooltip pending a separate selection-with-preview redesign, since swapping in Popover would have click both fire that action and toggle the popup. Made-with: Cursor
103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
import type { TFunction } 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 { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
|
import { BlockEnum, NodeRunningStatus } from '@/app/components/workflow/types'
|
|
|
|
type HeaderMetaProps = {
|
|
data: NodeProps['data']
|
|
hasVarValue: boolean
|
|
isLoading: boolean
|
|
loopIndex: ReactElement | null
|
|
t: TFunction
|
|
}
|
|
|
|
export const NodeHeaderMeta = ({
|
|
data,
|
|
hasVarValue,
|
|
isLoading,
|
|
loopIndex,
|
|
t,
|
|
}: HeaderMetaProps) => {
|
|
return (
|
|
<>
|
|
{data.type === BlockEnum.Iteration && (data as IterationNodeType).is_parallel && (
|
|
<Popover>
|
|
<PopoverTrigger
|
|
openOnHover
|
|
nativeButton={false}
|
|
aria-label={t('nodes.iteration.parallelModeEnableTitle', { ns: 'workflow' })}
|
|
render={(
|
|
<div className="ml-1 flex items-center justify-center rounded-[5px] border border-text-warning px-[5px] py-[3px] system-2xs-medium-uppercase text-text-warning">
|
|
{t('nodes.iteration.parallelModeUpper', { ns: 'workflow' })}
|
|
</div>
|
|
)}
|
|
/>
|
|
<PopoverContent
|
|
placement="top"
|
|
popupClassName="w-[180px] rounded-md border-0 bg-components-panel-bg px-3 py-2 text-left system-xs-regular wrap-break-word text-text-tertiary shadow-lg"
|
|
>
|
|
<div className="font-extrabold">
|
|
{t('nodes.iteration.parallelModeEnableTitle', { ns: 'workflow' })}
|
|
</div>
|
|
{t('nodes.iteration.parallelModeEnableDesc', { ns: 'workflow' })}
|
|
</PopoverContent>
|
|
</Popover>
|
|
)}
|
|
{!!(data._iterationLength && data._iterationIndex && data._runningStatus === NodeRunningStatus.Running) && (
|
|
<div className="mr-1.5 text-xs font-medium text-text-accent">
|
|
{data._iterationIndex > data._iterationLength ? data._iterationLength : data._iterationIndex}
|
|
/
|
|
{data._iterationLength}
|
|
</div>
|
|
)}
|
|
{!!(data.type === BlockEnum.Loop && data._loopIndex) && loopIndex}
|
|
{isLoading && <span className="i-ri-loader-2-line h-3.5 w-3.5 animate-spin text-text-accent" />}
|
|
{!isLoading && data._runningStatus === NodeRunningStatus.Failed && (
|
|
<span className="i-ri-error-warning-fill h-3.5 w-3.5 text-text-destructive" />
|
|
)}
|
|
{!isLoading && data._runningStatus === NodeRunningStatus.Exception && (
|
|
<span className="i-ri-alert-fill h-3.5 w-3.5 text-text-warning-secondary" />
|
|
)}
|
|
{!isLoading && (data._runningStatus === NodeRunningStatus.Succeeded || (!data._runningStatus && hasVarValue)) && (
|
|
<span className="i-ri-checkbox-circle-fill h-3.5 w-3.5 text-text-success" />
|
|
)}
|
|
{!isLoading && data._runningStatus === NodeRunningStatus.Paused && (
|
|
<span className="i-ri-pause-circle-fill h-3.5 w-3.5 text-text-warning-secondary" />
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
type NodeBodyProps = {
|
|
data: NodeProps['data']
|
|
child: ReactElement
|
|
}
|
|
|
|
export const NodeBody = ({
|
|
data,
|
|
child,
|
|
}: NodeBodyProps) => {
|
|
if (data.type === BlockEnum.Iteration || data.type === BlockEnum.Loop) {
|
|
return (
|
|
<div className="grow pr-1 pb-1 pl-1">
|
|
{child}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return child
|
|
}
|
|
|
|
export const NodeDescription = ({ data }: { data: NodeProps['data'] }) => {
|
|
if (!data.desc || data.type === BlockEnum.Iteration || data.type === BlockEnum.Loop)
|
|
return null
|
|
|
|
return (
|
|
<div className="px-3 pt-1 pb-2 system-xs-regular wrap-break-word whitespace-pre-line text-text-tertiary">
|
|
{data.desc}
|
|
</div>
|
|
)
|
|
}
|