ListPicker
Selection modal for choosing from a list of options with optional search.
Basic Usage
import { ListPicker } from '@multinaire/expo-ui';
<ListPicker
type="dropdown"
items={[
{ value: 'us', text: 'United States' },
{ value: 'uk', text: 'United Kingdom' },
{ value: 'ca', text: 'Canada' },
]}
selectedItem={selectedCountry}
onChange={(item) => setSelectedCountry(item)}
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
type | 'list' | 'dropdown' | — | Presentation style of the picker. 'list' shows items inline; 'dropdown' shows them in a modal |
items | ListPickerItemData[] | — | Array of selectable items |
selectedItem | T | — | Currently selected item value |
isLoading | boolean | false | Show loading skeleton items in place of the list |
searchInputPlaceholder | string | — | Placeholder text for the search input |
searchPredicate | (item, filter) => boolean | — | Custom filter predicate. Return true to keep the item visible for a given filter string |
onChangeSearch | (filter: string) => void | — | Callback invoked on every keystroke in the search input |
onChange | (item: T) => void | — | Callback invoked with the newly selected item value |
onSearch | (filter: string) => void | — | Callback invoked when the user submits a search query |
ListPickerItemData
| Property | Type | Description |
|---|---|---|
value | T | The value associated with this item, passed to onChange when selected |
text | string | Primary label text of the item. Rendered on a single line — longer text is truncated with an ellipsis |
leading | IconName | ImageSource | Leading icon name or image source displayed at the start of the item |
ListPickerItem
The row ListPicker renders for each item, exported for use on its own — as a
list row elsewhere, or as the row of a
SortableContainer, whose default
itemHeight is exactly this row's height.
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | — | Primary label text of the item. Rendered on a single line — longer text is truncated with an ellipsis |
leading | IconName | ImageSource | — | Leading icon name or image source displayed at the start of the item |
selected | boolean | false | Whether the item reads as selected. Adds a trailing checkmark and a highlighted border |
testID | string | text | Test identifier for UI automation |
onPress | () => void | — | Callback invoked when the item is pressed. Omit it to render a non-interactive row — the row no longer dims on touch, and a surrounding gesture (a SortableContainer drag, for instance) receives the touch uncontested |
Examples
Dropdown Picker
<ListPicker
type="dropdown"
items={countries.map((c) => ({
value: c.code,
text: c.name,
leading: { uri: c.flagUrl },
}))}
selectedItem={country}
onChange={setCountry}
/>
List Picker with Search
<ListPicker
type="list"
items={users.map((u) => ({
value: u.id,
text: u.name,
leading: { uri: u.avatarUrl },
}))}
selectedItem={selectedUser}
searchInputPlaceholder="Search users..."
searchPredicate={(item, filter) =>
item.text.toLowerCase().includes(filter.toLowerCase())
}
onChange={setSelectedUser}
/>
With Icons
<ListPicker
type="dropdown"
items={[
{ value: 'card', text: 'Credit Card', leading: 'CreditCard' },
{ value: 'paypal', text: 'PayPal', leading: 'Wallet' },
{ value: 'bank', text: 'Bank Transfer', leading: 'Building' },
]}
selectedItem={paymentMethod}
onChange={setPaymentMethod}
/>
With Loading State
<ListPicker
type="list"
isLoading={isLoadingOptions}
items={options}
selectedItem={selected}
onChange={setSelected}
/>
Server-Side Search
<ListPicker
type="list"
items={searchResults}
selectedItem={selected}
searchInputPlaceholder="Search..."
onSearch={(query) => fetchSearchResults(query)}
onChange={setSelected}
/>
Notes
- Each row is a fixed-height
Card, and its label is capped at one line — longtexttruncates with an ellipsis rather than wrapping, so rows stay aligned with each other and with their leading icon and selected checkmark.