Skip to content

Accordion

TIP

Don't specify padding and margin for Accordion.Item.Collapse, this will break the animation.

Basic usage

By default, the accordion has the secondary theme (use property).

tsx
import Accordion from '@semcore/ui/accordion';
import type { NSAccordion } from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import type { BoxProps } from '@semcore/ui/base-components';
import React from 'react';

type ExampleAccordionProps = NSAccordion.Props & { duration?: number } & NSAccordion.Item.Collapse.Props & BoxProps;

const Demo = (props: ExampleAccordionProps) => {
  const [value, onChange] = React.useState([0]);

  return (
    <Accordion value={value} onChange={(value: any) => onChange(value)} duration={props.duration} use={props.use}>
      {[...new Array(3)].map((_, index) => (
        <Accordion.Item value={index} key={index} disabled={index === 2}>
          <Accordion.Item.Toggle pb={2} w={props.w} h={props.h}>
            <Accordion.Item.ToggleButton>
              <Accordion.Item.Chevron mr={2} />
              Section
              {' '}
              {index + 1}
            </Accordion.Item.ToggleButton>
          </Accordion.Item.Toggle>
          <Accordion.Item.Collapse overflowHidden={props.overflowHidden} defaultHeight={props.defaultHeight}>
            <Box pt={3} px={6} pb={6}>{`This is section ${index + 1}`}</Box>
          </Accordion.Item.Collapse>
        </Accordion.Item>
      ))}
    </Accordion>
  );
};

export const defaultProps: ExampleAccordionProps = {
  duration: undefined,
  use: undefined,
  overflowHidden: undefined,
  defaultHeight: undefined,
  w: undefined,
  h: undefined,
};

Demo.defaultProps = defaultProps;

export default Demo;

One section opening

value can take both values: single and array of values. By changing it, you change the behavior of the component.

tsx
import Accordion from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import React from 'react';

const Demo = () => {
  const [value, onChange] = React.useState(null); // or []
  return (
    <Accordion value={value} onChange={onChange}>
      {[...new Array(3)].map((_, index) => (
        <Accordion.Item value={index} key={index} disabled={index === 2}>
          <Accordion.Item.Toggle pb={2}>
            <Accordion.Item.ToggleButton>
              <Accordion.Item.Chevron mr={2} />
              Section
              {' '}
              {index + 1}
            </Accordion.Item.ToggleButton>
          </Accordion.Item.Toggle>
          <Accordion.Item.Collapse>
            <Box pt={3} px={6} pb={6}>{`This is section ${index + 1}`}</Box>
          </Accordion.Item.Collapse>
        </Accordion.Item>
      ))}
    </Accordion>
  );
};

export default Demo;

Heading tag

By default, Accordion.Item.Toggle is set to an h3 heading level, but you can change it if needed.

tsx
import Accordion from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import React from 'react';

const Demo = () => {
  const [value, onChange] = React.useState(null); // or []
  return (
    <Accordion value={value} onChange={onChange}>
      {[...new Array(3)].map((_, index) => (
        <Accordion.Item value={index} key={index} disabled={index === 2}>
          <Accordion.Item.Toggle pb={2} tag='h2'>
            <Accordion.Item.ToggleButton>
              <Accordion.Item.Chevron mr={2} />
              Section
              {' '}
              {index + 1}
            </Accordion.Item.ToggleButton>
          </Accordion.Item.Toggle>
          <Accordion.Item.Collapse>
            <Box pt={3} px={6} pb={6}>{`This is section ${index + 1}`}</Box>
          </Accordion.Item.Collapse>
        </Accordion.Item>
      ))}
    </Accordion>
  );
};

export default Demo;

Primary theme

Pass use='primary' to enable the primary theme for the accordion.

tsx
import Accordion from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import React from 'react';

