Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { SearchBar } from '@/components/ui/searchbar';
import React, { useState } from 'react';
export function SearchBarDemo() {
const [searchQuery, setSearchQuery] = useState('');
const handleSearch = (query: string) => {
console.log('Searching for:', query);
};
return (
<SearchBar
placeholder='Search for anything...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleSearch}
/>
);
}
Installation
pnpm dlx bna-ui add searchbar
Usage
import { SearchBar, SearchBarWithSuggestions } from '@/components/ui/searchbar';
<SearchBar
placeholder='Search for anything...'
onSearch={(query) => console.log('Searching for:', query)}
loading={false}
/>
Examples
Default
import { SearchBar } from '@/components/ui/searchbar';
import React, { useState } from 'react';
export function SearchBarDemo() {
const [searchQuery, setSearchQuery] = useState('');
const handleSearch = (query: string) => {
console.log('Searching for:', query);
};
return (
<SearchBar
placeholder='Search for anything...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleSearch}
/>
);
}
With Loading State
import { SearchBar } from '@/components/ui/searchbar';
import React, { useState } from 'react';
export function SearchBarLoading() {
const [searchQuery, setSearchQuery] = useState('');
const [loading, setLoading] = useState(false);
const handleSearch = (query: string) => {
if (query.trim()) {
setLoading(true);
// Simulate API call
setTimeout(() => {
setLoading(false);
console.log('Search completed for:', query);
}, 2000);
}
};
return (
<SearchBar
placeholder='Search with loading state...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleSearch}
loading={loading}
/>
);
}
Custom Icons
import { Icon } from '@/components/ui/icon';
import { SearchBar } from '@/components/ui/searchbar';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import { Filter, MapPin, User } from 'lucide-react-native';
import React, { useState } from 'react';
export function SearchBarIcons() {
const [locationQuery, setLocationQuery] = useState('');
const [userQuery, setUserQuery] = useState('');
const icon = useThemeColor({}, 'icon');
return (
<View style={{ gap: 16 }}>
{/* Location search with map pin icon */}
<SearchBar
placeholder='Search locations...'
value={locationQuery}
onChangeText={setLocationQuery}
leftIcon={<Icon name={MapPin} size={16} color={icon} />}
onSearch={(query) => console.log('Location search:', query)}
/>
{/* User search with custom icons */}
<SearchBar
placeholder='Search users...'
value={userQuery}
onChangeText={setUserQuery}
leftIcon={<Icon name={User} size={16} color={icon} />}
rightIcon={<Icon name={Filter} size={16} color={icon} />}
showClearButton={false}
onSearch={(query) => console.log('User search:', query)}
/>
</View>
);
}
With Suggestions
import { SearchBarWithSuggestions } from '@/components/ui/searchbar';
import React, { useState } from 'react';
export function SearchBarSuggestions() {
const [searchQuery, setSearchQuery] = useState('');
const suggestions = [
'React Native',
'React Navigation',
'React Hook Form',
'Redux Toolkit',
'Expo Router',
'TypeScript',
'JavaScript',
'Node.js',
'Next.js',
'Tailwind CSS',
];
const handleSearch = (query: string) => {
console.log('Searching for:', query);
};
const handleSuggestionPress = (suggestion: string) => {
setSearchQuery(suggestion);
handleSearch(suggestion);
};
return (
<SearchBarWithSuggestions
placeholder='Type to see suggestions...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleSearch}
suggestions={suggestions}
onSuggestionPress={handleSuggestionPress}
maxSuggestions={8}
/>
);
}
Custom Styling
import { SearchBar } from '@/components/ui/searchbar';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function SearchBarStyled() {
const [query1, setQuery1] = useState('');
const [query2, setQuery2] = useState('');
const [query3, setQuery3] = useState('');
return (
<View style={{ gap: 16 }}>
{/* Rounded with gradient-like background */}
<SearchBar
placeholder='Rounded search...'
value={query1}
onChangeText={setQuery1}
containerStyle={{
borderRadius: 25,
borderWidth: 1.5,
borderColor: 'green',
}}
inputStyle={{
color: 'green',
fontWeight: '500',
}}
/>
{/* Minimal flat design */}
<SearchBar
placeholder='Minimal search...'
value={query2}
onChangeText={setQuery2}
containerStyle={{
backgroundColor: 'transparent',
borderBottomWidth: 1,
borderBottomColor: '#374151',
borderRadius: 0,
paddingHorizontal: 0,
}}
inputStyle={{
fontSize: 16,
fontWeight: '400',
}}
/>
{/* Dark theme with custom height */}
<SearchBar
placeholder='Custom dark search...'
value={query3}
onChangeText={setQuery3}
containerStyle={{
backgroundColor: '#1f2937',
borderRadius: 12,
height: 56,
borderWidth: 1,
borderColor: '#374151',
}}
inputStyle={{
color: '#f9fafb',
fontSize: 16,
}}
/>
</View>
);
}
Without Clear Button
import { SearchBar } from '@/components/ui/searchbar';
import React, { useState } from 'react';
export function SearchBarNoClear() {
const [searchQuery, setSearchQuery] = useState('');
const handleSearch = (query: string) => {
console.log('Searching without clear button:', query);
};
return (
<SearchBar
placeholder='Search without clear button...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleSearch}
showClearButton={false}
/>
);
}
Instant Search
import { SearchBar } from '@/components/ui/searchbar';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React, { useState } from 'react';
export function SearchBarInstant() {
const [searchQuery, setSearchQuery] = useState('');
const [searchResults, setSearchResults] = useState<string[]>([]);
const mockData = [
'Apple',
'Banana',
'Cherry',
'Date',
'Elderberry',
'Fig',
'Grape',
'Honeydew',
'Kiwi',
'Lemon',
];
const handleInstantSearch = (query: string) => {
if (query.trim()) {
const results = mockData.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);
setSearchResults(results);
} else {
setSearchResults([]);
}
};
return (
<View style={{ gap: 16 }}>
<SearchBar
placeholder='Instant search (no debounce)...'
value={searchQuery}
onChangeText={setSearchQuery}
onSearch={handleInstantSearch}
debounceMs={0} // No debounce for instant search
/>
{searchResults.length > 0 && (
<View style={{ gap: 8 }}>
<Text variant='caption' style={{ opacity: 0.7 }}>
Found {searchResults.length} results:
</Text>
{searchResults.map((result, index) => (
<Text key={index} style={{ paddingLeft: 16 }}>
• {result}
</Text>
))}
</View>
)}
</View>
);
}
API Reference
SearchBar
The main search input component with debouncing and customization options.
Prop | Type | Default | Description |
---|---|---|---|
loading | boolean | false | Shows loading indicator when true. |
onSearch | (query: string) => void | - | Callback fired when search is triggered (debounced). |
onClear | () => void | - | Callback fired when clear button is pressed. |
showClearButton | boolean | true | Whether to show the clear button when text is present. |
leftIcon | ReactNode | Search icon | Custom left icon component. |
rightIcon | ReactNode | - | Custom right icon component. |
containerStyle | ViewStyle | ViewStyle[] | - | Additional styles for the container. |
inputStyle | TextStyle | TextStyle[] | - | Additional styles for the text input. |
debounceMs | number | 300 | Debounce delay in milliseconds for search callbacks. |
placeholder | string | 'Search...' | Placeholder text for the input. |
value | string | - | Controlled value of the input. |
onChangeText | (text: string) => void | - | Callback fired when text changes. |
All other TextInputProps
are also supported.
SearchBarWithSuggestions
An enhanced search bar with dropdown suggestions functionality.
Prop | Type | Default | Description |
---|---|---|---|
suggestions | string[] | [] | Array of suggestion strings to display. |
onSuggestionPress | (suggestion: string) => void | - | Callback fired when a suggestion is selected. |
maxSuggestions | number | 5 | Maximum number of suggestions to display. |
showSuggestions | boolean | true | Whether to show the suggestions dropdown. |
All SearchBar
props are also supported.
Features
- Debounced Search: Configurable debounce delay to prevent excessive API calls
- Loading States: Built-in loading indicator support
- Clear Functionality: Optional clear button with customizable behavior
- Custom Icons: Support for custom left and right icons
- Suggestions Dropdown: Enhanced variant with autocomplete suggestions
- Flexible Styling: Comprehensive styling options for container and input
- Controlled/Uncontrolled: Supports both controlled and uncontrolled usage patterns
- Accessibility: Built with accessibility best practices
Accessibility
The SearchBar component follows accessibility guidelines:
- Proper focus management and keyboard navigation
- Screen reader compatible with appropriate labels
- Clear button is properly labeled for assistive technologies
- Suggestions dropdown supports keyboard navigation
- High contrast support for better visibility