fix(web): normalize dify-ui overlay control (#35832)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
yyh 2026-05-06 15:28:13 +08:00 committed by GitHub
parent 57539792c1
commit 8967ff34b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
62 changed files with 421 additions and 408 deletions

View File

@ -608,17 +608,6 @@
"count": 1
}
},
"web/app/components/apps/app-card.tsx": {
"no-restricted-imports": {
"count": 1
},
"react/set-state-in-effect": {
"count": 1
},
"ts/no-explicit-any": {
"count": 2
}
},
"web/app/components/apps/new-app-card.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1

View File

@ -223,116 +223,107 @@ export default function AccountPage() {
)}
{!IS_CE_EDITION && <Button className="mt-2 text-components-button-destructive-secondary-text" onClick={() => setShowDeleteAccountModal(true)}>{t('account.delete', { ns: 'common' })}</Button>}
</div>
{
editNameModalVisible && (
<Dialog open={editNameModalVisible} onOpenChange={open => !open && setEditNameModalVisible(false)}>
<DialogContent className="w-[420px]! p-6!">
<div className="mb-6 title-2xl-semi-bold text-text-primary">{t('account.editName', { ns: 'common' })}</div>
<div className={titleClassName}>{t('account.name', { ns: 'common' })}</div>
<Input
className="mt-2"
value={editName}
onChange={e => setEditName(e.target.value)}
/>
<div className="mt-10 flex justify-end">
<Button className="mr-2" onClick={() => setEditNameModalVisible(false)}>{t('operation.cancel', { ns: 'common' })}</Button>
<Button
disabled={editing || !editName}
variant="primary"
onClick={handleSaveName}
>
{t('operation.save', { ns: 'common' })}
</Button>
</div>
</DialogContent>
</Dialog>
)
}
{
editPasswordModalVisible && (
<Dialog open={editPasswordModalVisible} onOpenChange={open => !open && (setEditPasswordModalVisible(false), resetPasswordForm())}>
<DialogContent className="w-[420px]! p-6!">
<div className="mb-6 title-2xl-semi-bold text-text-primary">{userProfile.is_password_set ? t('account.resetPassword', { ns: 'common' }) : t('account.setPassword', { ns: 'common' })}</div>
{userProfile.is_password_set && (
<>
<div className={titleClassName}>{t('account.currentPassword', { ns: 'common' })}</div>
<div className="relative mt-2">
<Input
type={showCurrentPassword ? 'text' : 'password'}
value={currentPassword}
onChange={e => setCurrentPassword(e.target.value)}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<Button
type="button"
variant="ghost"
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
>
{showCurrentPassword ? '👀' : '😝'}
</Button>
</div>
</div>
</>
)}
<div className="mt-8 system-sm-semibold text-text-secondary">
{userProfile.is_password_set ? t('account.newPassword', { ns: 'common' }) : t('account.password', { ns: 'common' })}
</div>
<Dialog open={editNameModalVisible} onOpenChange={open => !open && setEditNameModalVisible(false)}>
<DialogContent className="w-105 p-6">
<div className="mb-6 title-2xl-semi-bold text-text-primary">{t('account.editName', { ns: 'common' })}</div>
<div className={titleClassName}>{t('account.name', { ns: 'common' })}</div>
<Input
className="mt-2"
value={editName}
onChange={e => setEditName(e.target.value)}
/>
<div className="mt-10 flex justify-end">
<Button className="mr-2" onClick={() => setEditNameModalVisible(false)}>{t('operation.cancel', { ns: 'common' })}</Button>
<Button
disabled={editing || !editName}
variant="primary"
onClick={handleSaveName}
>
{t('operation.save', { ns: 'common' })}
</Button>
</div>
</DialogContent>
</Dialog>
<Dialog open={editPasswordModalVisible} onOpenChange={open => !open && (setEditPasswordModalVisible(false), resetPasswordForm())}>
<DialogContent className="w-[420px]! p-6!">
<div className="mb-6 title-2xl-semi-bold text-text-primary">{userProfile.is_password_set ? t('account.resetPassword', { ns: 'common' }) : t('account.setPassword', { ns: 'common' })}</div>
{userProfile.is_password_set && (
<>
<div className={titleClassName}>{t('account.currentPassword', { ns: 'common' })}</div>
<div className="relative mt-2">
<Input
type={showPassword ? 'text' : 'password'}
value={password}
onChange={e => setPassword(e.target.value)}
type={showCurrentPassword ? 'text' : 'password'}
value={currentPassword}
onChange={e => setCurrentPassword(e.target.value)}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<Button
type="button"
variant="ghost"
onClick={() => setShowPassword(!showPassword)}
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
>
{showPassword ? '👀' : '😝'}
{showCurrentPassword ? '👀' : '😝'}
</Button>
</div>
</div>
<div className="mt-8 system-sm-semibold text-text-secondary">{t('account.confirmPassword', { ns: 'common' })}</div>
<div className="relative mt-2">
<Input
type={showConfirmPassword ? 'text' : 'password'}
value={confirmPassword}
onChange={e => setConfirmPassword(e.target.value)}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<Button
type="button"
variant="ghost"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
>
{showConfirmPassword ? '👀' : '😝'}
</Button>
</div>
</div>
<div className="mt-10 flex justify-end">
<Button
className="mr-2"
onClick={() => {
setEditPasswordModalVisible(false)
resetPasswordForm()
}}
>
{t('operation.cancel', { ns: 'common' })}
</Button>
<Button
disabled={editing}
variant="primary"
onClick={handleSavePassword}
>
{userProfile.is_password_set ? t('operation.reset', { ns: 'common' }) : t('operation.save', { ns: 'common' })}
</Button>
</div>
</DialogContent>
</Dialog>
)
}
</>
)}
<div className="mt-8 system-sm-semibold text-text-secondary">
{userProfile.is_password_set ? t('account.newPassword', { ns: 'common' }) : t('account.password', { ns: 'common' })}
</div>
<div className="relative mt-2">
<Input
type={showPassword ? 'text' : 'password'}
value={password}
onChange={e => setPassword(e.target.value)}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<Button
type="button"
variant="ghost"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? '👀' : '😝'}
</Button>
</div>
</div>
<div className="mt-8 system-sm-semibold text-text-secondary">{t('account.confirmPassword', { ns: 'common' })}</div>
<div className="relative mt-2">
<Input
type={showConfirmPassword ? 'text' : 'password'}
value={confirmPassword}
onChange={e => setConfirmPassword(e.target.value)}
/>
<div className="absolute inset-y-0 right-0 flex items-center">
<Button
type="button"
variant="ghost"
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
>
{showConfirmPassword ? '👀' : '😝'}
</Button>
</div>
</div>
<div className="mt-10 flex justify-end">
<Button
className="mr-2"
onClick={() => {
setEditPasswordModalVisible(false)
resetPasswordForm()
}}
>
{t('operation.cancel', { ns: 'common' })}
</Button>
<Button
disabled={editing}
variant="primary"
onClick={handleSavePassword}
>
{userProfile.is_password_set ? t('operation.reset', { ns: 'common' }) : t('operation.save', { ns: 'common' })}
</Button>
</div>
</DialogContent>
</Dialog>
{
showDeleteAccountModal && (
<DeleteAccount
@ -341,13 +332,11 @@ export default function AccountPage() {
/>
)
}
{showUpdateEmail && (
<EmailChangeModal
show={showUpdateEmail}
onClose={() => setShowUpdateEmail(false)}
email={userProfile.email}
/>
)}
<EmailChangeModal
show={showUpdateEmail}
onClose={() => setShowUpdateEmail(false)}
email={userProfile.email}
/>
</>
)
}

