Accordion

A collapsible content component with smooth animations, supporting both single and multiple item expansion.

Installation

Install the component:

npx natively-ui add accordion

Usage

AccordionDemo.jsx
1import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion'; 2 3export default function MyComponent() { 4 return ( 5 <Accordion type="single" defaultValue="item-1"> 6 <AccordionItem value="item-1"> 7 <AccordionTrigger>Is it accessible?</AccordionTrigger> 8 <AccordionContent> 9 Yes. It adheres to the WAI-ARIA design pattern. 10 </AccordionContent> 11 </AccordionItem> 12 </Accordion> 13 ); 14}

API Reference

Accordion

PropTypeDefaultDescription
type'single' | 'multiple''single'Whether a single or multiple items can be opened at the same time.
defaultValuestring | string[]-The initial value(s) of the accordion when it is first rendered.
valuestring | string[]-The controlled value of the accordion. Use when you need to control the state externally.
onValueChange(value: string | string[]) => void-Event handler called when the value changes.
classNamestring""Additional CSS classes for the accordion container.

AccordionItem

PropTypeDefaultDescription
valuestring-A unique value for the item. Required.
disabledbooleanfalseWhen true, prevents the user from interacting with the item.
classNamestring""Additional CSS classes for the item container.

AccordionTrigger

PropTypeDefaultDescription
classNamestring""Additional CSS classes for the trigger button.
childrenReact.ReactNode-The content to display in the trigger. Can be text or custom components.

AccordionContent

PropTypeDefaultDescription
classNamestring""Additional CSS classes for the content container.
childrenReact.ReactNode-The collapsible content to display when the item is open.

Features

  • Single or multiple item expansion modes
  • Smooth height animations with automatic content measurement
  • Keyboard accessible with proper ARIA attributes
  • Controlled and uncontrolled modes
  • Disabled state support
  • Customizable styling with className props
  • Context-based component communication
  • Built with React Native Animated API

Examples

Basic Usage

AccordionDemo.jsx
1<Accordion type="single" defaultValue="item-1"> 2 <AccordionItem value="item-1"> 3 <AccordionTrigger>Is it accessible?</AccordionTrigger> 4 <AccordionContent> 5 <Text>Yes. It adheres to the WAI-ARIA design pattern.</Text> 6 </AccordionContent> 7 </AccordionItem> 8 9 <AccordionItem value="item-2"> 10 <AccordionTrigger>Is it styled?</AccordionTrigger> 11 <AccordionContent> 12 <Text>Yes. It comes with default styles that matches the other components' aesthetic.</Text> 13 </AccordionContent> 14 </AccordionItem> 15 16 <AccordionItem value="item-3"> 17 <AccordionTrigger>Is it animated?</AccordionTrigger> 18 <AccordionContent> 19 <Text>Yes. It's animated by default, but you can disable it if you prefer.</Text> 20 </AccordionContent> 21 </AccordionItem> 22</Accordion>

Multiple Items

AccordionDemo.jsx
1<Accordion type="multiple" defaultValue={["item-1", "item-2"]}> 2 <AccordionItem value="item-1"> 3 <AccordionTrigger>What is React Native?</AccordionTrigger> 4 <AccordionContent> 5 <Text> 6 React Native is a framework for building native apps using React. 7 It allows you to write mobile applications using JavaScript and React. 8 </Text> 9 </AccordionContent> 10 </AccordionItem> 11 12 <AccordionItem value="item-2"> 13 <AccordionTrigger>What is Expo?</AccordionTrigger> 14 <AccordionContent> 15 <Text> 16 Expo is a platform for making React Native applications with tools 17 and services that help you develop, build, deploy, and iterate on iOS 18 and Android apps. 19 </Text> 20 </AccordionContent> 21 </AccordionItem> 22 23 <AccordionItem value="item-3"> 24 <AccordionTrigger>What is TypeScript?</AccordionTrigger> 25 <AccordionContent> 26 <Text> 27 TypeScript is a programming language developed by Microsoft that builds 28 on JavaScript by adding static type definitions. 29 </Text> 30 </AccordionContent> 31 </AccordionItem> 32</Accordion>

Controlled State

