@atom_design/dropdown
v1.0.0
Published
A React Native dropdown select component with anchored positioning and modal-based menu. Part of the Atom Design System.
Readme
@atom_design/dropdown
A React Native dropdown select component with smart anchored positioning and modal-based menu. Part of the Atom Design System.
Features
- 📍 Smart Positioning - Auto-positions above/below based on screen space
- 🎯 Anchored Menu - Dropdown matches trigger width and position
- ✅ Selection State - Visual feedback for selected option
- 🎨 Customizable - Style all elements with custom props
- ♿ Accessible - Full screen reader support
- 💪 TypeScript - Full type definitions included
- 📱 Cross-Platform - Works on iOS and Android
📦 Installation
npm install @atom_design/dropdown
# or
yarn add @atom_design/dropdownPeer Dependencies
npm install prop-types react-native-vector-icons🚀 Basic Usage
import React, { useState } from 'react';
import { View } from 'react-native';
import Dropdown from '@atom_design/dropdown';
const App = () => {
const [selected, setSelected] = useState(null);
const options = [
{ label: 'Apple', value: 'apple' },
{ label: 'Orange', value: 'orange' },
{ label: 'Banana', value: 'banana' },
];
return (
<View style={{ flex: 1, padding: 20 }}>
<Dropdown
label="Select Fruit"
options={options}
value={selected}
onSelect={setSelected}
placeholder="Choose a fruit"
/>
</View>
);
};
export default App;🧩 Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| label | string | - | Label above dropdown |
| triggerText | string | - | Override trigger text |
| options | Option[] | [] | Array of options |
| value | string \| number | - | Selected value |
| onSelect | (value) => void | - | Selection callback |
| placeholder | string | 'Select...' | Placeholder text |
| disabled | boolean | false | Disable dropdown |
| error | string | - | Error message |
| leftIcon | string | - | Left icon (MaterialIcons) |
| containerStyle | ViewStyle | - | Container style |
| triggerStyle | ViewStyle | - | Trigger button style |
| dropdownStyle | ViewStyle | - | Dropdown menu style |
| labelStyle | TextStyle | - | Label style |
| optionStyle | ViewStyle | - | Option item style |
| maxHeight | number | 300 | Max dropdown height |
| testID | string | - | Test ID |
📁 Option Structure
interface Option {
label: string; // Display text
value: string | number; // Value returned on select
}🧪 Test Screen Example
import React, { useState } from 'react';
import { SafeAreaView, ScrollView, Text, StyleSheet, View } from 'react-native';
import Dropdown from '@atom_design/dropdown';
const countries = [
{ label: 'United States', value: 'us' },
{ label: 'Canada', value: 'ca' },
{ label: 'United Kingdom', value: 'uk' },
{ label: 'Germany', value: 'de' },
{ label: 'France', value: 'fr' },
{ label: 'Australia', value: 'au' },
{ label: 'Japan', value: 'jp' },
{ label: 'India', value: 'in' },
];
const DropdownTestScreen = () => {
const [country, setCountry] = useState(null);
const [city, setCity] = useState(null);
return (
<SafeAreaView style={styles.container}>
<ScrollView contentContainerStyle={styles.content}>
<Text style={styles.header}>@atom_design/dropdown</Text>
{/* Basic Dropdown */}
<Dropdown
label="Country"
options={countries}
value={country}
onSelect={setCountry}
placeholder="Select country"
/>
{/* With Icon */}
<Dropdown
label="City"
options={[
{ label: 'New York', value: 'ny' },
{ label: 'Los Angeles', value: 'la' },
{ label: 'Chicago', value: 'chi' },
]}
value={city}
onSelect={setCity}
placeholder="Select city"
leftIcon="location-city"
/>
{/* With Error */}
<Dropdown
label="Required Field"
options={countries}
placeholder="This field is required"
error="Please select a country"
/>
{/* Disabled */}
<Dropdown
label="Disabled Dropdown"
options={countries}
placeholder="Cannot select"
disabled
/>
{/* Custom Styled */}
<Dropdown
label="Custom Style"
options={countries}
value={country}
onSelect={setCountry}
triggerStyle={styles.customTrigger}
dropdownStyle={styles.customDropdown}
/>
{/* Selection Display */}
{country && (
<View style={styles.selection}>
<Text style={styles.selectionText}>
Selected: {countries.find(c => c.value === country)?.label}
</Text>
</View>
)}
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
content: {
padding: 20,
},
header: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 24,
color: '#333',
},
customTrigger: {
borderColor: '#d9232d',
borderWidth: 2,
borderRadius: 12,
},
customDropdown: {
borderRadius: 12,
},
selection: {
marginTop: 20,
padding: 12,
backgroundColor: '#e3f2fd',
borderRadius: 8,
},
selectionText: {
fontSize: 14,
color: '#1976d2',
},
});
export default DropdownTestScreen;📝 TypeScript
Full TypeScript support included:
import Dropdown, { Option, DropdownProps } from '@atom_design/dropdown';
const options: Option[] = [
{ label: 'Option 1', value: 'opt1' },
{ label: 'Option 2', value: 'opt2' },
];
const MyDropdown: React.FC = () => {
const [value, setValue] = useState<string | null>(null);
return (
<Dropdown
label="Select"
options={options}
value={value}
onSelect={(val) => setValue(val as string)}
/>
);
};♿ Accessibility
The component includes full accessibility support:
- Proper
accessibilityRoleon all interactive elements accessibilityStatefor disabled and expanded statesaccessibilityHintfor usage guidance- Screen reader support for selected state
👤 Author
Atom Design Team
📄 License
MIT © Atom Design
