Skip to main content

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

Live Editor
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>
  );
}
Result
Loading...

Headline

Live Editor
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>
  );
}
Result
Loading...

List

Live Editor
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>
  );
}
Result
Loading...

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.

Live Editor
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>
  );
}
Result
Loading...

Badge

To display a badge you can use the badge prop.

Live Editor
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>
  );
}
Result
Loading...

Bordered

To display a bordered variant can use the bordered prop.

Live Editor
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>
  );
}
Result
Loading...

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.

Live Editor
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>
    </>
  );
}
Result
Loading...

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.

Live Editor
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>
    </>
  );
}
Result
Loading...

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.

Live Editor
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>
    </>
  );
}
Result
Loading...

Data Props

The below example shows component support for data props.

Live Editor
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>
  );
}
Result
Loading...

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.

Live Editor
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>
    </>
  );
}
Result
Loading...

Expanded

To make accordion item open by default you can add the isExpanded property to your item object.

Live Editor
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>
    </>
  );
}
Result
Loading...

Nested

The accordion component supports nested items. You can find below the example of data for using the accordion component nested option.

info

Nested items are available to use only for the list type accordion.

Live Editor
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>
  );
}
Result
Loading...

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.

info

togglePosition prop is available to use only for the list type accordion.

Live Editor
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>
  );
}
Result
Loading...

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.

Live Editor
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>
    </>
  );
}
Result
Loading...

Examples

Working with Checkbox List

Accordion can select or unselect all the items in a checkbox list by combining checkboxState, checkboxType and onUpdateAccordion.

Live Editor
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>
  );
}
Result
Loading...

Props

NameTypeDefault
type *
type of accordion
"headline" | "list"
data *
accordion data
AccordionItem[]
bordered
makes accordion headers bordered - for list type only
boolean
disabled
makes all accordion items disabled
boolean
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
boolean
togglePosition
toggle button position - for list type only
"left" | "right"
backgroundColor
background color of headline
string
data-{foo}
Data attributes can be used by testing libraries to retrieve components or assert their existence
string
* - the prop is required.