Accordion

The accordion component enables users to collapse and expand multiple content sections within a limited space. This helps group and hide content effectively, maintaining a clean interface and reducing clutter.

import {Accordion} from "@qualcomm-ui/react/accordion"

Usage

  • The accordion requires each of its items to have a unique value input.
  • The accordion is keyboard-navigable once focused. Arrow keys can be used to move to the next or previous item. Home and End keys can be used to jump to the first or last item, respectively.

Examples

Simple

Here's a typical usage example that uses the shorthand syntax for the item.

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.

<Accordion.Root className="w-96" defaultValue={["a"]}>
  <Accordion.Item
    secondaryText="Secondary text"
    text="Accordion Text 1"
    value="a"
  >
    <LoremIpsum />
  </Accordion.Item>

  <Accordion.Item
    secondaryText="Secondary text"
    text="Accordion Text 2"
    value="b"
  >
    <LoremIpsum />
  </Accordion.Item>
</Accordion.Root>

Composite

The following example is equivalent to the previous example, but uses the composite approach.

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.

<Accordion.ItemRoot value="a">
  <Accordion.ItemTrigger>
    <Accordion.ItemText>Accordion Text 1</Accordion.ItemText>
    <Accordion.ItemSecondaryText>
      Secondary text
    </Accordion.ItemSecondaryText>
    <Accordion.ItemIndicator />
  </Accordion.ItemTrigger>
  <Accordion.ItemContent>
    <LoremIpsum />
  </Accordion.ItemContent>
</Accordion.ItemRoot>

Composite Layout

Use the composite form only when the simple approach can't achieve your desired layout or behavior. The following example demonstrates how to display the expand/collapse indicator at the start of the trigger by changing its DOM position.

<Accordion.Root className="w-96">
  {items.map((item) => (
    <Accordion.ItemRoot key={item.value} value={item.value}>
      <Accordion.ItemTrigger>
        <Accordion.ItemIndicator />
        <Accordion.ItemText>{item.text}</Accordion.ItemText>
      </Accordion.ItemTrigger>
      <Accordion.ItemContent>{item.content}</Accordion.ItemContent>
    </Accordion.ItemRoot>
  ))}
</Accordion.Root>

Multiple

By default, only a single accordion section can be open at a time. Setting multiple allows multiple sections to be open or closed simultaneously.

<Accordion.Root className="w-96" multiple>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Collapsible

When multiple is not set, enabling collapsible lets the user close an open accordion item by clicking it again.

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
<Accordion.Root className="w-96" collapsible defaultValue={["a"]}>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Default Value

The defaultValue prop allows you to set the initial state for the accordion by specifying which accordion item or items (if multiple is set) should be open by default. It expects an array of values that should match those passed to each Accordion.Item.

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
<Accordion.Root className="w-96" defaultValue={["a"]}>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Disabled

You can disable accordion items by setting their disabled prop. This prevents the item from being interacted with. You can disable the entire accordion by setting the disabled prop on Accordion.Root.