const Demo = () => {
  return (
    <Accordion use='primary'>
      {[...new Array(3)].map((_, index) => (
        <Accordion.Item value={index} key={index} disabled={index === 2}>
          <Accordion.Item.Toggle pb={2}>
            <Accordion.Item.ToggleButton>
              <Accordion.Item.Chevron mr={2} />
              Section
              {' '}
              {index + 1}
            </Accordion.Item.ToggleButton>
          </Accordion.Item.Toggle>
          <Accordion.Item.Collapse>
            <Box pt={3} px={6} pb={6}>{`This is section ${index + 1}`}</Box>
          </Accordion.Item.Collapse>
        </Accordion.Item>
      ))}
    </Accordion>
  );
};

export default Demo;

Custom styles for selected toggle

You can customize accordion styles if needed.

For example, to find out whether an element is selected and to highlight it, pass the function into the body of the element.

tsx
import Accordion from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import React from 'react';

const cn = (...classes: any[]) => classes.filter(Boolean).join(' ');

const Demo = () => {
  return (
    <>
      <style>
        {`
          /* In this example we are forced to use more specific css-selectors to override the default Vitepress styles */
          .vp-doc h3.styled-accordion-item {
            background-color: var(--intergalactic-bg-secondary-neutral);
            padding: var(--intergalactic-spacing-2x) var(--intergalactic-spacing-3x);
            color: var(--intergalactic-text-primary);
            margin-bottom: var(--intergalactic-spacing-05x);
          }
          .vp-doc h3.styled-accordion-item:first-of-type {
            border-radius: var(--intergalactic-control-rounded) var(--intergalactic-control-rounded) 0 0;
          }
          .vp-doc h3.styled-accordion-item:last-of-type {
            border-radius: 0 0 var(--intergalactic-control-rounded) var(--intergalactic-control-rounded);
          }
          .vp-doc h3.styled-accordion-item-selected {
            background-color: var(--intergalactic-bg-secondary-neutral-hover);
            color: var(--intergalactic-text-primary);
          }
        `}
      </style>
      <Accordion>
        {[...new Array(3)].map((_, index) => (
          <Accordion.Item value={index} key={index}>
            {({ selected }) => (
              <>
                <Accordion.Item.Toggle
                  className={cn(
                    'styled-accordion-item',
                    selected && 'styled-accordion-item-selected',
                  )}
                >
                  <Accordion.Item.ToggleButton>
                    <Accordion.Item.Chevron mr={2} />
                    Section
                    {' '}
                    {index + 1}
                  </Accordion.Item.ToggleButton>
                </Accordion.Item.Toggle>
                <Accordion.Item.Collapse>
                  <Box py={3} px={6}>{`This is section ${index + 1}`}</Box>
                </Accordion.Item.Collapse>
              </>
            )}
          </Accordion.Item>
        ))}
      </Accordion>
    </>
  );
};

export default Demo;

SEO friendly accordion

By default, collapsed sections aren't rendered in the DOM. If you need to render all sections, pass preserveNode to the Accordion.Item.Collapse component.

tsx
import Accordion from '@semcore/ui/accordion';
import { Box } from '@semcore/ui/base-components';
import React from 'react';

const Demo = () => {
  const [value, onChange] = React.useState([0]);

  return (
    <Accordion value={value} onChange={(value: any) => onChange(value)}>
      {[...new Array(3)].map((_, index) => (
        <Accordion.Item value={index} key={index} disabled={index === 1}>
          <Accordion.Item.Toggle pb={2}>
            <Accordion.Item.ToggleButton>
              <Accordion.Item.Chevron mr={2} />
              Section
              {' '}
              {index + 1}
            </Accordion.Item.ToggleButton>
          </Accordion.Item.Toggle>
          <Accordion.Item.Collapse preserveNode>
            <Box pt={3} px={6} pb={6}>
              {`This is section ${index + 1}`}
              ,
              {' '}
              and it contains a
              {' '}
              <a href='#'>focusable link</a>
            </Box>
          </Accordion.Item.Collapse>
        </Accordion.Item>
      ))}
    </Accordion>
  );
};

export default Demo;

Released under the MIT License.

Released under the MIT License.