fix(web): migrate variable type selector overlay (#35590)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
This commit is contained in:
非法操作 2026-04-27 13:27:19 +08:00 committed by GitHub
parent 818a71d637
commit 6c089cab66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 45 deletions

View File

@ -5338,14 +5338,6 @@
"count": 2
}
},
"web/app/components/workflow/panel/chat-variable-panel/components/variable-type-select.tsx": {
"no-restricted-imports": {
"count": 1
},
"ts/no-explicit-any": {
"count": 4
}
},
"web/app/components/workflow/panel/chat-variable-panel/type.ts": {
"erasable-syntax-only/enums": {
"count": 1

View File

@ -36,8 +36,9 @@ describe('VariableTypeSelector', () => {
await user.keyboard('{Escape}')
await waitFor(() => {
expect(screen.queryByText('number')).not.toBeInTheDocument()
expect(screen.getByRole('combobox')).toHaveAttribute('aria-expanded', 'false')
})
expect(screen.queryByRole('listbox')).not.toBeInTheDocument()
})
it('keeps the custom popup class in in-cell mode', async () => {

View File

@ -1,38 +1,47 @@
'use client'
import { cn } from '@langgenius/dify-ui/cn'
import { RiArrowDownSLine, RiCheckLine } from '@remixicon/react'
import { Select, SelectContent, SelectItem, SelectItemIndicator, SelectItemText, SelectTrigger } from '@langgenius/dify-ui/select'
import * as React from 'react'
import { useState } from 'react'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
type Props = {
type Props<T extends string> = {
inCell?: boolean
value?: any
list: any
onSelect: (value: any) => void
value?: T
list: readonly T[]
onSelect: (value: T) => void
popupClassName?: string
}
const VariableTypeSelector = ({
const VariableTypeSelector = <T extends string, >({
inCell = false,
value,
list,
onSelect,
popupClassName,
}: Props) => {
}: Props<T>) => {
const [open, setOpen] = useState(false)
const handleValueChange = (nextValue: string | null) => {
if (!nextValue)
return
const nextItem = list.find(item => item === nextValue)
if (!nextItem)
return
onSelect(nextItem)
}
return (
<PortalToFollowElem
<Select
value={value ?? null}
open={open}
onOpenChange={() => setOpen(v => !v)}
placement="bottom"
onOpenChange={setOpen}
onValueChange={handleValueChange}
>
<PortalToFollowElemTrigger className="w-full" onClick={() => setOpen(v => !v)}>
<SelectTrigger
className="h-auto w-full max-w-none cursor-pointer rounded-none bg-transparent p-0 hover:bg-transparent focus-visible:bg-transparent data-popup-open:bg-transparent [&>*:last-child]:hidden"
>
<div className={cn(
'flex w-full cursor-pointer items-center px-2',
!inCell && 'rounded-lg bg-components-input-bg-normal py-1 hover:bg-state-base-hover-alt',
@ -48,27 +57,22 @@ const VariableTypeSelector = ({
>
{value}
</div>
<RiArrowDownSLine className="ml-0.5 h-4 w-4 text-text-quaternary" />
<span className="ml-0.5 i-ri-arrow-down-s-line h-4 w-4 text-text-quaternary" aria-hidden="true" />
</div>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className={cn('z-11 w-full', popupClassName)}>
<div className="rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
{list.map((item: any) => (
<div
key={item}
className="flex cursor-pointer items-center gap-2 rounded-lg py-[6px] pr-2 pl-3 hover:bg-state-base-hover"
onClick={() => {
onSelect(item)
setOpen(false)
}}
>
<div className="grow truncate system-md-regular text-text-secondary">{item}</div>
{value === item && <RiCheckLine className="h-4 w-4 text-text-accent" />}
</div>
))}
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
</SelectTrigger>
<SelectContent placement="bottom-start" popupClassName={cn('bg-components-panel-bg-blur', popupClassName)}>
{list.map(item => (
<SelectItem
key={item}
value={item}
className="h-auto gap-2 py-[6px] pr-2 pl-3 system-md-regular font-normal"
>
<SelectItemText className="px-0 system-md-regular text-text-secondary">{item}</SelectItemText>
<SelectItemIndicator />
</SelectItem>
))}
</SelectContent>
</Select>
)
}