Listbox
The Listbox component allows users to select one or more items from a list. It can be used to build menus, select inputs, and other list-based UIs.
Installation
$ cbui-cli install listboxcbui-cli globally and authenticated your account. This will ensure you can access all the necessary features.Import
1import { Listbox, ListboxItem, ListboxSection, ListboxContext, useListboxContext } from '@/crossbuildui/listbox';
2// import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; // If using icons
3// import { View, Text } from 'react-native'; // For contentListboxItem uses react-native-vector-icons/MaterialIcons. The glass variant for Listbox uses expo-blur. Ensure these libraries are installed and linked if you rely on these features.Basic Usage
Create a listbox by nesting ListboxItem components within a Listbox container. Each item needs a unique itemKey.
1<Listbox aria-label="Basic Listbox Example">
2 <ListboxItem itemKey="item1">Item One</ListboxItem>
3 <ListboxItem itemKey="item2">Item Two</ListboxItem>
4 <ListboxItem itemKey="item3">Item Three</ListboxItem>
5</Listbox>With Sections
Organize items into groups using the ListboxSection component. Sections can have titles and optional dividers.
1<Listbox aria-label="Listbox with Sections">
2 <ListboxSection title="Actions" itemKey="actions-section">
3 <ListboxItem itemKey="new">New file</ListboxItem>
4 <ListboxItem itemKey="copy">Copy link</ListboxItem>
5 <ListboxItem itemKey="edit">Edit file</ListboxItem>
6 </ListboxSection>
7 <ListboxSection title="Danger Zone" itemKey="danger-section" showDivider>
8 <ListboxItem itemKey="delete" style={{color: 'red'}}>Delete file</ListboxItem>
9 </ListboxSection>
10</Listbox>Selection Modes
Control selection behavior with selectionMode: 'single', 'multiple', or 'none'. Use defaultSelectedKeys for uncontrolled initial selection or selectedKeys for controlled selection.
1// Single Selection (default behavior if selectionMode is not 'none')
2<Listbox selectionMode="single" defaultSelectedKeys={["cat"]}>
3 <ListboxItem itemKey="dog">Dog</ListboxItem>
4 <ListboxItem itemKey="cat">Cat</ListboxItem>
5 <ListboxItem itemKey="mouse">Mouse</ListboxItem>
6</Listbox>
7
8// Multiple Selection
9<Listbox selectionMode="multiple" defaultSelectedKeys={["apple", "orange"]}>
10 <ListboxItem itemKey="apple">Apple</ListboxItem>
11 <ListboxItem itemKey="banana">Banana</ListboxItem>
12 <ListboxItem itemKey="orange">Orange</ListboxItem>
13</Listbox>
14
15// No Selection
16<Listbox selectionMode="none">
17 <ListboxItem itemKey="view">View Details</ListboxItem>
18 <ListboxItem itemKey="info">Information</ListboxItem>
19</Listbox>Disabled Items & Listbox
Disable specific items using the disabledKeys prop on Listbox or the isDisabled prop on ListboxItem. The entire Listbox can be disabled using its disabled prop.
1<Listbox disabledKeys={["edit"]}>
2 <ListboxItem itemKey="new">New File</ListboxItem>
3 <ListboxItem itemKey="copy">Copy Link</ListboxItem>
4 <ListboxItem itemKey="edit">Edit File (Disabled)</ListboxItem>
5 <ListboxItem itemKey="delete" isDisabled>Delete File (Explicitly Disabled)</ListboxItem>
6</Listbox>
7
8// Entire Listbox disabled
9<Listbox disabled defaultSelectedKeys={["one"]}>
10 <ListboxItem itemKey="one">One</ListboxItem>
11 <ListboxItem itemKey="two">Two</ListboxItem>
12</Listbox>Item Content & Structure
ListboxItem supports title, description, startContent, endContent, and custom selectedIcon. Providing children to ListboxItem will override the title.
1<Listbox>
2 <ListboxItem
3 itemKey="profile"
4 title="User Profile"
5 description="Manage your account settings"
6 startContent={<Icon name="account-circle-outline" size={24} />}
7 endContent={<Icon name="chevron-right" size={20} />}
8 >
9 {/* Children override title, so title prop is ignored here */}
10 <View><Text style={{fontWeight: 'bold'}}>Custom Profile View</Text></View>
11 </ListboxItem>
12 <ListboxItem
13 itemKey="notifications"
14 title="Notifications"
15 description="Configure alerts"
16 startContent={<Icon name="bell-outline" size={24} />}
17 selectedIcon={<Icon name="star" size={20} color="gold" />}
18 />
19</Listbox>Variants & Colors
Listbox supports solid, bordered, light, flat, faded, shadow, and glass variants. Apply thematic colors using the color prop.
1<View style={{flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-around', gap: 10}}>
2 <Listbox variant="solid" color="primary" defaultSelectedKeys={["s1"]} style={{margin:5, width: 150}}>
3 <ListboxItem itemKey="s1">Solid Primary</ListboxItem>
4 </Listbox>
5 <Listbox variant="bordered" color="secondary" defaultSelectedKeys={["b1"]} style={{margin:5, width: 150}}>
6 <ListboxItem itemKey="b1">Bordered Secondary</ListboxItem>
7 </Listbox>
8 <Listbox variant="light" color="success" defaultSelectedKeys={["l1"]} style={{margin:5, width: 150}}>
9 <ListboxItem itemKey="l1">Light Success</ListboxItem>
10 </Listbox>
11 <Listbox variant="flat" color="warning" defaultSelectedKeys={["f1"]} style={{margin:5, width: 150}}>
12 <ListboxItem itemKey="f1">Flat Warning</ListboxItem>
13 </Listbox>
14 <Listbox variant="faded" color="danger" defaultSelectedKeys={["fd1"]} style={{margin:5, width: 150}}>
15 <ListboxItem itemKey="fd1">Faded Danger</ListboxItem>
16 </Listbox>
17 <Listbox variant="shadow" color="default" defaultSelectedKeys={["sh1"]} style={{margin:5, width: 150}}>
18 <ListboxItem itemKey="sh1">Shadow Default</ListboxItem>
19 </Listbox>
20 <Listbox variant="glass" color="primary" defaultSelectedKeys={["g1"]} style={{margin:5, width: 150}} glassIntensity={70} glassTint="light">
21 <ListboxItem itemKey="g1">Glass Primary</ListboxItem>
22 </Listbox>
23</View>Glass Variant
The glass variant applies a frosted glass effect to the Listbox container background using expo-blur. Customize it with glassIntensity (0-100) and glassTint ('light', 'dark', 'default'). Item text colors adapt for better contrast on the blurred background, but you might need to adjust them manually for certain tints using slotStyles on ListboxItem or itemStyle on Listbox/ListboxSection.
1<View style={{gap: 16}}>
2 <Listbox variant="glass" glassIntensity={80} glassTint="light" style={{paddingVertical: 8}} aria-label="Light Glass Listbox">
3 <ListboxItem itemKey="profile" title="Profile" description="View your profile" />
4 <ListboxItem itemKey="settings" title="Settings" description="Configure application settings" />
5 </Listbox>
6
7 <Listbox variant="glass" glassIntensity={50} glassTint="dark" style={{paddingVertical: 8, marginTop: 10}} aria-label="Dark Glass Listbox">
8 {/* Item text colors might need manual adjustment for dark glass if default doesn't contrast well */}
9 <ListboxItem itemKey="dashboard" title="Dashboard" slotStyles={{title: {color: 'white'}, description: {color: 'lightgray'}}} description="Analytics overview" />
10 <ListboxItem itemKey="logout" title="Logout" color="danger" slotStyles={{title: {color: 'pink'}}} />
11 </Listbox>
12</View>
13/*
14 Note: For the 'glass' variant, the Listbox container itself gets the blur effect.
15 ListboxItems within it typically have transparent backgrounds to show the blur.
16*/Dynamic Items
Render items dynamically by providing an items array and a renderItem function, or by passing a function as children.
1const users = [
2 { id: '1', name: 'Alice', avatar: 'https://i.pravatar.cc/150?u=alice' },
3 { id: '2', name: 'Bob', avatar: 'https://i.pravatar.cc/150?u=bob' },
4 { id: '3', name: 'Charlie', avatar: 'https://i.pravatar.cc/150?u=charlie' },
5];
6
7<Listbox
8 items={users}
9 renderItem={(user) => (
10 <ListboxItem
11 itemKey={user.id}
12 title={user.name}
13 startContent={<Image source={{ uri: user.avatar }} style={{ width: 30, height: 30, borderRadius: 15 }} />}
14 />
15 )}
16 aria-label="User List"
17/>
18
19// Alternative with children as a function
20<Listbox items={users} aria-label="User List Alt">
21 {(user) => (
22 <ListboxItem
23 itemKey={user.id}
24 title={user.name}
25 description={`User ID: ${user.id}`}
26 />
27 )}
28</Listbox>Top & Bottom Content
Add custom content at the beginning or end of the list using topContent and bottomContent props.
1<Listbox topContent={<Text style={{padding:10, fontWeight:'bold'}}>Available Options</Text>}
2 bottomContent={<Text style={{padding:10, fontSize:10, textAlign:'center'}}>End of list</Text>}>
3 <ListboxItem itemKey="opt1">Option 1</ListboxItem>
4 <ListboxItem itemKey="opt2">Option 2</ListboxItem>
5</Listbox>Empty State
Display custom content when the list is empty using the emptyContent prop.
1<Listbox items={[]} emptyContent={<View style={{padding:20, alignItems:'center'}}><Text>No data found.</Text></View>}>
2 {(item) => <ListboxItem itemKey={item.id}>{item.name}</ListboxItem>}
3</Listbox>Using Listbox Context
For advanced customization or to build components that react to the Listbox state, you can use the useListboxContext hook. This hook provides access to properties like selectionMode, selectedKeys, variant, color, disabledKeys, and more.
Any component that calls useListboxContext must be a descendant of a Listbox component. This is useful for custom topContent, bottomContent, or deeply integrated custom items.
1import { Listbox, ListboxItem, useListboxContext } from '@/crossbuildui/listbox';
2import { Text, View } from 'react-native';
3
4const ListboxInfoDisplay = () => {
5 const context = useListboxContext();
6
7 if (!context) {
8 return <Text>This component must be used within a Listbox.</Text>;
9 }
10
11 const { selectionMode, selectedKeys, variant, color, disabledKeys } = context;
12
13 return (
14 <View style={{ padding: 8, backgroundColor: '#f0f0f0', borderTopWidth: 1, borderColor: '#ccc' }}>
15 <Text>Listbox Context Info:</Text>
16 <Text>- Selection Mode: {selectionMode}</Text>
17 <Text>- Variant: {variant}, Color: {color}</Text>
18 <Text>- Selected: {Array.from(selectedKeys).join(', ') || 'None'}</Text>
19 <Text>- Disabled Keys: {Array.from(disabledKeys).join(', ') || 'None'}</Text>
20 </View>
21 );
22};
23
24// <Listbox selectionMode="multiple" variant="flat" color="primary" topContent={<ListboxInfoDisplay />}><ListboxItem itemKey="1">Item 1</ListboxItem></Listbox>Props Overview
Listbox Props
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
children | ReactNode | (item) => ReactElement | - | Static items or render function for dynamic items. |
items | T[] | - | Array of data for dynamic rendering. |
renderItem | (item: T) => ReactElement | - | Function to render each item from the items array. |
variant | ListboxVariant | 'solid' | Visual style. |
color | ListboxColor | 'default' | Thematic color. |
selectionMode | ListboxSelectionMode | 'none' | Selection behavior. |
selectedKeys | Iterable<string|number> | - | Controlled selected item keys. |
defaultSelectedKeys | Iterable<string|number> | [] | Initially selected keys (uncontrolled). |
disabledKeys | Iterable<string|number> | [] | Keys of disabled items. |
disallowEmptySelection | boolean | false | Prevent deselection if it results in no selection. |
topContent | ReactNode | - | Content displayed above the list items. |
bottomContent | ReactNode | - | Content displayed below the list items. |
emptyContent | ReactNode | "No items." | Content displayed when list is empty. |
hideSelectedIcon | boolean | false | Hide selected state icon globally. |
style | StyleProp<ViewStyle> | - | Style for the Listbox container. |
itemStyle | Partial<ListboxItemSlots> | - | Global styles for all ListboxItem slots. |
onSelectionChange | (keys: Set<string|number>) => void | - | Callback when selection changes. |
disabled | boolean | false | Disable the entire Listbox. |
glassTint | 'default' | 'light' | 'dark' | Theme-derived | Tint for the 'glass' variant blur effect. |
glassIntensity | number | 50 | Intensity (0-100) for the 'glass' variant blur effect. |
ListboxItem Props
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
children | ReactNode | - | Custom content, overrides title. |
itemKey | string | number | - | Unique key for the item. **Required.** |
title | ReactNode | - | Primary text content of the item. |
textValue | string | - | Plain text representation for accessibility/typeahead. |
description | ReactNode | - | Secondary text content below the title. |
startContent | ReactNode | - | Content displayed before the main text. |
endContent | ReactNode | - | Content displayed after the selected icon (if visible). |
selectedIcon | ReactNode | (props) => ReactNode | Default Icon | Custom icon for selected state. |
showDivider | boolean | false | Show a divider below this item. |
hideSelectedIcon | boolean | Contextual | Override Listbox/Section setting for this item. |
style | StyleProp<ViewStyle> | - | Style for the item's outer Pressable. |
slotStyles | Partial<ListboxItemSlots> | - | Styles for inner parts of the item (title, description, etc.). |
isDisabled | boolean | false | Explicitly disable this item. |
ListboxSection Props
| PROP | TYPE | DEFAULT | DESCRIPTION |
|---|---|---|---|
children | ReactNode | - | ListboxItem components within this section. |
itemKey | string | number | - | Unique key for the section. Required. |
title | string | - | Title displayed above the section items. |
hideSelectedIcon | boolean | Contextual | Override Listbox's hideSelectedIcon for items in this section. |
showDivider | boolean | false | Show a divider after the section. |
dividerProps | StyleProp<ViewStyle> | - | Custom style for the section divider. |
style | StyleProp<ViewStyle> | - | Style for the section container. |
itemStyle | Partial<ListboxItemSlots> | - | Styles for ListboxItem slots within this section, overrides Listbox's itemStyle. |
Styling
Customize appearance using:
- Listbox:
style: For the main Listbox container (View).itemStyle: Global styles for allListboxItemslots (e.g.,base,title,description).- For the
glassvariant,glassTintandglassIntensitycontrol the blur. The Listbox container background becomes transparent, and aBlurViewis rendered underneath.
- ListboxSection:
style: For the section wrapperView.itemStyle: Styles forListboxItemslots within this section, overriding Listbox'sitemStyle.dividerProps: Style for the section's bottom divider.
- ListboxItem:
style: For the item's rootPressablecomponent.slotStyles: Specific styles for inner parts of this item (e.g.,wrapper,title,startContentWrapper), overriding section and ListboxitemStyle.
Style precedence for item slots: ListboxItem.slotStyles > ListboxSection.itemStyle > Listbox.itemStyle.
1<Listbox
2 style={{ marginVertical: 10, borderColor: 'purple', borderWidth: 1, borderRadius: 12 }} // Styles the Listbox container
3 itemStyle={{ // Global styles for all ListboxItem slots
4 base: { paddingVertical: 15 },
5 title: { fontWeight: '600', color: 'navy' },
6 description: { fontStyle: 'italic' }
7 }}
8 variant="flat"
9 color="primary"
10>
11 <ListboxSection
12 title="Custom Section"
13 itemKey="custom-sec"
14 style={{ backgroundColor: 'rgba(200,200,255,0.3)' }}
15 itemStyle={{ // Overrides Listbox's itemStyle for this section
16 title: { color: 'darkgreen' }
17 }}
18 >
19 <ListboxItem
20 itemKey="styled1"
21 title="Item with Specific Slot Styles"
22 slotStyles={{ // Styles for slots of this specific item
23 base: { borderLeftWidth: 3, borderLeftColor: 'orange' },
24 wrapper: { paddingLeft: 10 },
25 title: { textDecorationLine: 'underline', color: 'red' } // Overrides section and listbox itemStyle
26 }}
27 style={{ backgroundColor: 'lightyellow' }} // Style for the Pressable of this item
28 />
29 <ListboxItem itemKey="styled2" title="Section Styled Item" description="Inherits from section" />
30 </ListboxSection>
31 <ListboxItem itemKey="styled3" title="Listbox Styled Item" description="Inherits from listbox" />
32</Listbox>Accessibility
The Listbox components are designed with accessibility in mind:
Listboxcontainer hasaccessibilityRole="list".- Each
ListboxItemhasaccessibilityRole="menuitem"(can be adjusted if used as a general selectable list). ListboxItemincludesaccessibilityStateforselectedanddisabledstates.ListboxItemusestextValueortitlefor itsaccessibilityLabel.