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>
);
}
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
|
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) | ((id: string | number, isExpanded: boolean, isCustomCheckbox: boolean) => void)
| — |
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. |