Select Menu
The single select is used for setting enumerable values when filtering data.
import { SelectMenu, FilterMenu, stateChangeTypes, SelectMenuButton, toggleArrayValue } from '@balance-web/select-menu';The SelectMenu shares most of its behaviour, appearance and API with the
DropdownMenu. Rather than accepting children you must provide options as an
array, an onChange handler and a value.
Standard
Single select
Multi select
The SelectMenu is unopinionated in how many items are selected in the list, or
how you manage selected options. Pass an array to the value prop to select
more items. Options in a multi select render a checkbox instead of a tick, and
in a FilterMenu the search text stays after each pick. When the screen
controls inputValue, the screen decides when to clear it.
Select all
Every multi select shows a "Select all" checkbox row above the options. Pass
onSelectAll to handle it, or hideSelectAll to opt out; the types require
one of the two when value is an array. The checkbox is empty when none of the shown options are selected,
partly selected when some are, and checked when all are. Choosing it selects
every shown option, or clears them when all are already selected. In a
FilterMenu, the shown options are the ones that match the search; disabled
options and selected options that are not shown are left as they are.
onSelectAll is called with the whole next value.
Disabled option
You may disable options where appropriate.
Filterable
The FilterMenu shares most of the SelectMenu API, with a few additions to
manage filtering -- checkout the SelectMenu docs to learn more.
Async
The FilterMenu has no opinions about how you filter the options, whether it's
client or server side. If you fetch options onInputChange, you must show the
user that it isLoading. We recommend using debounce (or similar) to
optimise performance.
Advanced
Footer
Use the footerOption prop to pin a special action item at the bottom of the
menu, separated by a divider. The footer item is always visible regardless of
scroll position. Use itemRenderer to render it differently from regular
options — typically as a TextLinkButton or similar call-to-action.
NOTE: Inside
itemRenderer, check the item's value to distinguish the footer item from regular options and return the appropriate element.
Group labels and dividers
A menu has no nested groups. To show group labels, dividers or other rows that
are not options, insert them into options and return false for them from
itemToSelectable. SelectMenu and FilterMenu render those rows with
itemRenderer, without a checkbox or tick and without padding, so the content
controls its own layout. The keyboard skips them, they can't be clicked or
chosen, and "Select all" leaves them out.
- Give every row a unique value from
itemToValue; it is the row's React key. itemHeightreceives the row's index inoptions("Select all" doesn't count), so return a smaller height for labels and dividers.- In a
FilterMenu, filter the groups before flattening them intooptions, so a label is never left without options under it.
Recipes
Mapping
Provide alternative properties in your options using the itemToDisabled,
itemToValue, and itemToLabel utilities. Map complex objects to the required
data select-menu requires while using other properties in the itemRenderer.
Item renderer
You can provide an alternate item renderer.
itemHeight
Used in conjunction with itemRenderer to achieve custom layouts.
Default is 40
Menu width
By default, the menu dialog will match the width of the input container. For situations where horizontal real estate is limited this might mean that menu items are clipped. Provide a menuWidth prop to resolve the issue, accomodating expected item label lengths.
Clearable value
Provide onClear in addition to the onChange handler to let the user clear
all the values with one click.
Labelling
There's a few strategies for displaying the value within the button.
selectedValueThreshold
The most user friendly approach is to display as much information as possible to the user within your space constraints. In the example below we show up to 2 values, then when there's more than two we show the first selected value and the remaining count.
Indicator
When horizontal space is at a premium you may want to display the count in a notification badge.
Custom trigger button
SelectMenuButton is the chip-styled button SelectMenu/FilterMenu render
internally as their default trigger — reach for it directly when you need a
trigger that looks native but with custom content, rather than passing a
function to trigger.
stateChangeTypes
stateChangeTypes re-exports downshift's
useCombobox.stateChangeTypes — the set of action-type constants downshift
uses internally (InputKeyDownEnter, ItemClick, …). Reach for it when you
need to distinguish how a selection was made, for example inside a custom
onLoadMore/onIsOpenChange handler for an embedded grid cell editor.
Pagination
SelectMenu can be used in a paginated mode using the infinite scrolling technique.
To use pagination you must provied the following props:
canLoadMore— signal that more items are availableonLoadMore— function to load more items when user reaches the bottom of the menu andcanLoadMoreis trueloadingState— must be kept in-sync to avoid duplicate calls
NOTE: Like all handlers,
onLoadMoremust be memoized withReact.useCallback()for performance.