From 533929d314a49d1b1c2c2f46440d8e741a4b9473 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Tue, 26 May 2026 15:59:59 +0800 Subject: [PATCH] fix(dify-ui): align picker stories with Base UI (#36680) --- .../src/autocomplete/__tests__/index.spec.tsx | 31 ++++ .../src/autocomplete/index.stories.tsx | 64 +++++--- packages/dify-ui/src/autocomplete/index.tsx | 2 +- .../src/combobox/__tests__/index.spec.tsx | 88 +++++++---- .../dify-ui/src/combobox/index.stories.tsx | 146 ++++++++++++++---- packages/dify-ui/src/combobox/index.tsx | 2 +- .../src/select/__tests__/index.spec.tsx | 37 ++++- packages/dify-ui/src/select/index.stories.tsx | 7 +- packages/dify-ui/src/select/index.tsx | 2 +- web/app/components/base/chip/index.tsx | 2 +- 10 files changed, 295 insertions(+), 86 deletions(-) diff --git a/packages/dify-ui/src/autocomplete/__tests__/index.spec.tsx b/packages/dify-ui/src/autocomplete/__tests__/index.spec.tsx index 72ed042033..d0cab69401 100644 --- a/packages/dify-ui/src/autocomplete/__tests__/index.spec.tsx +++ b/packages/dify-ui/src/autocomplete/__tests__/index.spec.tsx @@ -218,6 +218,8 @@ describe('Autocomplete wrappers', () => { await expect.element(screen.getByText('Workflow')).toHaveClass('system-sm-medium') await expect.element(screen.getByTestId('status')).toHaveClass('text-text-tertiary') await expect.element(screen.getByTestId('empty')).toHaveClass('system-sm-regular') + await expect.element(screen.getByTestId('empty')).toHaveClass('empty:p-0') + expect(screen.getByTestId('empty').element().getBoundingClientRect().height).toBe(0) expect(screen.getByText('Workflow').element().parentElement?.querySelector('.i-ri-arrow-right-line')).toHaveAttribute('aria-hidden', 'true') }) @@ -248,5 +250,34 @@ describe('Autocomplete wrappers', () => { await expect.element(screen.getByText('Workflow')).toHaveClass('custom-text') await expect.element(screen.getByTestId('indicator')).toHaveClass('custom-indicator') }) + + it('should navigate function-rendered items with arrow keys', async () => { + const screen = await renderWithSafeViewport( + + + + + + + {(item: string) => ( + + {item} + + )} + + + , + ) + + const input = asHTMLElement(screen.getByRole('combobox', { name: 'Search resources' }).element()) + + input.focus() + input.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true, cancelable: true })) + await expect.element(screen.getByRole('option', { name: 'workflow' })).toHaveAttribute('data-highlighted') + + input.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true, cancelable: true })) + + await expect.element(screen.getByRole('option', { name: 'dataset' })).toHaveAttribute('data-highlighted') + }) }) }) diff --git a/packages/dify-ui/src/autocomplete/index.stories.tsx b/packages/dify-ui/src/autocomplete/index.stories.tsx index 79f8983cd2..6de6b16766 100644 --- a/packages/dify-ui/src/autocomplete/index.stories.tsx +++ b/packages/dify-ui/src/autocomplete/index.stories.tsx @@ -160,12 +160,36 @@ const virtualizedSuggestions: Suggestion[] = Array.from({ length: 1000 }, (_, in const getSuggestionLabel = (item: Suggestion) => item.label const SuggestionItem = ({ + item, + dense, +}: { + item: Suggestion + dense?: boolean +}) => ( + + {item.icon && +) + +// Only virtualized items receive an explicit index; ordinary lists must let Base UI register items by DOM order for keyboard navigation. +const VirtualizedSuggestionItem = ({ item, index, dense, }: { item: Suggestion - index?: number + index: number dense?: boolean }) => ( @@ -186,12 +210,10 @@ const SuggestionItem = ({ const TagSuggestionItem = ({ item, - index, }: { item: Suggestion - index?: number }) => ( - + {item.label} {item.description && {item.description}} @@ -215,8 +237,8 @@ const BasicTagAutocomplete = ({ - {(item: Suggestion, index: number) => ( - + {(item: Suggestion) => ( + )} No tag suggestion. Keep the typed value. @@ -327,8 +349,8 @@ const AsyncSearchDemo = () => { {loading ? 'Loading suggestions…' : `${items.length} remote suggestions`} - {(item: Suggestion, index: number) => ( - + {(item: Suggestion) => ( + )} No remote suggestion. Keep the typed query. @@ -384,7 +406,7 @@ const VirtualizedSuggestionList = ({ transform: `translateY(${virtualItem.start}px)`, }} > - + ) })} @@ -455,8 +477,8 @@ const FuzzyMatchingDemo = () => { - {(item: Suggestion, index: number) => ( - + {(item: Suggestion) => ( + {item.icon &&