Components
Accordion

Accordion

A collapsible component that displays content in a vertical stack.

Usage

Pudding donut gummies chupa chups oat cake marzipan biscuit tart. Dessert macaroon ice cream bonbon jelly. Jelly topping tiramisu halvah lollipop.
import { ChevronDownIcon } from 'lucide-react'
import * as Accordion from '~/components/ui/accordion'

export const Demo = (props: Accordion.RootProps) => {
  const items = ['React', 'Solid', 'Svelte', 'Vue']
  return (
    <Accordion.Root defaultValue={['React']} multiple {...props}>
      {items.map((item, id) => (
        <Accordion.Item key={id} value={item} disabled={item === 'Svelte'}>
          <Accordion.ItemTrigger>
            {item}
            <Accordion.ItemIndicator>
              <ChevronDownIcon />
            </Accordion.ItemIndicator>
          </Accordion.ItemTrigger>
          <Accordion.ItemContent>
            Pudding donut gummies chupa chups oat cake marzipan biscuit tart. Dessert macaroon ice
            cream bonbon jelly. Jelly topping tiramisu halvah lollipop.
          </Accordion.ItemContent>
        </Accordion.Item>
      ))}
    </Accordion.Root>
  )
}

Installation

1

Add Component

Insert code snippet into your project. Update import paths as needed.

import type { Assign } from '@ark-ui/react'
import { Accordion } from '@ark-ui/react/accordion'
import { type AccordionVariantProps, accordion } from 'styled-system/recipes'
import type { JsxStyleProps } from 'styled-system/types'
import { createStyleContext } from '~/lib/create-style-context'

const { withProvider, withContext } = createStyleContext(accordion)

export interface RootProps
  extends Assign<JsxStyleProps, Accordion.RootProps>,
    AccordionVariantProps {}
export const Root = withProvider<HTMLDivElement, RootProps>(Accordion.Root, 'root')

export const ItemContent = withContext<
  HTMLDivElement,
  Assign<JsxStyleProps, Accordion.ItemContentProps>
>(Accordion.ItemContent, 'itemContent')

export const ItemIndicator = withContext<
  HTMLDivElement,
  Assign<JsxStyleProps, Accordion.ItemIndicatorProps>
>(Accordion.ItemIndicator, 'itemIndicator')

export const Item = withContext<HTMLDivElement, Assign<JsxStyleProps, Accordion.ItemProps>>(
  Accordion.Item,
  'item',
)

export const ItemTrigger = withContext<
  HTMLButtonElement,
  Assign<JsxStyleProps, Accordion.ItemTriggerProps>
>(Accordion.ItemTrigger, 'itemTrigger')

export {
  AccordionContext as Context,
  AccordionItemContext as ItemContext,
  type AccordionContextProps as ContextProps,
  type AccordionItemContextProps as ItemContextProps,
} from '@ark-ui/react/accordion'

export type {
  AccordionFocusChangeDetails as FocusChangeDetails,
  AccordionValueChangeDetails as ValueChangeDetails,
} from '@ark-ui/react/accordion'
2

Add Recipe

This step is necessary only if you do not use any of the Park UI plugins.

import { accordionAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'

export const accordion = defineSlotRecipe({
  className: 'accordion',
  slots: accordionAnatomy.keys(),
  base: {
    root: {
      divideY: '1px',
      width: 'full',
      borderTopWidth: '1px',
      borderBottomWidth: '1px',
    },
    itemTrigger: {
      alignItems: 'center',
      color: 'fg.default',
      cursor: 'pointer',
      display: 'flex',
      fontWeight: 'semibold',
      gap: '3',
      justifyContent: 'space-between',
      textStyle: 'lg',
      textAlign: 'left',
      width: 'full',
      _disabled: {
        color: 'fg.disabled',
        cursor: 'not-allowed',
      },
    },
    itemIndicator: {
      color: 'fg.muted',
      transformOrigin: 'center',
      transitionDuration: 'normal',
      transitionProperty: 'transform',
      transitionTimingFunction: 'default',
      _open: {
        transform: 'rotate(-180deg)',
      },
    },
    itemContent: {
      color: 'fg.muted',
      overflow: 'hidden',
      transitionProperty: 'padding-bottom',
      transitionDuration: 'normal',
      transitionTimingFunction: 'default',
      _open: {
        animation: 'collapse-in',
      },
      _closed: {
        animation: 'collapse-out',
      },
    },
  },
  defaultVariants: {
    size: 'md',
  },
  variants: {
    size: {
      md: {
        itemTrigger: {
          py: '4',
        },
        itemContent: {
          pb: '6',
          pr: '8',
          _closed: {
            pb: '0',
          },
        },
      },
    },
  },
})

Previous

Text

Next

Alert

On this page