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 listbox

Import

index.tsx
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 content

Basic Usage

Create a listbox by nesting ListboxItem components within a Listbox container. Each item needs a unique itemKey.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

index.tsx
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.

MyCustomListboxComponent.tsx
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

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode | (item) => ReactElement-Static items or render function for dynamic items.
itemsT[]-Array of data for dynamic rendering.
renderItem(item: T) => ReactElement-Function to render each item from the items array.
variantListboxVariant'solid'Visual style.
colorListboxColor'default'Thematic color.
selectionModeListboxSelectionMode'none'Selection behavior.
selectedKeysIterable<string|number>-Controlled selected item keys.
defaultSelectedKeysIterable<string|number>[]Initially selected keys (uncontrolled).
disabledKeysIterable<string|number>[]Keys of disabled items.
disallowEmptySelectionbooleanfalsePrevent deselection if it results in no selection.
topContentReactNode-Content displayed above the list items.
bottomContentReactNode-Content displayed below the list items.
emptyContentReactNode"No items."Content displayed when list is empty.
hideSelectedIconbooleanfalseHide selected state icon globally.
styleStyleProp<ViewStyle>-Style for the Listbox container.
itemStylePartial<ListboxItemSlots>-Global styles for all ListboxItem slots.
onSelectionChange(keys: Set<string|number>) => void-Callback when selection changes.
disabledbooleanfalseDisable the entire Listbox.
glassTint'default' | 'light' | 'dark'Theme-derivedTint for the 'glass' variant blur effect.
glassIntensitynumber50Intensity (0-100) for the 'glass' variant blur effect.

ListboxItem Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-Custom content, overrides title.
itemKeystring | number-Unique key for the item. **Required.**
titleReactNode-Primary text content of the item.
textValuestring-Plain text representation for accessibility/typeahead.
descriptionReactNode-Secondary text content below the title.
startContentReactNode-Content displayed before the main text.
endContentReactNode-Content displayed after the selected icon (if visible).
selectedIconReactNode | (props) => ReactNodeDefault IconCustom icon for selected state.
showDividerbooleanfalseShow a divider below this item.
hideSelectedIconbooleanContextualOverride Listbox/Section setting for this item.
styleStyleProp<ViewStyle>-Style for the item's outer Pressable.
slotStylesPartial<ListboxItemSlots>-Styles for inner parts of the item (title, description, etc.).
isDisabledbooleanfalseExplicitly disable this item.

ListboxSection Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-ListboxItem components within this section.
itemKeystring | number-Unique key for the section. Required.
titlestring-Title displayed above the section items.
hideSelectedIconbooleanContextualOverride Listbox's hideSelectedIcon for items in this section.
showDividerbooleanfalseShow a divider after the section.
dividerPropsStyleProp<ViewStyle>-Custom style for the section divider.
styleStyleProp<ViewStyle>-Style for the section container.
itemStylePartial<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 all ListboxItem slots (e.g., base, title, description).
    • For the glass variant, glassTint and glassIntensity control the blur. The Listbox container background becomes transparent, and a BlurView is rendered underneath.
  • ListboxSection:
    • style: For the section wrapper View.
    • itemStyle: Styles for ListboxItem slots within this section, overriding Listbox's itemStyle.
    • dividerProps: Style for the section's bottom divider.
  • ListboxItem:
    • style: For the item's root Pressable component.
    • slotStyles: Specific styles for inner parts of this item (e.g., wrapper, title, startContentWrapper), overriding section and Listbox itemStyle.

Style precedence for item slots: ListboxItem.slotStyles > ListboxSection.itemStyle > Listbox.itemStyle.

index.tsx
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:

  • Listbox container has accessibilityRole="list".
  • Each ListboxItem has accessibilityRole="menuitem" (can be adjusted if used as a general selectable list).
  • ListboxItem includes accessibilityState for selected and disabled states.
  • ListboxItem uses textValue or title for its accessibilityLabel.