AccordionDemo.jsx
1const [value, setValue] = useState("item-1"); 2 3<View style={{ gap: 16 }}> 4 <View style={{ flexDirection: 'row', gap: 8 }}> 5 <Button onPress={() => setValue("item-1")} size="sm"> 6 Open First 7 </Button> 8 <Button onPress={() => setValue("item-2")} size="sm"> 9 Open Second 10 </Button> 11 <Button onPress={() => setValue("")} size="sm"> 12 Close All 13 </Button> 14 </View> 15 16 <Accordion type="single" value={value} onValueChange={setValue}> 17 <AccordionItem value="item-1"> 18 <AccordionTrigger>First Item</AccordionTrigger> 19 <AccordionContent> 20 <Text>This is the first item's content.</Text> 21 </AccordionContent> 22 </AccordionItem> 23 24 <AccordionItem value="item-2"> 25 <AccordionTrigger>Second Item</AccordionTrigger> 26 <AccordionContent> 27 <Text>This is the second item's content.</Text> 28 </AccordionContent> 29 </AccordionItem> 30 </Accordion> 31</View>

Custom Styling

AccordionDemo.jsx
1<Accordion type="single" className="bg-white rounded-lg shadow-md"> 2 <AccordionItem 3 value="item-1" 4 className="border-b border-slate-200 last:border-b-0" 5 > 6 <AccordionTrigger className="px-6 py-4 hover:bg-slate-50"> 7 <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}> 8 <Icon name="settings" size={20} color="#3B82F6" /> 9 <Text style={{ fontSize: 16, fontWeight: '600', color: '#1E293B' }}> 10 Settings 11 </Text> 12 </View> 13 </AccordionTrigger> 14 <AccordionContent className="px-6 py-4 bg-slate-50"> 15 <Text style={{ color: '#64748B', lineHeight: 20 }}> 16 Configure your application settings and preferences here. 17 </Text> 18 </AccordionContent> 19 </AccordionItem> 20 21 <AccordionItem 22 value="item-2" 23 className="border-b border-slate-200 last:border-b-0" 24 > 25 <AccordionTrigger className="px-6 py-4 hover:bg-slate-50"> 26 <View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}> 27 <Icon name="user" size={20} color="#10B981" /> 28 <Text style={{ fontSize: 16, fontWeight: '600', color: '#1E293B' }}> 29 Profile 30 </Text> 31 </View> 32 </AccordionTrigger> 33 <AccordionContent className="px-6 py-4 bg-slate-50"> 34 <Text style={{ color: '#64748B', lineHeight: 20 }}> 35 Manage your profile information and account details. 36 </Text> 37 </AccordionContent> 38 </AccordionItem> 39</Accordion>

Disabled Items

AccordionDemo.jsx
1<Accordion type="single"> 2 <AccordionItem value="item-1"> 3 <AccordionTrigger>Available Feature</AccordionTrigger> 4 <AccordionContent> 5 <Text>This feature is available and can be accessed.</Text> 6 </AccordionContent> 7 </AccordionItem> 8 9 <AccordionItem value="item-2" disabled> 10 <AccordionTrigger>Coming Soon</AccordionTrigger> 11 <AccordionContent> 12 <Text>This feature is coming soon and is currently disabled.</Text> 13 </AccordionContent> 14 </AccordionItem> 15 16 <AccordionItem value="item-3"> 17 <AccordionTrigger>Another Available Feature</AccordionTrigger> 18 <AccordionContent> 19 <Text>This is another feature that you can use right now.</Text> 20 </AccordionContent> 21 </AccordionItem> 22</Accordion>

FAQ Section

AccordionDemo.jsx
1const faqs = [ 2 { 3 id: "faq-1", 4 question: "How do I reset my password?", 5 answer: "You can reset your password by clicking on the 'Forgot Password' link on the login page. We'll send you an email with instructions to create a new password." 6 }, 7 { 8 id: "faq-2", 9 question: "Is my data secure?", 10 answer: "Yes, we use industry-standard encryption and security measures to protect your data. All sensitive information is encrypted both in transit and at rest." 11 }, 12 { 13 id: "faq-3", 14 question: "Can I cancel my subscription anytime?", 15 answer: "Absolutely! You can cancel your subscription at any time from your account settings. Your access will continue until the end of your current billing period." 16 } 17]; 18 19<View> 20 <Text style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 16 }}> 21 Frequently Asked Questions 22 </Text> 23 24 <Accordion type="single"> 25 {faqs.map(faq => ( 26 <AccordionItem key={faq.id} value={faq.id}> 27 <AccordionTrigger> 28 <Text style={{ fontSize: 16, fontWeight: '500' }}> 29 {faq.question} 30 </Text> 31 </AccordionTrigger> 32 <AccordionContent> 33 <Text style={{ color: '#6B7280', lineHeight: 22 }}> 34 {faq.answer} 35 </Text> 36 </AccordionContent> 37 </AccordionItem> 38 ))} 39 </Accordion> 40</View>