<Accordion.Root className="w-full" disabled={disabled}>
  {items.map((item) => (
    <Accordion.Item
      key={item.value}
      disabled={item.disabled}
      text={item.text}
      value={item.value}
    >
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Uncontained

Set the uncontained prop when the accordion is not placed inside a container and needs to align flush with adjacent layout elements—such as when positioned directly below a paragraph of text. This prop removes the default horizontal padding from accordion items, allowing them to sit seamlessly within the surrounding content.

<Accordion.Root className="w-96" uncontained>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Size

Use the size prop to control the size of the accordion items. The available sizes are sm, md (default), and lg.

<Accordion.Root className="w-full" size={size}>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Secondary Text

Use the Accordion.ItemSecondaryText component to display additional text opposite the trigger title.

<Accordion.Root className="w-96">
  {items.map((item) => (
    <Accordion.Item
      key={item.value}
      secondaryText={item.secondaryText}
      text={item.text}
      value={item.value}
    >
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Icon

Pass an icon to the icon prop on the Accordion.ItemTrigger element to display it next to the trigger title.

<Accordion.Root className="w-96">
  {items.map((item) => (
    <Accordion.Item
      key={item.value}
      icon={FileChartColumn}
      text={item.text}
      value={item.value}
    >
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

UX considerations

In order to prevent visual confusion, only one icon can appear next to the trigger title. If you place the indicator at the start, the icon prop will be ignored.

Controlled State

The Accordion follows our controlled state pattern with these three props:

  • value - the controlled value that determines which accordion items are open.
  • onValueChange - callback fired when the value changes: (value: string[]) => void
  • defaultValue - initial state for uncontrolled mode

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.

currently opened:a
<Accordion.Root
  multiple
  onValueChange={setCurrentValue}
  value={currentValue}
>
  <Accordion.Item text="Accordion Text 1" value="a">
    <LoremIpsum />
  </Accordion.Item>
  <Accordion.Item text="Accordion Text 2" value="b">
    <LoremIpsum />
  </Accordion.Item>
  <Accordion.Item text="Accordion Text 3" value="c">
    <LoremIpsum />
  </Accordion.Item>
</Accordion.Root>

Focus Callback

The onFocusChange prop allows you to listen for focus events on the accordion's items.

Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas.
currently focused: none
<Accordion.Root
  defaultValue={["a"]}
  multiple
  onFocusChange={(value) => setCurrentValue(value || "")}
>
  {items.map((item) => (
    <Accordion.Item key={item.value} text={item.text} value={item.value}>
      {item.content}
    </Accordion.Item>
  ))}
</Accordion.Root>

Shortcuts

Item Content

The Accordion.ItemContent component is a shortcut for the following:

<AccordionItemContentAnimator>
  <AccordionItemContentBody>{children}</AccordionItemContentBody>
</AccordionItemContentAnimator>

Item Shorthand

The Accordion.Item component is a shortcut for the following:

<Accordion.ItemRoot>
  <Accordion.ItemTrigger>
    <Accordion.ItemText>{props.text}</Accordion.ItemText>
    {props.secondaryText ? (
      <Accordion.ItemSecondaryText>
        {props.secondaryText}
      </Accordion.ItemSecondaryText>
    ) : null}
    <Accordion.ItemIndicator />
  </Accordion.ItemTrigger>
  <Accordion.ItemContent>{props.children}</Accordion.ItemContent>
</Accordion.ItemRoot>

API

<Accordion.Root>

Groups all parts of the accordion. Renders a <div> element by default.
PropTypeDefault
React children prop.
Whether sections can be collapsed (in non-multiple mode).
boolean
Initial value of the accordion.
string[]
The document's text/writing direction.
'ltr' | 'rtl'
'ltr'
The disabled state of the accordion.
boolean
Whether multiple accordion items can be expanded at once.
boolean
Focus change callback.
    (
    value: string,
    ) => void
    Value change callback.
      (
      value: string[],
      ) => void
      Allows you to replace the component's HTML element with a different tag or component. Learn more
      | ReactElement
      | ((
      props: object,
      ) => ReactElement)
      The size of the accordion.
      | 'sm'
      | 'md'
      | 'lg'
      To display the accordion uncontained to the edges of its container.
      boolean
      Value(s) of the accordion's open item(s).
      string[]
      Description
      React children prop.
      Type
      boolean
      Description
      Whether sections can be collapsed (in non-multiple mode).
      Type
      string[]
      Description
      Initial value of the accordion.
      Type
      'ltr' | 'rtl'
      Description
      The document's text/writing direction.
      Type
      boolean
      Description
      The disabled state of the accordion.
      Type
      boolean
      Description
      Whether multiple accordion items can be expanded at once.
      Type
      (
      value: string,
      ) => void
      Description
      Focus change callback.
        Type
        (
        value: string[],
        ) => void
        Description
        Value change callback.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          Type
          | 'sm'
          | 'md'
          | 'lg'
          Description
          The size of the accordion.
          Type
          boolean
          Description
          To display the accordion uncontained to the edges of its container.
          Type
          string[]
          Description
          Value(s) of the accordion's open item(s).

          <Accordion.Item>

          Groups all parts of the accordion item and exposes customization via props. Renders a <div> element by default.
          PropType
          The primary text label for the item.
          The value of the accordion item.
          string
          React children prop. This is the content body of the item.
          Props applied to the content element.
          The disabled state of the accordion item.
          boolean
          An icon to display next to the trigger title.
          LucideIcon
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          string
          Props applied to the indicator element.
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          The secondary text label for the item.
          Props applied to the secondary text element.
          Props applied to the text element.
          Props applied to the trigger element.
          Description
          The primary text label for the item.
          Type
          string
          Description
          The value of the accordion item.
          Description
          React children prop. This is the content body of the item.
          Description
          Props applied to the content element.
          Type
          boolean
          Description
          The disabled state of the accordion item.
          Type
          LucideIcon
          Description
          An icon to display next to the trigger title.
          Type
          string
          Description
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          Description
          Props applied to the indicator element.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          Description
          The secondary text label for the item.
          Description
          Props applied to the secondary text element.
          Description
          Props applied to the text element.
          Description
          Props applied to the trigger element.

          <Accordion.ItemTrigger>

          A button that opens and closes the corresponding panel. Renders a <button> element by default.
          PropType
          React children prop.
          An icon to display next to the trigger title.
          LucideIcon
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          string
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          React children prop.
          Type
          LucideIcon
          Description
          An icon to display next to the trigger title.
          Type
          string
          Description
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more

          <Accordion.ItemText>

          A heading that labels the accordion item. Renders a <span> element by default.
          PropType
          React children prop.
          Description
          React children prop.

          <Accordion.ItemSecondaryText>

          A description with additional information about the accordion item. Renders a <span> element by default.
          PropType
          React children prop.
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          React children prop.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more

          <Accordion.ItemIndicator>

          Indicates the open/close state of the trigger's associated panel. Renders a <div> element by default.
          PropTypeDefault
          Indicator icon for the accordion item trigger.
          | LucideIcon
          | ReactNode
          ChevronDown
          
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Type
          | LucideIcon
          | ReactNode
          Description
          Indicator icon for the accordion item trigger.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more

          <Accordion.ItemContent>

          A collapsible panel with the accordion item contents. Renders a <div> element by default.
          PropType
          React children prop.
          Props applied to the content body element.
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          React children prop.
          Description
          Props applied to the content body element.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more

          <Accordion.ItemContentAnimator>

          The outer container of the accordion item content. Responsible for animating the inner accordion contents. Renders a <div> element by default.
          PropType
          React children prop.
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          string
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          React children prop.
          Type
          string
          Description
          id attribute. If omitted, a unique identifier will be automatically generated for accessibility.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more

          <Accordion.ItemContentBody>

          The inner container of the accordion item content. Renders a <div> element by default.
          PropType
          React children prop.
          Allows you to replace the component's HTML element with a different tag or component. Learn more
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          React children prop.
          Type
          | ReactElement
          | ((
          props: object,
          ) => ReactElement)
          Description
          Allows you to replace the component's HTML element with a different tag or component. Learn more