mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
refactor: normalize search input and dify-ui focus states (#37413)
This commit is contained in:
@@ -217,16 +217,6 @@ function List({
|
||||
placeholder={t('operation.search', { ns: 'common' })}
|
||||
aria-label={t('gotoAnything.actions.searchApplications', { ns: 'app' })}
|
||||
/>
|
||||
{!!keywords && (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('operation.clear', { ns: 'common' })}
|
||||
className="absolute top-1/2 right-2 flex size-4 -translate-y-1/2 items-center justify-center text-components-input-text-placeholder hover:text-components-input-text-filled"
|
||||
onClick={() => setKeywords('')}
|
||||
>
|
||||
<span aria-hidden className="i-ri-close-circle-fill size-4" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
|
||||
@@ -71,7 +71,7 @@ export function Infotip({
|
||||
aria-label={ariaLabel}
|
||||
onClick={handleClick}
|
||||
className={cn(
|
||||
'inline-flex size-4 shrink-0 cursor-pointer items-center justify-center border-0 bg-transparent p-0 focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden',
|
||||
'inline-flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -35,6 +35,23 @@ describe('SearchInput', () => {
|
||||
const clearButton = screen.getByLabelText('common.operation.clear')
|
||||
expect(clearButton).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('uses the design-system focus treatment for the clear button', () => {
|
||||
render(<SearchInput value="has value" onValueChange={() => {}} />)
|
||||
|
||||
const clearButton = screen.getByRole('button', { name: 'common.operation.clear' })
|
||||
expect(clearButton).toHaveClass(
|
||||
'right-1.5',
|
||||
'size-5',
|
||||
'focus-visible:bg-components-input-bg-hover',
|
||||
'focus-visible:ring-2',
|
||||
'focus-visible:ring-state-accent-solid',
|
||||
'focus-visible:ring-inset',
|
||||
)
|
||||
expect(clearButton).not.toHaveClass('size-4')
|
||||
expect(clearButton).not.toHaveClass('focus-visible:ring-1')
|
||||
expect(clearButton).not.toHaveClass('focus-visible:ring-components-input-border-active')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Interaction', () => {
|
||||
|
||||
@@ -84,6 +84,7 @@ export function SearchInput({
|
||||
onValueChange(e.currentTarget.value)
|
||||
}}
|
||||
autoComplete="off"
|
||||
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||||
autoFocus={autoFocus}
|
||||
enterKeyHint="search"
|
||||
/>
|
||||
@@ -91,7 +92,7 @@ export function SearchInput({
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('operation.clear', { ns: 'common' })}
|
||||
className="group/clear absolute top-1/2 right-2 flex size-4 -translate-y-1/2 cursor-pointer touch-manipulation items-center justify-center rounded-md border-none bg-transparent p-0 outline-hidden focus-visible:ring-1 focus-visible:ring-components-input-border-active focus-visible:ring-inset"
|
||||
className="group/clear absolute top-1/2 right-1.5 flex size-5 -translate-y-1/2 cursor-pointer touch-manipulation items-center justify-center rounded-md border-none bg-transparent p-0 outline-hidden focus-visible:bg-components-input-bg-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-inset"
|
||||
onClick={handleClear}
|
||||
>
|
||||
<span className="i-ri-close-circle-fill size-4 text-text-quaternary group-hover/clear:text-text-tertiary" aria-hidden="true" />
|
||||
|
||||
@@ -146,7 +146,7 @@ describe('List', () => {
|
||||
|
||||
it('should render the search input', () => {
|
||||
render(<List />)
|
||||
expect(screen.getByRole('textbox')).toBeInTheDocument()
|
||||
expect(screen.getByRole('searchbox')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render tag filter', () => {
|
||||
@@ -195,7 +195,7 @@ describe('List', () => {
|
||||
it('should update search input value', () => {
|
||||
render(<List />)
|
||||
|
||||
const input = screen.getByRole('textbox')
|
||||
const input = screen.getByRole('searchbox')
|
||||
fireEvent.change(input, { target: { value: 'test search' } })
|
||||
|
||||
expect(input).toHaveValue('test search')
|
||||
@@ -259,7 +259,7 @@ describe('List', () => {
|
||||
it('should clear search input when onClear is called', () => {
|
||||
render(<List />)
|
||||
|
||||
const input = screen.getByRole('textbox')
|
||||
const input = screen.getByRole('searchbox')
|
||||
// First set a value
|
||||
fireEvent.change(input, { target: { value: 'test search' } })
|
||||
expect(input).toHaveValue('test search')
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useBoolean, useDebounceFn } from 'ahooks'
|
||||
// Libraries
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { SearchInput } from '@/app/components/base/search-input'
|
||||
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
|
||||
import { useAppContext, useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import { useExternalApiPanel } from '@/context/external-api-panel-context'
|
||||
@@ -69,13 +69,10 @@ const List = () => {
|
||||
/>
|
||||
)}
|
||||
<TagFilter type="knowledge" value={tagFilterValue} onChange={handleTagsChange} onOpenTagManagement={() => setShowTagManagementModal(true)} />
|
||||
<Input
|
||||
showLeftIcon
|
||||
showClearIcon
|
||||
wrapperClassName="w-[200px]"
|
||||
<SearchInput
|
||||
className="w-50"
|
||||
value={keywords}
|
||||
onChange={e => handleKeywordsChange(e.target.value)}
|
||||
onClear={() => handleKeywordsChange('')}
|
||||
onValueChange={handleKeywordsChange}
|
||||
/>
|
||||
{
|
||||
isCurrentWorkspaceManager && (
|
||||
|
||||
Reference in New Issue
Block a user