Skip to content

SelectNext: support searching/filtering options #1254

Closed as not planned
Closed as not planned
@acelaya

Description

@acelaya

Add some way to do text search inside the SelectNext options, as sketched here hypothesis/client#5775 (comment)

Based on how the SelectNext component was architected, one way to support filtering items would be introducing a new <Select.Filterable /> wrapper for <Select.Option /> items, which allows children to be filtered via context.

function App() {
  const [selected, setSelected] = useState<(typeof items)[number]>();

  return (
    <Select {...}>
      <Select.Option value={...}>Main</Select.Option>

      <Select.Filterable onFilter={(query: string, value: T) => boolean} placeholder={...}>
        {items.map(item => (
          <Select.Option value={item} key={item.id}>
            {({ disabled, isSelected }) => <>{item.name} ({item.id})</>}
          </Select.Option>
        ))}
      </Select.Filterable>
    </Select>
  )
}

Then we can expose the onFilter callback via context, down to the Option entries, which can decide if they should render or not, based on that.

We could even allow multiple Filterable blocks, or options outside any Filterable, that cannot be filtered. Ideally the search box should be position sticky, making sure it's visible while scrolling between the options it can filter.

The Filterable component could be something in these lines:

const FilterableContext = createContext<{ shouldRender: (value: T) => boolean } | null>(null);

function Filterable<T>({ onFilter, placeholder, children }) {
  const [query, setQuery] = useState('');
  const shouldRender = useCallback(
    (value: T) => onFilter(query, value), 
    [onFilter, query],
  );

  return (
    <FilterableContext.Provider value={{ shouldRender }}>
      <input type="search" placeholder={placeholder} value={query} onInput={e => setQuery(e.target.value)} />
      {children}
    </FilterableContext.Provider>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions