Accordion
Accordions are navigational elements that allow to structure content title-like and focus the view by hiding content.
One advantages of accordions is that they support in getting an overview before focusing on details. Additionally, accordions help to structure and display larger content on a single page. Nevertheless preventing scrolling should not be the only reason for making use of an accordion.
Accordions are more suitable when people need only a few key pieces of content on a single page.
Example
function MyAccordion() { const lipsum = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpos."; const data = [ { id: 1, count: 100, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: lipsum, tooltipContent: lipsum }, { id: 2, count: 30, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: 'Title 2', tooltipContent: lipsum }, { id: 3, count: 50, content: <div> <Input label="First Name" /> {' '} <Input label="Last Name" /> </div>, isSelectable: true, title: 'Title 3', tooltipContent: lipsum }, ]; return ( <div> <Accordion data={data} type="headline" /> </div> ); }
Headline
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, title: 'Section Title', content: <Content /> }, { id: 2, title: 'Section Title 2', content: <Content /> } ]; return ( <div> <Accordion data={data} type="headline" /> </div> ); }
List
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, title: 'Section Title', content: <Content /> }, { id: 2, title: 'Section Title 2', content: <Content /> } ]; return ( <div> <Accordion data={data} type="list" /> </div> ); }
Variants
Background Color
To customize the background color of headline accordion, you can use the backgroundColor prop.
You can also use any color code in hex, rgb, rgba, or hsl formats.
function MyAccordion() { const lipsum = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpos."; const data = [ { id: 1, count: 100, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: "It is a long established fact that a reader will be distracted", tooltipContent: lipsum, }, { id: 2, count: 30, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: 'Title 2', tooltipContent: lipsum, isDisabled: true, } ]; return ( <div> <Accordion data={data} type="headline" backgroundColor="transparent" /><br/> <Accordion data={data} type="headline" backgroundColor={ColorPrimary20} /><br/> <Accordion data={data} type="list" backgroundColor="transparent" /><br/> <Accordion data={data} type="list" bordered backgroundColor={ColorPositive10} /> </div> ); }
Badge
To display a badge you can use the badge prop.
function MyAccordion() { const lipsum = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpos."; const data = [ { id: 1, count: 100, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: "It is a long established fact that a reader will be distracted", tooltipContent: lipsum, badge: { label: 'Completed', color: 'positive', iconName: 'Check' } }, { id: 2, count: 30, content: <Text type="body1">{lipsum}</Text>, isSelectable: true, title: 'Title 2', tooltipContent: lipsum, badge: { label: 'Custom', customColor: '#6c19d3', iconName: 'Cross' } } ]; return ( <div> <Accordion data={data} type="headline" /><br/> <Accordion data={data} type="list" /> </div> ); }
Bordered
To display a bordered variant can use the bordered prop.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, count: 100, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, count: 100, title: 'Section Title 2', tooltipContent: 'section title 2 tooltip content' } ]; return ( <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" bordered /> </div> ); }
Checkbox
You can display a checkbox for accordion header.
the list type accordion headers can't have item based checkbox.
If you using the list type accordion please use selectable prop instead. It's adds all accordion headers checkbox.
If you use the headline type accordion, you can use the selectable prop to make all items with the checkbox.
Or you can add the checkboxes to your items separately.
To use item based checkbox in the accordion header, you need to add to your item object the isSelectable property.
You can also change the checkbox state for the expanded accordion item header. To use this feature, you need to add to your item object the checkboxType property.
It's takes two type of value checked or indeterminate by default it's a checked.
You can isolate and customize the checkbox component utilizing isolateCheckbox, combined with onItemUpdate, callback.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const dataHeadline = [ { id: 1, content: <Content />, isSelectable: true, title: 'Section Title', tooltipContent: 'section title tooltip content', checkboxType: 'indeterminate', isIsolateCheckbox: true }, { id: 2, content: <Content />, isSelectable: true, title: 'Section Title 2', tooltipContent: 'section title 2 tooltip content' } ]; const data = [ { id: 1, content: <Content />, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, title: 'Section Title 2', tooltipContent: 'section title 2 tooltip content' } ]; return ( <> <div> <Accordion data={dataHeadline} type="headline" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" selectable /> </div> </> ); }
onItemUpdate
onItemUpdate is a callback prop that informs the parent component about the set of information that belongs to the clicked accordion item when the user clicks on the accordion header. These parameters are: id: clicked item id. isExpanded: a boolean value returns true if the clicked item is expanded. isCustomCheckbox: a boolean value returns true if the clicked area is a custom checkbox.
This callback allows you to modify accordion item properties at the parent component when the user clicks on the accordion item header or custom checkbox.
function MyAccordion() { const [checkboxState, setCheckboxState] = useState(false); const [accordionData, setAccordionData] = useState([]); const item = 'Click on checkbox to select'; const description = 'This dropdown is standard Accordion checkbox functionality.'; const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, title: 'Section Title 2', tooltipContent: 'section title 2 tooltip content' }, { id: 3, content: ( <div> <Text type="body2">{item}</Text> </div> ), title: 'Customized checkbox functionality', isolateCheckbox: true, tooltipContent: description, checkboxState: checkboxState } ]; useEffect(() => { setAccordionData(data); }, []); const onUpdateAccordion = (id, isExpanded, isCustomCheckbox) => { const modifiedData = accordionData.map((item) => item.id === id ? { ...item, title: 'title changed after click', checkboxState: !item.checkboxState } : item ); setAccordionData(modifiedData); }; return ( <> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={accordionData} type="list" selectable onItemUpdate={onUpdateAccordion} /> </div> </> ); }
Count
You can display a count on accordion headers.
To display a count value you need to add to your item object count property with its content.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, count: 25, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, count: 20, title: 'Section Title 2', tooltipContent: 'section title 2 tooltip content' } ]; return ( <> <div> <Accordion data={data} type="headline" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" /> </div> </> ); }
Data Props
The below example shows component support for data props.
function MyAccordion() { const data = [ { id: 1, count: 30, content: <Text type="body1">{'test'}</Text>, isSelectable: true, title: 'Title 2' }, { id: 2, count: 50, content: <div> <Input label="First Name" /> {' '} <Input label="Last Name" /> </div>, isSelectable: true, title: 'Title 3' }, ]; return ( <div> <Accordion data={data} type="headline" data-testid="accordion-test-id"/> </div> ); }
Disabled
To disable a accordion item you need to add isDisabled property to your item object.
If you prefer to make all accordion items disabled, you can use the disabled prop.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, count: 100, isDisabled: true, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, count: 4, title: 'Section Title', tooltipContent: <div>Section Title 2 tooltip content</div> } ]; return ( <> <div> <Accordion data={data} type="headline" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="headline" disabled /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" disabled /> </div> </> ); }
Expanded
To make accordion item open by default you can add the isExpanded property to your item object.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, count: 100, isExpanded: true, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, count: 4, title: 'Section Title', tooltipContent: <div>Section Title 2 tooltip content</div> } ]; return ( <> <div> <Accordion data={data} type="headline" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="headline" disabled /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" disabled /> </div> </> ); }
Nested
The accordion component supports nested items. You can find below the example of data for using the accordion component nested option.
Nested items are available to use only for the list type accordion.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, title: 'Section Title', items: [ { id: 1, content: <Content />, title: 'Sub Title 1' }, { id: 2, content: <Content />, title: 'Sub Title 2', items: [ { id: 1, content: <Content />, title: 'Sub Title 2 a' } ] } ] }, { id: 2, content: <Content />, title: 'Section Title 2' } ]; return ( <div> <Accordion data={data} type="list" /> </div> ); }
Toggle Position
You can change the toggle arrow button position with the togglePosition prop.
The toggle button can be used at the accordion header's right and left positions.
By default, the toggle button position is right side.
togglePosition prop is available to use only for the list type accordion.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, title: 'Section Title 2', tooltipContent: <div>Section Title 2 tooltip content</div> } ]; return ( <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" togglePosition="right" /> <Accordion data={data} type="list" togglePosition="left" /> </div> ); }
Tooltip
You can display a tooltip for each accordion item title.
To display a tooltip you need to add to your item object tooltipContent property with its content.
function MyAccordion() { const Content = () => { return ( <Text type="body1"> Hello! This is some random text with tag of 'p' and the type of 'body1' </Text> ); }; const data = [ { id: 1, content: <Content />, title: 'Section Title', tooltipContent: 'section title tooltip content' }, { id: 2, content: <Content />, title: 'Section Title 2', tooltipContent: <div>Section Title 2 tooltip content</div> } ]; return ( <> <div> <Accordion data={data} type="headline" /> </div> <div style={{ height: '100%', marginTop: '30px' }}> <Accordion data={data} type="list" /> </div> </> ); }
Examples
Working with Checkbox List
Accordion can select or unselect all the items in a checkbox list by combining checkboxState, checkboxType and onUpdateAccordion.
function MyAccordion() { const [data, setData] = useState([]); const initialData = [ { id: 'header1', title: 'Section Title 1', tooltipContent: 'section title tooltip content', checkboxState: false, checkboxType: 'checked', isExpanded: false, items : [ { id: "checkbox1", label: "Checkbox 1", checked: false }, { id: "checkbox2", label: "Checkbox 2", checked: false }, { id: "checkbox3", label: "Checkbox 3", checked: false } ] }, { id: 'header2', title: 'Section Title 2', tooltipContent: 'section title tooltip content', checkboxState: false, checkboxType: 'checked', isExpanded: false, items : [ { id: "checkbox4", label: "Checkbox 4", checked: false }, { id: "checkbox5", label: "Checkbox 5", checked: false } ] } ] const CheckboxList = ({items, headerId}) => { const handleChange = (itemId) => { const modifiedItems = items.map(item => item.id === itemId ? {...item, checked: !item.checked} : item); const count = modifiedItems.filter(item => item.checked).length; const modifiedData = data.map(header => header.id === headerId ? { ...header, items: modifiedItems, checkboxState: count > 0 ? true : false, checkboxType: count < modifiedItems.length && count > 0 ? 'indeterminate' : 'checked' } : header); setData(modifiedData); } return ( <div> {items.map(item => <div key={item.id}> <Checkbox label={item.label} checked={item.checked} onChange={() => handleChange(item.id, headerId)} /> </div> )} </div> ); }; useEffect(() => { setData(initialData); }, []); const accordionData = data.map(header => ({ id: header.id, content: <CheckboxList items={header.items} headerId={header.id} />, title: header.title, tooltipContent: header.tooltipContent, isSelectable: true, isolateCheckbox: true, checkboxState: header.checkboxState, checkboxType: header.checkboxType, isExpanded: header.isExpanded, })); const onUpdateAccordion = (id, isExpanded, isCustomCheckbox) => { console.log(data); if(isCustomCheckbox) { const modifiedData = data.map(header => header.id === id ? { ...header, items: header.items.map( item => ({ ...item, checked: !header.checkboxState}) ), checkboxState: !header.checkboxState, checkboxType: 'checked', isExpanded: true, } : header); setData(modifiedData); } }; return ( <div style={{ height: '100%'}}> <Accordion data={accordionData} type="headline" bordered onItemUpdate={onUpdateAccordion} /> </div> ); }
Props
| Name | Type | Default |
|---|---|---|
type * type of accordion |
| — |
data * accordion data |
| — |
bordered makes accordion headers bordered - for list type only |
| — |
disabled makes all accordion items disabled |
| — |
onItemUpdate callback for getting clicked item id, expand status and type (clicked item is custom checkbox or accordion header) |
| — |
selectable makes all items selectable |
| — |
togglePosition toggle button position - for list type only |
| — |
backgroundColor background color of headline |
| — |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
| * - the prop is required. |