tremorlabs / tremor

React components to build charts and dashboards
https://tremor.so
Apache License 2.0
15.39k stars 446 forks source link

[Feature]: Optionally limit the number of rendered options in a MultiSelect #990

Open miloknowles opened 2 months ago

miloknowles commented 2 months ago

What problem does this feature solve?

Problem

The MultiSelect component causes the browser to freeze when you have several hundred or thousands of options. Specifically, this happens when you click to open the dropdown menu and it has to render all of the children.

I've confirmed that filtering by a search query (below) is fine:

const filteredOptions = useMemo(
  () => (searchQuery ? getFilteredOptions(searchQuery, reactElementChildren) : optionsAvailable),
  [searchQuery, reactElementChildren, optionsAvailable],
);

... but rendering a large number of filteredOptions causes problems. If we limit the number of rendered options to e.g. 100, the performance is fine, and the user can still search through all of the options with a query.

Use-Case

In my case, I have a dataset with a few thousand people in it, and I want to allow the user to quickly select several rows to compare in a table (see below). This might be possible with table actions by checking/unchecking rows, but I'd prefer to use a MultiSelect.

In general, it seems like MultiSelect should be able to scale to more options.

Screenshot 2024-03-12 at 8 12 26 AM

What does the proposed API look like?

I propose adding an optional prop to MultiSelect: something like limitRenderedOptions?: number.

If set by the user, only a fixed number of children are rendered in the dropdown. Effectively, the user can still search through all options but only sees the top limitRenderedOptions results.

<SelectedValueContext.Provider
  {...{ onBlur: { handleResetSearch } }}
  value={{ selectedValue: value }}
>
  { limitRenderedOptions ? filteredOptions.slice(0, limitRenderedOptions) : filteredOptions }
</SelectedValueContext.Provider>

I've tested this change locally, and it solves the issue above.

Jonesmann1337 commented 1 month ago

I have basically the very same issue! This proposal sounds good to me.