View File

@ -83,7 +83,6 @@ const VarPicker: FC<Props> = ({
placement="bottom-end"
sideOffset={8}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
{options.length > 0
? (

View File

@ -113,7 +113,7 @@ const ChatUserInput = ({
<SelectTrigger className="w-full">
{String(inputs[key] || t('placeholder.select', { ns: 'common' }))}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{(options || []).map(option => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -167,7 +167,7 @@ const PromptValuePanel: FC<IPromptValuePanelProps> = ({
<SelectTrigger className="w-full bg-gray-50">
{String(inputs[key] || t('placeholder.select', { ns: 'common' }))}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{(options || []).map(option => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -317,7 +317,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
<SelectTrigger size="large" className="w-[200px]">
{selectedLanguage?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{languageOptions.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -24,15 +24,19 @@ import {
DropdownMenuTrigger,
} from '@langgenius/dify-ui/dropdown-menu'
import { toast } from '@langgenius/dify-ui/toast'
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@langgenius/dify-ui/tooltip'
import { useSuspenseQuery } from '@tanstack/react-query'
import * as React from 'react'
import { useCallback, useEffect, useId, useMemo, useState } from 'react'
import { useCallback, useId, useMemo, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { AppTypeIcon } from '@/app/components/app/type-selector'
import AppIcon from '@/app/components/base/app-icon'
import Input from '@/app/components/base/input'
import TagSelector from '@/app/components/base/tag-management/selector'
import Tooltip from '@/app/components/base/tooltip'
import { UserAvatarList } from '@/app/components/base/user-avatar-list'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { useAppContext } from '@/context/app-context'
@ -229,8 +233,9 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
setShowConfirmDelete(false)
setConfirmDeleteInput('')
}
catch (e: any) {
toast.error(`${t('appDeleteFailed', { ns: 'app' })}${'message' in e ? `: ${e.message}` : ''}`)
catch (e) {
const message = e instanceof Error ? e.message : ''
toast.error(`${t('appDeleteFailed', { ns: 'app' })}${message ? `: ${message}` : ''}`)
}
}, [app.id, mutateDeleteApp, onPlanInfoChanged, t])
@ -313,8 +318,8 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
if (onRefresh)
onRefresh()
}
catch (e: any) {
toast.error(e.message || t('editFailed', { ns: 'app' }))
catch (e) {
toast.error(e instanceof Error ? e.message : t('editFailed', { ns: 'app' }))
}
}, [app.id, onRefresh, t])
@ -391,10 +396,18 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
const shouldShowAccessControlOption = systemFeatures.webapp_auth.enabled && isCurrentWorkspaceEditor
const operationsMenuWidthClassName = shouldShowSwitchOption ? 'w-[256px]' : 'w-[216px]'
const [tags, setTags] = useState<Tag[]>(app.tags)
useEffect(() => {
setTags(app.tags)
}, [app.tags])
const appTagsKey = useMemo(() => app.tags.map(tag => tag.id).join(','), [app.tags])
const [tagState, setTagState] = useState<{ key: string, tags: Tag[] }>(() => ({
key: appTagsKey,
tags: app.tags,
}))
const tags = tagState.key === appTagsKey ? tagState.tags : app.tags
const handleTagsUpdate = useCallback((nextTags: Tag[]) => {
setTagState({
key: appTagsKey,
tags: nextTags,
})
}, [appTagsKey])
const EditTimeText = useMemo(() => {
const timeText = formatTime({
@ -454,23 +467,39 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
)}
<div className="flex h-5 w-5 items-center justify-center">
{app.access_mode === AccessMode.PUBLIC && (
<Tooltip asChild={false} popupContent={t('accessItemsDescription.anyone', { ns: 'app' })}>
<span aria-hidden className="i-ri-global-line h-4 w-4 text-text-quaternary" />
<Tooltip>
<TooltipTrigger
aria-label={t('accessItemsDescription.anyone', { ns: 'app' })}
render={<span title={t('accessItemsDescription.anyone', { ns: 'app' })} className="i-ri-global-line h-4 w-4 text-text-quaternary" />}
/>
<TooltipContent>{t('accessItemsDescription.anyone', { ns: 'app' })}</TooltipContent>
</Tooltip>
)}
{app.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS && (
<Tooltip asChild={false} popupContent={t('accessItemsDescription.specific', { ns: 'app' })}>
<span aria-hidden className="i-ri-lock-line h-4 w-4 text-text-quaternary" />
<Tooltip>
<TooltipTrigger
aria-label={t('accessItemsDescription.specific', { ns: 'app' })}
render={<span title={t('accessItemsDescription.specific', { ns: 'app' })} className="i-ri-lock-line h-4 w-4 text-text-quaternary" />}
/>
<TooltipContent>{t('accessItemsDescription.specific', { ns: 'app' })}</TooltipContent>
</Tooltip>
)}
{app.access_mode === AccessMode.ORGANIZATION && (
<Tooltip asChild={false} popupContent={t('accessItemsDescription.organization', { ns: 'app' })}>
<span aria-hidden className="i-ri-building-line h-4 w-4 text-text-quaternary" />
<Tooltip>
<TooltipTrigger
aria-label={t('accessItemsDescription.organization', { ns: 'app' })}
render={<span title={t('accessItemsDescription.organization', { ns: 'app' })} className="i-ri-building-line h-4 w-4 text-text-quaternary" />}
/>
<TooltipContent>{t('accessItemsDescription.organization', { ns: 'app' })}</TooltipContent>
</Tooltip>
)}
{app.access_mode === AccessMode.EXTERNAL_MEMBERS && (
<Tooltip asChild={false} popupContent={t('accessItemsDescription.external', { ns: 'app' })}>
<span aria-hidden className="i-ri-verified-badge-line h-4 w-4 text-text-quaternary" />
<Tooltip>
<TooltipTrigger
aria-label={t('accessItemsDescription.external', { ns: 'app' })}
render={<span title={t('accessItemsDescription.external', { ns: 'app' })} className="i-ri-verified-badge-line h-4 w-4 text-text-quaternary" />}
/>
<TooltipContent>{t('accessItemsDescription.external', { ns: 'app' })}</TooltipContent>
</Tooltip>
)}
</div>
@ -501,7 +530,7 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
targetID={app.id}
value={tags.map(tag => tag.id)}
selectedTags={tags}
onCacheUpdate={setTags}
onCacheUpdate={handleTagsUpdate}
onChange={onRefresh}
/>
</div>
@ -532,42 +561,40 @@ const AppCard = ({ app, onlineUsers = [], onRefresh }: AppCardProps) => {
<span aria-hidden className="i-ri-more-fill h-4 w-4 text-text-tertiary" />
</div>
</DropdownMenuTrigger>
{isOperationsMenuOpen && (
<DropdownMenuContent
placement="bottom-end"
sideOffset={4}
popupClassName={operationsMenuWidthClassName}
>
{systemFeatures.webapp_auth.enabled
? (
<AppCardOperationsMenuContent
app={app}
shouldShowSwitchOption={shouldShowSwitchOption}
shouldShowAccessControlOption={shouldShowAccessControlOption}
onEdit={handleShowEditModal}
onDuplicate={handleShowDuplicateModal}
onExport={exportCheck}
onSwitch={handleShowSwitchModal}
onDelete={handleShowDeleteConfirm}
onAccessControl={handleShowAccessControl}
/>
)
: (
<AppCardOperationsMenu
app={app}
shouldShowSwitchOption={shouldShowSwitchOption}
shouldShowOpenInExploreOption={!app.has_draft_trigger}
shouldShowAccessControlOption={shouldShowAccessControlOption}
onEdit={handleShowEditModal}
onDuplicate={handleShowDuplicateModal}
onExport={exportCheck}
onSwitch={handleShowSwitchModal}
onDelete={handleShowDeleteConfirm}
onAccessControl={handleShowAccessControl}
/>
)}
</DropdownMenuContent>
)}
<DropdownMenuContent
placement="bottom-end"
sideOffset={4}
popupClassName={operationsMenuWidthClassName}
>
{systemFeatures.webapp_auth.enabled
? (
<AppCardOperationsMenuContent
app={app}
shouldShowSwitchOption={shouldShowSwitchOption}
shouldShowAccessControlOption={shouldShowAccessControlOption}
onEdit={handleShowEditModal}
onDuplicate={handleShowDuplicateModal}
onExport={exportCheck}
onSwitch={handleShowSwitchModal}
onDelete={handleShowDeleteConfirm}
onAccessControl={handleShowAccessControl}
/>
)
: (
<AppCardOperationsMenu
app={app}
shouldShowSwitchOption={shouldShowSwitchOption}
shouldShowOpenInExploreOption={!app.has_draft_trigger}
shouldShowAccessControlOption={shouldShowAccessControlOption}
onEdit={handleShowEditModal}
onDuplicate={handleShowDuplicateModal}
onExport={exportCheck}
onSwitch={handleShowSwitchModal}
onDelete={handleShowDeleteConfirm}
onAccessControl={handleShowAccessControl}
/>
)}
</DropdownMenuContent>
</DropdownMenu>
</div>
</>

View File

@ -248,7 +248,7 @@ describe('InputsFormContent', () => {
expect(mockSetCurrentConversationInputs).toHaveBeenCalledWith(expect.objectContaining({ sel: 'A' }))
})
it('renders select dropdown above the settings dialog layer', async () => {
it('renders select dropdown on the shared dify-ui overlay layer', async () => {
const user = userEvent.setup()
const context = createMockContext({
inputsForms: [{ variable: 'sel', type: InputVarType.select, label: 'Sel', options: ['A', 'B'], default: 'B' }],
@ -258,7 +258,7 @@ describe('InputsFormContent', () => {
renderWithContext(<InputsFormContent />, context)
await user.click(screen.getByText('B'))
expect(screen.getByText('A').closest('.z-\\[60\\]')).not.toBeNull()
expect(screen.getByText('A').closest('.z-1002')).not.toBeNull()
})
it('handles select input with existing value (value not in options -> shows placeholder)', () => {

View File

@ -92,7 +92,7 @@ const InputsFormContent = ({ showTip }: Props) => {
<SelectTrigger className="w-full">
{String(inputsFormValue?.[form.variable] ?? form.default ?? form.label)}
</SelectTrigger>
<SelectContent popupClassName="z-[60] w-(--anchor-width)">
<SelectContent>
{form.options.map((option: string) => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -200,7 +200,7 @@ describe('InputsFormContent', () => {
expect(mockContextValue.handleNewConversationInputsChange).toHaveBeenCalled()
})
it('should render select dropdown above the settings dialog layer', async () => {
it('should render select dropdown on the shared dify-ui overlay layer', async () => {
render(<InputsFormContent />)
const selectTrigger = screen.getAllByText(/Select Label/i).find(el => el.tagName === 'SPAN')
if (!selectTrigger)
@ -208,7 +208,7 @@ describe('InputsFormContent', () => {
await user.click(selectTrigger)
expect(screen.getByText('Option 1').closest('.z-\\[60\\]')).not.toBeNull()
expect(screen.getByText('Option 1').closest('.z-1002')).not.toBeNull()
})
it('should handle single file upload change', async () => {

View File

@ -92,7 +92,7 @@ const InputsFormContent = ({ showTip }: Props) => {
<SelectTrigger className="w-full">
{String(inputsFormValue?.[form.variable] ?? form.default ?? form.label)}
</SelectTrigger>
<SelectContent popupClassName="z-[60] w-(--anchor-width)">
<SelectContent>
{form.options.map((option: string) => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -69,7 +69,7 @@ const FormGeneration: FC<FormGenerationProps> = ({
<SelectTrigger className="w-full">
{selectedOption?.name ?? form.placeholder}
</SelectTrigger>
<SelectContent popupClassName="z-102 w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -267,7 +267,7 @@ const BaseField = ({
: translatedPlaceholder}
</SelectValue>
</SelectTrigger>
<SelectContent popupClassName="max-h-[320px] w-(--anchor-width) bg-components-panel-bg-blur">
<SelectContent popupClassName="max-h-[320px] bg-components-panel-bg-blur">
{memorizedOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.label}</SelectItemText>
@ -293,7 +293,7 @@ const BaseField = ({
{nextValue => getSingleSelectLabel(nextValue, memorizedOptions, translatedPlaceholder)}
</SelectValue>
</SelectTrigger>
<SelectContent popupClassName="max-h-[320px] w-(--anchor-width) bg-components-panel-bg-blur">
<SelectContent popupClassName="max-h-[320px] bg-components-panel-bg-blur">
{memorizedOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.label}</SelectItemText>
@ -332,7 +332,7 @@ const BaseField = ({
: dynamicPlaceholder}
</SelectValue>
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width) bg-components-panel-bg-blur">
<SelectContent popupClassName="bg-components-panel-bg-blur">
{dynamicNoticeTitle && (
<div className={cn(
'flex h-[22px] items-center px-3 system-xs-medium-uppercase text-text-tertiary',
@ -367,7 +367,7 @@ const BaseField = ({
{nextValue => getSingleSelectLabel(nextValue, dynamicOptions, dynamicPlaceholder)}
</SelectValue>
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width) bg-components-panel-bg-blur">
<SelectContent popupClassName="bg-components-panel-bg-blur">
{dynamicNoticeTitle && (
<div className={cn(
'flex h-[22px] items-center px-3 system-xs-medium-uppercase text-text-tertiary',

View File

@ -80,7 +80,7 @@ const SelectField = ({
{(nextValue: string | null) => getDisplayLabel(nextValue, options, placeholderText)}
</SelectValue>
</SelectTrigger>
<SelectContent popupClassName={cn('w-(--anchor-width) bg-components-panel-bg-blur', popupProps?.className)}>
<SelectContent popupClassName={cn('bg-components-panel-bg-blur', popupProps?.className)}>
{popupProps?.title && (
<div
className={cn(

View File

@ -55,7 +55,7 @@ const FieldInfo: FC<FieldInfoProps> = ({
<SelectTrigger className={cn(s.select, s.selectWrapper)}>
{selectedOption?.name ?? `${t('metadata.placeholder.select', { ns: 'datasetDocuments' })}${label}`}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -85,7 +85,7 @@ export default function LanguagePage() {
<SelectTrigger size="large">
{selectedLanguage?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{languageOptions.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>
@ -111,7 +111,7 @@ export default function LanguagePage() {
<SelectTrigger size="large">
{selectedTimezone?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{timezones.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -76,7 +76,6 @@ const MemberSelector: FC<Props> = ({
placement="bottom"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1002 } }}
>
<div className="min-w-[372px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-xs">
<div className="p-2 pb-1">

View File

@ -302,7 +302,7 @@ function Form<
<SelectTrigger size="medium" className={cn(inputClassName)}>
{selectedOption?.name ?? placeholder?.[language] ?? placeholder?.en_US}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{filteredOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>
@ -494,7 +494,6 @@ function Form<
{infotipContent}
</div>
<VarReferencePicker
zIndex={1001}
readonly={false}
isShowNodeName
nodeId={nodeId || ''}

View File

@ -109,7 +109,7 @@ const SelectPackage: React.FC<SelectPackageProps> = ({
)}
</div>
</SelectTrigger>
<SelectContent popupClassName="z-1001 w-[512px]">
<SelectContent popupClassName="w-[512px]">
{versions.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>
@ -141,7 +141,7 @@ const SelectPackage: React.FC<SelectPackageProps> = ({
<SelectTrigger className="h-9 text-components-input-text-filled">
{selectedPackageOption?.name ?? t(`${i18nPrefix}.selectPackagePlaceholder`, { ns: 'plugin' }) ?? ''}
</SelectTrigger>
<SelectContent popupClassName="z-1001 w-[512px]">
<SelectContent popupClassName="w-[512px]">
{packages.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -70,7 +70,7 @@ const AppInputsForm = ({
<SelectTrigger className="w-full">
{selectedOption?.name ?? label}
</SelectTrigger>
<SelectContent popupClassName="z-1050 w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -80,19 +80,30 @@ vi.mock('@/hooks/use-oauth', () => ({
}))
vi.mock('../common-modal', () => ({
CommonCreateModal: ({ createType, onClose, builder }: {
CommonCreateModal: ({ open, createType, onClose, builder }: {
open?: boolean
createType: SupportedCreationMethods
onClose: () => void
builder?: TriggerSubscriptionBuilder
}) => (
<div
data-testid="common-create-modal"
data-create-type={createType}
data-has-builder={!!builder}
>
<button data-testid="close-modal" onClick={onClose}>Close</button>
</div>
),
}) => {
if (open === false)
return null
return (
<div
data-testid="common-create-modal"
data-create-type={createType}
data-has-builder={!!builder}
>
<button
data-testid="close-modal"
onClick={onClose}
>
Close
</button>
</div>
)
},
}))
vi.mock('../oauth-client', () => ({

View File

@ -23,12 +23,39 @@ import {
} from './hooks/use-common-modal-state'
type Props = {
open?: boolean
onClose: () => void
createType: SupportedCreationMethods
builder?: TriggerSubscriptionBuilder
}
export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
export const CommonCreateModal = ({ open = true, onClose, createType, builder }: Props) => {
return (
<Dialog
open={open}
onOpenChange={nextOpen => !nextOpen && onClose()}
disablePointerDismissal
>
<DialogContent
backdropProps={{ forceRender: true }}
className={cn(
'flex max-h-[80%] min-h-[360px] flex-col overflow-hidden p-0 shadow-xs',
createType === SupportedCreationMethods.MANUAL
? 'w-[640px] max-w-[calc(100vw-2rem)]'
: 'w-[480px] max-w-[calc(100vw-2rem)]',
)}
>
<CommonCreateModalContent
createType={createType}
builder={builder}
onClose={onClose}
/>
</DialogContent>
</Dialog>
)
}
function CommonCreateModalContent({ onClose, createType, builder }: Omit<Props, 'open'>) {
const { t } = useTranslation()
const {
@ -59,89 +86,77 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
const modalSize = createType === SupportedCreationMethods.MANUAL ? 'md' : 'sm'
return (
<Dialog open disablePointerDismissal>
<DialogContent
backdropProps={{ forceRender: true }}
className={cn(
'flex max-h-[80%] min-h-[360px] flex-col overflow-hidden p-0 shadow-xs',
modalSize === 'md'
? 'w-[640px] max-w-[calc(100vw-2rem)]'
: 'w-[480px] max-w-[calc(100vw-2rem)]',
<div
className="flex min-h-0 flex-1 flex-col"
data-testid="modal"
data-size={modalSize}
data-disabled={isDisabled}
>
<div className="relative shrink-0 p-6 pr-14 pb-3">
<DialogTitle className="title-2xl-semi-bold text-text-primary" data-testid="modal-title">
{t(MODAL_TITLE_KEY_MAP[createType], { ns: 'pluginTrigger' })}
</DialogTitle>
<DialogCloseButton
className="top-5 right-5 h-8 w-8 rounded-lg [&>span]:h-5 [&>span]:w-5"
data-testid="modal-close"
onClick={onClose}
/>
</div>
<div className="min-h-0 flex-1 overflow-y-auto px-6 py-3">
{isApiKeyType && <MultiSteps currentStep={currentStep} />}
{isVerifyStep && (
<VerifyStepContent
apiKeyCredentialsSchema={apiKeyCredentialsSchema}
apiKeyCredentialsFormRef={formRefs.apiKeyCredentialsFormRef}
onChange={handleApiKeyCredentialsChange}
/>
)}
>
<div
className="flex min-h-0 flex-1 flex-col"
data-testid="modal"
data-size={modalSize}
data-disabled={isDisabled}
>
<div className="relative shrink-0 p-6 pr-14 pb-3">
<DialogTitle className="title-2xl-semi-bold text-text-primary" data-testid="modal-title">
{t(MODAL_TITLE_KEY_MAP[createType], { ns: 'pluginTrigger' })}
</DialogTitle>
<DialogCloseButton
className="top-5 right-5 h-8 w-8 rounded-lg [&>span]:h-5 [&>span]:w-5"
data-testid="modal-close"
onClick={onClose}
/>
</div>
<div className="min-h-0 flex-1 overflow-y-auto px-6 py-3">
{isApiKeyType && <MultiSteps currentStep={currentStep} />}
{isConfigurationStep && (
<ConfigurationStepContent
createType={createType}
subscriptionBuilder={subscriptionBuilder}
subscriptionFormRef={formRefs.subscriptionFormRef}
autoCommonParametersSchema={autoCommonParametersSchema}
autoCommonParametersFormRef={formRefs.autoCommonParametersFormRef}
manualPropertiesSchema={manualPropertiesSchema}
manualPropertiesFormRef={formRefs.manualPropertiesFormRef}
onManualPropertiesChange={handleManualPropertiesChange}
logs={logData?.logs || []}
pluginId={detail?.plugin_id || ''}
pluginName={detail?.name || ''}
provider={detail?.provider || ''}
/>
)}
</div>
{isVerifyStep && (
<VerifyStepContent
apiKeyCredentialsSchema={apiKeyCredentialsSchema}
apiKeyCredentialsFormRef={formRefs.apiKeyCredentialsFormRef}
onChange={handleApiKeyCredentialsChange}
/>
)}
{isConfigurationStep && (
<ConfigurationStepContent
createType={createType}
subscriptionBuilder={subscriptionBuilder}
subscriptionFormRef={formRefs.subscriptionFormRef}
autoCommonParametersSchema={autoCommonParametersSchema}
autoCommonParametersFormRef={formRefs.autoCommonParametersFormRef}
manualPropertiesSchema={manualPropertiesSchema}
manualPropertiesFormRef={formRefs.manualPropertiesFormRef}
onManualPropertiesChange={handleManualPropertiesChange}
logs={logData?.logs || []}
pluginId={detail?.plugin_id || ''}
pluginName={detail?.name || ''}
provider={detail?.provider || ''}
/>
)}
</div>
<div className="flex shrink-0 justify-end p-6 pt-5">
<div className="flex items-center">
<Button
disabled={isDisabled}
onClick={onClose}
>
{t('operation.cancel', { ns: 'common' })}
</Button>
<Button
className="ml-2"
variant="primary"
disabled={isDisabled}
data-testid="modal-confirm"
onClick={handleConfirm}
>
{confirmButtonText}
</Button>
</div>
</div>
{isVerifyStep && (
<div className="shrink-0">
<EncryptedBottom />
</div>
)}
<div className="flex shrink-0 justify-end p-6 pt-5">
<div className="flex items-center">
<Button
disabled={isDisabled}
onClick={onClose}
>
{t('operation.cancel', { ns: 'common' })}
</Button>
<Button
className="ml-2"
variant="primary"
disabled={isDisabled}
data-testid="modal-confirm"
onClick={handleConfirm}
>
{confirmButtonText}
</Button>
</div>
</DialogContent>
</Dialog>
</div>
{isVerifyStep && (
<div className="shrink-0">
<EncryptedBottom />
</div>
)}
</div>
)
}

View File

@ -4,7 +4,6 @@ import { cn } from '@langgenius/dify-ui/cn'
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectTrigger } from '@langgenius/dify-ui/select'
import { toast } from '@langgenius/dify-ui/toast'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { RiAddLine, RiEqualizer2Line } from '@remixicon/react'
import { useBoolean } from 'ahooks'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@ -40,6 +39,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
const { subscriptions } = useSubscriptionList()
const subscriptionCount = subscriptions?.length || 0
const [selectedCreateInfo, setSelectedCreateInfo] = useState<{ type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder } | null>(null)
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false)
const detail = usePluginStore(state => state.detail)
const [isMenuOpen, setIsMenuOpen] = useState(false)
@ -89,8 +89,11 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
<Tooltip>
<TooltipTrigger
render={(
<ActionButton onClick={onClickClientSettings}>
<RiEqualizer2Line className="h-4 w-4 text-text-tertiary" />
<ActionButton
aria-label={t('subscription.addType.options.oauth.clientSettings', { ns: 'pluginTrigger' })}
onClick={onClickClientSettings}
>
<span aria-hidden className="i-ri-equalizer-2-line h-4 w-4 text-text-tertiary" />
</ActionButton>
)}
/>
@ -126,12 +129,21 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
show: supportedMethods.includes(SupportedCreationMethods.MANUAL),
},
]
}, [t, oauthConfig, supportedMethods, methodType, onClickClientSettings])
}, [t, oauthConfig, supportedMethods, onClickClientSettings])
const visibleOptions = useMemo(() => {
return allOptions.filter(option => option.show)
}, [allOptions])
const shouldAllowSelect = methodType === DEFAULT_METHOD || (methodType === SupportedCreationMethods.OAUTH && supportedMethods.length === 1)
const showCreateModal = useCallback((createInfo: { type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder }) => {
setSelectedCreateInfo(createInfo)
setIsCreateModalOpen(true)
}, [])
const hideCreateModal = useCallback(() => {
setIsCreateModalOpen(false)
}, [])
const onChooseCreateType = async (type: SupportedCreationMethods) => {
if (type === SupportedCreationMethods.OAUTH) {
if (oauthConfig?.configured) {
@ -140,7 +152,10 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
openOAuthPopup(response.authorization_url, (callbackData) => {
if (callbackData) {
toast.success(t('modal.oauth.authorization.authSuccess', { ns: 'pluginTrigger' }))
setSelectedCreateInfo({ type: SupportedCreationMethods.OAUTH, builder: response.subscription_builder })
showCreateModal({
type: SupportedCreationMethods.OAUTH,
builder: response.subscription_builder,
})
}
})
},
@ -154,7 +169,9 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
}
}
else {
setSelectedCreateInfo({ type })
showCreateModal({
type,
})
}
}
@ -202,7 +219,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
onClick={onClickCreate}
>
<div className="flex flex-1 items-center justify-center">
<RiAddLine className="mr-2 size-4" />
<span aria-hidden className="mr-2 i-ri-add-line size-4" />
{buttonTextMap[methodType!]}
{methodType === SupportedCreationMethods.OAUTH && oauthConfig?.custom_enabled && oauthConfig?.custom_configured && (
<Badge
@ -220,7 +237,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
<TooltipTrigger
render={(
<div onClick={onClickClientSettings} className="p-2">
<RiEqualizer2Line className="size-4 text-components-button-primary-text" />
<span aria-hidden className="i-ri-equalizer-2-line size-4 text-components-button-primary-text" />
</div>
)}
/>
@ -238,6 +255,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)}
render={(
<ActionButton
aria-label={buttonTextMap[methodType!]}
onClick={onClickCreate}
className={cn(
'float-right',
@ -245,7 +263,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
)}
state={subscriptionCount >= MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default}
>
<RiAddLine className="size-4" />
<span aria-hidden className="i-ri-add-line size-4" />
</ActionButton>
)}
/>
@ -255,7 +273,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
</Tooltip>
)}
</SelectTrigger>
<SelectContent placement="bottom-start" sideOffset={4} popupClassName={cn('z-1000', buttonType === CreateButtonType.FULL_BUTTON && 'min-w-(--anchor-width)')}>
<SelectContent placement="bottom-start" sideOffset={4}>
{visibleOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<div className="mr-8 flex grow items-center gap-1 truncate px-1">
@ -268,23 +286,33 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
))}
</SelectContent>
</Select>
{selectedCreateInfo && (
<CommonCreateModal
createType={selectedCreateInfo.type}
builder={selectedCreateInfo.builder}
onClose={() => setSelectedCreateInfo(null)}
/>
)}
{isShowClientSettingsModal && (
<OAuthClientSettingsModal
oauthConfig={oauthConfig}
onClose={() => {
hideClientSettingsModal()
refetchOAuthConfig()
}}
showOAuthCreateModal={builder => setSelectedCreateInfo({ type: SupportedCreationMethods.OAUTH, builder })}
/>
)}
{selectedCreateInfo
? (
<CommonCreateModal
open={isCreateModalOpen}
createType={selectedCreateInfo.type}
builder={selectedCreateInfo.builder}
onClose={hideCreateModal}
/>
)
: null}
{isShowClientSettingsModal
? (
<OAuthClientSettingsModal
oauthConfig={oauthConfig}
onClose={() => {
hideClientSettingsModal()
refetchOAuthConfig()
}}
showOAuthCreateModal={(builder) => {
showCreateModal({
type: SupportedCreationMethods.OAUTH,
builder,
})
}}
/>
)
: null}
</>
)
}

View File

@ -110,7 +110,6 @@ export const SubscriptionSelectorEntry = ({ selectedId, onSelect }: {
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 11 } }}
>
<div className="rounded-xl border border-components-panel-border bg-components-panel-bg shadow-lg">
<SubscriptionList

View File

@ -233,7 +233,7 @@ const ReasoningConfigForm: React.FC<Props> = ({
<SelectTrigger className="h-8 grow">
{selectedOption?.name ?? placeholder?.[language] ?? placeholder?.en_US}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{pickerProps.selectItems.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>
@ -278,7 +278,6 @@ const ReasoningConfigForm: React.FC<Props> = ({
)}
{showVariableSelector && (
<VarReferencePicker
zIndex={1001}
className="h-8 grow"
readonly={false}
isShowNodeName

View File

@ -58,7 +58,6 @@ const StrategyPicker = ({
<DropdownMenuContent
placement="top-end"
sideOffset={4}
className="z-99"
popupClassName="w-[280px] p-1"
>
<DropdownMenuRadioGroup

View File

@ -101,7 +101,6 @@ const ToolPicker: FC<Props> = ({
placement="top"
sideOffset={0}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="relative min-h-20 w-full rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur pb-2 shadow-lg backdrop-blur-xs">
<div className="p-2 pb-1">

View File

@ -138,7 +138,7 @@ const RunOnce: FC<IRunOnceProps> = ({
<SelectTrigger className="w-full">
{String(inputs[item.key] || item.default || t('placeholder.select', { ns: 'common' }))}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{(item.options || []).map(option => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -80,7 +80,6 @@ const LabelSelector: FC<LabelSelectorProps> = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1040 } }}
>
<div className="relative w-[591px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[5px]">
<div className="border-b-[0.5px] border-divider-regular p-2">

View File

@ -51,7 +51,6 @@ const MethodSelector: FC<MethodSelectorProps> = ({
<PopoverContent
placement="bottom-start"
sideOffset={4}
positionerProps={{ style: { zIndex: 1040 } }}
>
<div className="relative w-[320px]">
<div className="p-1">

View File

@ -545,7 +545,7 @@ export const CommentThread: FC<CommentThreadProps> = memo(({
<DropdownMenuContent
placement="bottom-end"
sideOffset={4}
popupClassName="z-[100] w-36 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[10px]"
popupClassName="w-36 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[10px]"
>
<button
className="flex w-full items-center justify-start rounded-xl px-3 py-2 text-left text-sm text-text-secondary hover:bg-state-base-hover"
@ -635,7 +635,7 @@ export const CommentThread: FC<CommentThreadProps> = memo(({
<DropdownMenuContent
placement="bottom-end"
sideOffset={4}
popupClassName="z-[100] w-36 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[10px]"
popupClassName="w-36 rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg backdrop-blur-[10px]"
data-reply-menu
>
<div className={cn(deletingReplyId === reply.id ? 'hidden' : 'block')}>

View File

@ -231,7 +231,6 @@ export const AgentStrategySelector = memo((props: AgentStrategySelectorProps) =>
placement="bottom"
sideOffset={0}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 10 } }}
>
<div className="w-[388px] overflow-hidden rounded-md border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow">
<header className="flex gap-1 p-2">

View File

@ -191,7 +191,7 @@ const FormItem: FC<Props> = ({
<SelectTrigger className="w-full">
{String(value || payload.default || t('placeholder.select', { ns: 'common' }))}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{(payload.options || []).map(option => (
<SelectItem key={option} value={option}>
<SelectItemText>{option}</SelectItemText>

View File

@ -65,7 +65,6 @@ const FormInputItem: FC<Props> = ({
schema,
value,
onChange,
inPanel,
currentTool,
currentProvider,
showManageInputField,
@ -329,7 +328,7 @@ const FormInputItem: FC<Props> = ({
<SelectTrigger className="h-8 grow">
{selectedStaticOption?.name ?? placeholder?.[language] ?? placeholder?.en_US}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{staticSelectItems.map(item => (
<SelectItem key={item.value} value={item.value}>
{item.icon && (
@ -361,7 +360,7 @@ const FormInputItem: FC<Props> = ({
<SelectTrigger className="h-8 grow">
{selectedDynamicOption?.name ?? (isLoadingOptions ? 'Loading...' : (placeholder?.[language] ?? placeholder?.en_US))}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{dynamicSelectItems.map(item => (
<SelectItem key={item.value} value={item.value}>
{item.icon && (
@ -413,7 +412,6 @@ const FormInputItem: FC<Props> = ({
)}
{showVariableSelector && (
<VarReferencePicker
zIndex={inPanel ? 1000 : undefined}
className="h-8 grow"
readonly={readOnly}
isShowNodeName

View File

@ -66,7 +66,7 @@ const ConstantField: FC<Props> = ({
>
{selectedOption?.name ?? placeholder?.[language] ?? placeholder?.en_US}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -82,7 +82,6 @@ type Props = {
placeholder?: string
minWidth?: number
popupFor?: 'assigned' | 'toAssigned'
zIndex?: number
currentTool?: Tool
currentProvider?: ToolWithProvider | TriggerWithProvider
preferSchemaType?: boolean
@ -117,7 +116,6 @@ const VarReferencePicker: FC<Props> = ({
placeholder,
minWidth,
popupFor,
zIndex,
currentTool,
currentProvider,
preferSchemaType,
@ -415,11 +413,6 @@ const VarReferencePicker: FC<Props> = ({
sideOffset={0}
className="mt-1"
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{
style: {
zIndex: zIndex || 100,
},
}}
>
{!isConstant && (
<VarReferencePopup
@ -428,7 +421,6 @@ const VarReferencePicker: FC<Props> = ({
onChange={handleVarReferenceChange}
itemWidth={isAddBtnTrigger ? 260 : (minWidth || triggerWidth)}
isSupportFileVar={isSupportFileVar}
zIndex={zIndex}
preferSchemaType={preferSchemaType}
/>
)}

View File

@ -14,7 +14,6 @@ type Props = {
onChange: (value: ValueSelector, varDetail: Var) => void
itemWidth?: number
isSupportFileVar?: boolean
zIndex?: number
preferSchemaType?: boolean
}
const VarReferencePopup: FC<Props> = ({
@ -23,7 +22,6 @@ const VarReferencePopup: FC<Props> = ({
onChange,
itemWidth,
isSupportFileVar = true,
zIndex,
preferSchemaType,
}) => {
const { t } = useTranslation()
@ -68,7 +66,6 @@ const VarReferencePopup: FC<Props> = ({
onChange={onChange}
itemWidth={itemWidth}
isSupportFileVar={isSupportFileVar}
zIndex={zIndex}
showManageInputField={showManageRagInputFields}
onManageInputField={() => setShowInputFieldPanel?.(true)}
preferSchemaType={preferSchemaType}

View File

@ -78,7 +78,6 @@ type ItemProps = {
isLoopVar?: boolean
isFlat?: boolean
isInCodeGeneratorInstructionEditor?: boolean
zIndex?: number
className?: string
preferSchemaType?: boolean
isSelected?: boolean
@ -97,7 +96,6 @@ const Item: FC<ItemProps> = ({
isLoopVar,
isFlat,
isInCodeGeneratorInstructionEditor,
zIndex,
className,
preferSchemaType,
isSelected,
@ -265,11 +263,6 @@ const Item: FC<ItemProps> = ({
placement="left-start"
sideOffset={0}
popupClassName={cn(VAR_REFERENCE_CHILD_POPUP_CLASS_NAME, 'border-none bg-transparent p-0 shadow-none backdrop-blur-none')}
positionerProps={{
style: {
zIndex: zIndex || 100,
},
}}
>
{(isStructureOutput || isObj) && (
<PickerStructurePanel
@ -297,7 +290,6 @@ type Props = {
maxHeightClass?: string
onClose?: () => void
onBlur?: () => void
zIndex?: number
isInCodeGeneratorInstructionEditor?: boolean
showManageInputField?: boolean
onManageInputField?: () => void
@ -315,7 +307,6 @@ const VarReferenceVars: FC<Props> = ({
maxHeightClass,
onClose,
onBlur,
zIndex,
isInCodeGeneratorInstructionEditor,
showManageInputField,
onManageInputField,
@ -490,7 +481,6 @@ const VarReferenceVars: FC<Props> = ({
isLoopVar={item.isLoop}
isFlat={item.isFlat}
isInCodeGeneratorInstructionEditor={isInCodeGeneratorInstructionEditor}
zIndex={zIndex}
preferSchemaType={preferSchemaType}
isSelected={effectiveSelectedIndex === optionIndex}
onActivate={() => setSelectedIndex(optionIndex)}

View File

@ -51,7 +51,6 @@ const DependencyPicker: FC<Props> = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 100 } }}
>
<div
className="rounded-lg bg-white p-1 shadow-sm"

View File

@ -155,12 +155,7 @@ const EmailInput = ({
sideOffset={4}
alignOffset={-40}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{
anchor: inputRef,
style: {
zIndex: 1000,
},
}}
positionerProps={{ anchor: inputRef }}
>
<MemberList
searchValue={searchKey}

View File

@ -58,7 +58,6 @@ const MemberSelector: FC<Props> = ({
sideOffset={4}
alignOffset={35}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<MemberList
searchValue={searchValue}

View File

@ -63,7 +63,6 @@ const ConditionAdd = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars

View File

@ -373,7 +373,7 @@ const ConditionItem = ({
<SelectTrigger className="h-8 rounded-t-none border-0 px-2 text-xs hover:bg-components-input-bg-normal focus-visible:bg-components-input-bg-normal">
{selectedSelectOption?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value} className="text-xs">
<SelectItemText>{option.name}</SelectItemText>

View File

@ -44,7 +44,6 @@ const ConditionVarSelector = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars

View File

@ -101,7 +101,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
<div className="px-4 pb-2">
<Field title={t(`${i18nPrefix}.MaxParallelismTitle`, { ns: 'workflow' })} isSubTitle tooltip={<div className="w-[230px]">{t(`${i18nPrefix}.MaxParallelismDesc`, { ns: 'workflow' })}</div>}>
<div className="row flex">
<Input type="number" wrapperClassName="w-18 mr-4 " max={MAX_PARALLEL_LIMIT} min={MIN_ITERATION_PARALLEL_NUM} value={inputs.parallel_nums} onChange={(e) => { changeParallelNums(Number(e.target.value)) }} />
<Input type="number" wrapperClassName="w-18 mr-4" max={MAX_PARALLEL_LIMIT} min={MIN_ITERATION_PARALLEL_NUM} value={inputs.parallel_nums} onChange={(e) => { changeParallelNums(Number(e.target.value)) }} />
<Slider
value={inputs.parallel_nums}
onValueChange={changeParallelNums}
@ -133,7 +133,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
<SelectTrigger className="w-full">
{selectedResponseMethod?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{responseMethod.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -50,7 +50,6 @@ const AddCondition = ({
placement="bottom-start"
sideOffset={12}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1002 } }}
>
<div className="w-[320px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<div className="p-2 pb-1">

View File

@ -63,7 +63,6 @@ const ConditionCommonVariableSelector = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[200px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
{variables.map(v => (

View File

@ -70,7 +70,6 @@ const ConditionVariableSelector = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars

View File

@ -134,7 +134,7 @@ const ValueInput = ({
<SelectTrigger className="h-8 grow text-[13px]">
{selectedOption?.name ?? 'Select value'}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -61,7 +61,6 @@ const ConditionAdd = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars

View File

@ -317,7 +317,7 @@ const ConditionItem = ({
<SelectTrigger className="h-8 rounded-t-none border-0 px-2 text-xs hover:bg-components-input-bg-normal focus-visible:bg-components-input-bg-normal">
{selectedSelectOption?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{selectOptions.map(option => (
<SelectItem key={option.value} value={option.value} className="text-xs">
<SelectItemText>{option.name}</SelectItemText>

View File

@ -44,7 +44,6 @@ const ConditionVarSelector = ({
placement="bottom-start"
sideOffset={4}
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
positionerProps={{ style: { zIndex: 1000 } }}
>
<div className="w-[296px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg">
<VarReferenceVars

View File

@ -27,7 +27,7 @@ const InputModeSelect = ({
<SelectTrigger className="w-full">
{selectedOption?.label ?? t('nodes.loop.inputMode', { ns: 'workflow' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{options.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.label}</SelectItemText>

View File

@ -50,7 +50,7 @@ const VariableTypeSelect = ({
<SelectTrigger className="w-full">
{selectedOption?.label}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{options.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.label}</SelectItemText>

View File

@ -147,7 +147,7 @@ const AddExtractParameter: FC<Props> = ({
<SelectTrigger className="w-full capitalize">
{param.type}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{TYPES.map(type => (
<SelectItem key={type} value={type} className="capitalize">
<SelectItemText className="capitalize">{type}</SelectItemText>

View File

@ -44,7 +44,7 @@ const FrequencySelector = ({ frequency, onChange }: FrequencySelectorProps) => {
<SelectTrigger className="w-full py-2">
{selectedFrequency?.name ?? t('nodes.triggerSchedule.selectFrequency', { ns: 'workflow' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
<SelectGroup>
<SelectLabel>{groupLabel}</SelectLabel>
{frequencies.map(item => (

View File

@ -147,7 +147,7 @@ const renderSelectCell = (
>
{selectedOption?.name ?? column.placeholder}
</SelectTrigger>
<SelectContent className="-translate-x-3" popupClassName="z-60 w-26 min-w-26">
<SelectContent className="-translate-x-3" popupClassName="w-26 min-w-26">
{options.map(option => (
<SelectItem key={option.value} value={option.value}>
<SelectItemText>{option.name}</SelectItemText>

View File

@ -95,7 +95,7 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
<SelectTrigger className="h-8 pr-8 text-sm">
{selectedMethod?.name}
</SelectTrigger>
<SelectContent popupClassName="z-5 w-26 min-w-26">
<SelectContent popupClassName="w-26 min-w-26">
{HTTP_METHODS.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>
@ -167,7 +167,7 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
<SelectTrigger className="h-8 w-full text-sm">
{selectedContentType?.name}
</SelectTrigger>
<SelectContent popupClassName="z-5">
<SelectContent>
{CONTENT_TYPES.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -87,33 +87,34 @@ const SearchInput = ({
/>
)}
/>
{open && !!schools.length && !!value && (
<PopoverContent
placement="bottom"
sideOffset={4}
popupClassName="w-[var(--anchor-width)] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg"
positionerProps={{ style: { zIndex: 32 } }}
>
<div
className="max-h-[330px] overflow-y-auto"
onScroll={handleScroll}
>
{schools.map(school => (
{!!schools.length && !!value
? (
<PopoverContent
placement="bottom"
sideOffset={4}
popupClassName="w-[var(--anchor-width)] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg"
>
<div
key={school}
className="flex h-8 cursor-pointer items-center truncate rounded-lg px-2 py-1.5 system-md-regular text-text-secondary hover:bg-state-base-hover"
title={school}
onClick={() => {
onChange(school)
setOpen(false)
}}
className="max-h-[330px] overflow-y-auto"
onScroll={handleScroll}
>
{school}
{schools.map(school => (
<div
key={school}
className="flex h-8 cursor-pointer items-center truncate rounded-lg px-2 py-1.5 system-md-regular text-text-secondary hover:bg-state-base-hover"
title={school}
onClick={() => {
onChange(school)
setOpen(false)
}}
>
{school}
</div>
))}
</div>
))}
</div>
</PopoverContent>
)}
</PopoverContent>
)
: null}
</Popover>
)
}

View File

@ -138,7 +138,7 @@ export default function InviteSettingsPage() {
<SelectTrigger size="large">
{selectedLanguage?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{languageOptions.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -151,7 +151,7 @@ const OneMoreStep = () => {
<SelectTrigger size="large">
{selectedLanguage?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{languageOptions.map(item => (
<SelectItem key={item.value} value={item.value}>
<SelectItemText>{item.name}</SelectItemText>
@ -178,7 +178,7 @@ const OneMoreStep = () => {
<SelectTrigger size="large">
{selectedTimezone?.name ?? t('placeholder.select', { ns: 'common' })}
</SelectTrigger>
<SelectContent popupClassName="w-(--anchor-width)">
<SelectContent>
{timezones.map(item => (
<SelectItem key={item.value} value={String(item.value)}>
<SelectItemText>{item.name}</SelectItemText>

View File

@ -102,7 +102,7 @@ export const CheckModal = () => {
const confirmInfo = anthropicConfirmInfo || notionConfirmInfo || billingConfirmInfo
if (!confirmInfo || !showPayStatusModal)
if (!confirmInfo)
return null
const description = (confirmInfo as { desc?: string }).desc || ''