react-pro-accordion
react-pro-accordion
A powerful, accessible, customizable, and production-ready accordion component library for React.
Features
- Multiple Modes — Single, multiple, controlled, and uncontrolled
- Fully Accessible — WCAG compliant with complete ARIA support and keyboard navigation
- Performant — Optimized with
React.memo,useMemo,useCallback, and minimal re-renders - Highly Customizable — CSS variables, 7 built-in themes, custom icons and styles
- Smooth Animations — Height and opacity transitions with spring physics
- Imperative API — Programmatic control via
refmethods - SSR Ready — Compatible with Next.js and other server-side rendering frameworks
- RTL Support — Full right-to-left language support
- Lazy Rendering — Content mounts only when the item is expanded
- TypeScript — Full type definitions included
- Tree-shakeable — Import only what you need (~8 KB gzipped)
Installation (Change Path Accordingly)
npm install react-pro-accordion
# or
yarn add react-pro-accordion
Quick Start
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from 'react-pro-accordion';
import 'react-pro-accordion/style.css';
function App() {
return (
<Accordion>
<AccordionItem id="item1">
<AccordionTrigger>What is React Pro Accordion?</AccordionTrigger>
<AccordionContent>
A powerful, accessible accordion library for React applications.
</AccordionContent>
</AccordionItem>
<AccordionItem id="item2">
<AccordionTrigger>Why choose React Pro Accordion?</AccordionTrigger>
<AccordionContent>
Superior performance, full accessibility, and extensive customization options.
</AccordionContent>
</AccordionItem>
</Accordion>
);
}
Documentation
Modes
Single (default)
Only one item can be open at a time.
<Accordion>
<AccordionItem id="item1">
<AccordionTrigger>Title 1</AccordionTrigger>
<AccordionContent>Content 1</AccordionContent>
</AccordionItem>
<AccordionItem id="item2">
<AccordionTrigger>Title 2</AccordionTrigger>
<AccordionContent>Content 2</AccordionContent>
</AccordionItem>
</Accordion>
Multiple
Allow multiple items to be open simultaneously.
<Accordion mode="multiple" allowMultiple={true}>
<AccordionItem id="item1">
<AccordionTrigger>Title 1</AccordionTrigger>
<AccordionContent>Content 1</AccordionContent>
</AccordionItem>
<AccordionItem id="item2">
<AccordionTrigger>Title 2</AccordionTrigger>
<AccordionContent>Content 2</AccordionContent>
</AccordionItem>
</Accordion>
Controlled
Manage expanded state externally.
function ControlledAccordion() {
const [expanded, setExpanded] = useState(['item1']);
const handleToggle = (id, isOpen) => {
setExpanded((prev) => (isOpen ? [...prev, id] : prev.filter((item) => item !== id)));
};
return (
<Accordion expanded={expanded} onToggle={handleToggle} mode="multiple" allowMultiple={true}>
<AccordionItem id="item1">
<AccordionTrigger>Controlled Item 1</AccordionTrigger>
<AccordionContent>Content 1</AccordionContent>
</AccordionItem>
<AccordionItem id="item2">
<AccordionTrigger>Controlled Item 2</AccordionTrigger>
<AccordionContent>Content 2</AccordionContent>
</AccordionItem>
</Accordion>
);
}
Imperative API
Use a ref to control the accordion programmatically.
import { useRef } from 'react';
function ImperativeExample() {
const accordionRef = useRef();
return (
<>
<button onClick={() => accordionRef.current.openAll()}>Open All</button>
<button onClick={() => accordionRef.current.closeAll()}>Close All</button>
<button onClick={() => accordionRef.current.toggle('item1')}>Toggle Item 1</button>
<Accordion ref={accordionRef}>
<AccordionItem id="item1">
<AccordionTrigger>Item 1</AccordionTrigger>
<AccordionContent>Content 1</AccordionContent>
</AccordionItem>
</Accordion>
</>
);
}
Available ref methods:
| Method | Description |
|---|---|
open(id) |
Open a specific item |
close(id) |
Close a specific item |
toggle(id) |
Toggle a specific item |
openAll() |
Open all items |
closeAll() |
Close all items |
getExpandedItems() |
Returns an array of currently expanded item IDs |
Custom Icons
<Accordion>
<AccordionItem id="item1">
<AccordionTrigger>
Custom Icons
<AccordionIcon expandedIcon={<span>📖</span>} collapsedIcon={<span>📚</span>} />
</AccordionTrigger>
<AccordionContent>Content with custom icons</AccordionContent>
</AccordionItem>
</Accordion>
Animations
<Accordion
animationDuration={200}
animationEasing="cubic-bezier(0.4, 0, 0.2, 1)"
disableAnimation={false}
onAnimationStart={(id) => console.log(`Started: ${id}`)}
onAnimationEnd={(id) => console.log(`Ended: ${id}`)}
>
{/* items */}
</Accordion>
Lazy Rendering
Content is only mounted when the item is first expanded. Useful for performance-sensitive lists.
<Accordion lazyRender={true}>
<AccordionItem id="item1">
<AccordionTrigger>Lazy Item</AccordionTrigger>
<AccordionContent>This content renders only when expanded.</AccordionContent>
</AccordionItem>
</Accordion>
RTL Support
<Accordion dir="rtl">
<AccordionItem id="item1">
<AccordionTrigger>مرحبا بكم</AccordionTrigger>
<AccordionContent>محتوى باللغة العربية</AccordionContent>
</AccordionItem>
</Accordion>
Dynamic Items
function DynamicAccordion() {
const [items, setItems] = useState([{ id: '1', title: 'Item 1', content: 'Content 1' }]);
const addItem = () => {
const next = items.length + 1;
setItems((prev) => [
...prev,
{ id: String(next), title: `Item ${next}`, content: `Content ${next}` },
]);
};
return (
<>
<button onClick={addItem}>Add Item</button>
<Accordion>
{items.map((item) => (
<AccordionItem key={item.id} id={item.id}>
<AccordionTrigger>{item.title}</AccordionTrigger>
<AccordionContent>{item.content}</AccordionContent>
</AccordionItem>
))}
</Accordion>
</>
);
}
Custom Hooks
useAccordion
Build fully custom accordion UI with your own markup.
import { useAccordion } from 'react-pro-accordion';
function CustomAccordion() {
const { open, toggle, isExpanded } = useAccordion({
defaultExpanded: [],
allowMultiple: true,
});
return (
<div>
<button onClick={() => open('item1')}>Open Item 1</button>
<div>
<button onClick={() => toggle('item1')}>{isExpanded('item1') ? '▼' : '▶'} Item 1</button>
{isExpanded('item1') && <div>Content 1</div>}
</div>
</div>
);
}
useAccordionControls
Access control methods from anywhere inside an <Accordion> tree.
import { useAccordionControls } from 'react-pro-accordion';
function Controls() {
const { openAll, closeAll, openItem, toggleItem } = useAccordionControls();
return (
<div>
<button onClick={openAll}>Open All</button>
<button onClick={closeAll}>Close All</button>
<button onClick={() => openItem('item1')}>Open Item 1</button>
<button onClick={() => toggleItem('item1')}>Toggle Item 1</button>
</div>
);
}
Available hooks:
| Hook | Description |
|---|---|
useAccordion(options) |
Core accordion state and logic |
useAccordionItem(id, options) |
State for an individual item |
useAccordionContext() |
Access the accordion context directly |
useAccordionControls() |
Access open/close/toggle methods |
useAnimation(options) |
Custom animation hook |
API Reference
<Accordion>
| Prop | Type | Default | Description |
|---|---|---|---|
mode |
'single' | 'multiple' |
'single' |
Controls whether one or many items can be open |
allowMultiple |
boolean |
false |
Allow multiple items open at once |
collapsible |
boolean |
true |
Allow all items to be closed simultaneously |
defaultExpanded |
string[] |
[] |
IDs of items expanded on initial render |
expanded |
string[] |
undefined |
Controlled list of expanded item IDs |
lazyRender |
boolean |
false |
Only render content when the item is expanded |
animationDuration |
number |
200 |
Transition duration in milliseconds |
animationEasing |
string |
'cubic-bezier(0.4, 0, 0.2, 1)' |
CSS easing function |
disableAnimation |
boolean |
false |
Disable all animations |
dir |
'ltr' | 'rtl' |
'ltr' |
Text direction |
onOpen |
(id: string) => void |
— | Fires when an item opens |
onClose |
(id: string) => void |
— | Fires when an item closes |
onToggle |
(id: string, isOpen: boolean) => void |
— | Fires on any toggle |
onOpenAll |
() => void |
— | Fires when all items are opened |
onCloseAll |
() => void |
— | Fires when all items are closed |
onAnimationStart |
(id: string) => void |
— | Fires when an animation begins |
onAnimationEnd |
(id: string) => void |
— | Fires when an animation ends |
className |
string |
'' |
Additional CSS class |
style |
object |
{} |
Inline styles |
as |
React.ElementType |
'div' |
Custom wrapper element type |
<AccordionItem>
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
required | Unique identifier for this item |
disabled |
boolean |
false |
Prevents the item from being toggled |
defaultExpanded |
boolean |
false |
Expands this item on initial render |
className |
string |
'' |
Additional CSS class |
style |
object |
{} |
Inline styles |
as |
React.ElementType |
'div' |
Custom wrapper element type |
<AccordionHeader>
| Prop | Type | Default | Description |
|---|---|---|---|
level |
number |
3 |
Heading level (1–6) |
className |
string |
'' |
Additional CSS class |
style |
object |
{} |
Inline styles |
as |
React.ElementType |
'div' |
Custom wrapper element type |
<AccordionTrigger>
| Prop | Type | Default | Description |
|---|---|---|---|
iconPosition |
'left' | 'right' |
'right' |
Position of the expand/collapse icon |
className |
string |
'' |
Additional CSS class |
style |
object |
{} |
Inline styles |
as |
React.ElementType |
'button' |
Custom wrapper element type |
<AccordionIcon>
| Prop | Type | Default | Description |
|---|---|---|---|
expandedIcon |
React.ReactNode |
null |
Icon shown when item is expanded |
collapsedIcon |
React.ReactNode |
null |
Icon shown when item is collapsed |
className |
string |
'' |
Additional CSS class |
style |
object |
{} |
Inline styles |
as |
React.ElementType |
'span' |
Custom wrapper element type |
Styling & Theming
CSS Variables
All visual properties can be overridden via CSS custom properties.
:root {
/* Layout */
--accordion-border-radius: 0.5rem;
--accordion-border-color: #e2e8f0;
--accordion-bg-color: #ffffff;
--accordion-item-border-color: #e2e8f0;
--accordion-item-expanded-bg: #f7fafc;
/* Trigger */
--accordion-trigger-padding: 1rem;
--accordion-trigger-font-weight: 500;
--accordion-trigger-color: #1a202c;
--accordion-trigger-hover-bg: #f7fafc;
--accordion-trigger-hover-color: #2d3748;
--accordion-trigger-expanded-color: #2c5282;
--accordion-trigger-expanded-bg: #ebf8ff;
--accordion-trigger-gap: 0.5rem;
/* Content */
--accordion-content-padding: 1rem;
/* Animation */
--accordion-transition-duration: 0.3s;
--accordion-animation-duration: 0.3s;
--accordion-animation-easing: cubic-bezier(0.4, 0, 0.2, 1);
/* Focus */
--accordion-focus-ring-color: #3182ce;
}
Built-in Themes
Apply a theme by adding the corresponding class to your <Accordion>.
<Accordion className="react-pro-accordion--dark"> {/* Dark */}
<Accordion className="react-pro-accordion--light"> {/* Light (default) */}
<Accordion className="react-pro-accordion--compact">{/* Compact */}
<Accordion className="react-pro-accordion--large"> {/* Large */}
<Accordion className="react-pro-accordion--bordered">{/* Bordered */}
<Accordion className="react-pro-accordion--minimal">{/* Minimal */}
<Accordion className="react-pro-accordion--card"> {/* Card */}
Custom Theme Example
.my-theme {
--accordion-border-color: #9b4d96;
--accordion-bg-color: #fdf6fd;
--accordion-trigger-color: #6b3e66;
--accordion-trigger-hover-bg: #f0e6ef;
--accordion-trigger-expanded-color: #9b4d96;
--accordion-border-radius: 20px;
--accordion-trigger-padding: 1.25rem;
}
<Accordion className="my-theme">{/* items */}</Accordion>
Inline CSS Variable Override
<Accordion
style={{
'--accordion-border-color': '#c53030',
'--accordion-bg-color': '#fff5f5',
'--accordion-trigger-color': '#c53030',
'--accordion-border-radius': '12px',
}}
>
{/* items */}
</Accordion>
Accessibility
React Pro Accordion is built with accessibility as a first-class feature.
- ARIA attributes —
aria-expanded,aria-controls,aria-disabledapplied automatically - Keyboard navigation — Full keyboard support out of the box:
Enter/Space— Toggle the focused itemArrow Up/Arrow Down— Move focus between itemsHome/End— Jump to first or last item
- Screen reader support — State changes are announced correctly
- Focus management — Visible focus indicators on all interactive elements
- Reduced motion — Respects
prefers-reduced-motionmedia query
Browser Support
| Browser | Support |
|---|---|
| Chrome | Latest |
| Firefox | Latest |
| Safari | Latest |
| Edge | Latest |
| iOS Safari | Latest |
| Android Chrome | Latest |
Development
# Install dependencies
npm install
# Build the package
npm run build
License
This project is under the MIT license.
Author
Built with by Nascenture.
- Website: https://www.nascenture.com
- React Development Services: https://www.nascenture.com/react-js-development/