Pallas UI
DocsComponents
Core Concepts
    • Introduction
    • Getting Started
    • Theming
    • Color Tokens
    • Spacing & Sizing
    • Layout Guide
    • AspectRatio
    • Box
    • Flex
    • Grid
    • Shapes
Previews
    • Accordion
    • Alert
    • Avatar
    • Badge
    • Breadcrumb
    • Button
    • Carousel
    • Checkbox
    • Combobox
    • Command
    • Date Picker
    • Form
    • Input
    • Input OTP
    • Label
    • MenuBar
    • Modal
    • Popover
    • Progress
    • Radio Group
    • ScrollArea
    • Segmented
    • Select
    • Separator
    • Sheet
    • Sidebar
    • Skeleton
    • Slider
    • Spinner
    • Steps
    • Switch
    • Tabs
    • Textarea
    • Toast
    • Tooltip
    • TreeView
    • Typography
  1. Components
  2. Accordion

Accordion

A vertically stacked set of interactive headings that each reveal a section of content.

Loading preview...

Installation

Install the following dependencies

npm install @radix-ui/react-accordion

Copy and paste the following code into your project

'use client'
 
import { createStyleContext } from '@pallas-ui/style-context'
import type { Assign, WithFixedClassName } from '@pallas-ui/style-context'
import * as RadixAccordion from '@radix-ui/react-accordion'
import { Slot } from '@radix-ui/react-slot'
import { type AccordionVariantProps, accordion } from '@styled-system/recipes'
import type { ComponentProps, JsxStyleProps } from '@styled-system/types'
import { ChevronDown } from 'lucide-react'
import * as React from 'react'
 
const { withProvider, withContext } = createStyleContext(accordion)
 
export type RootProps = WithFixedClassName<
  ComponentProps<typeof RadixAccordion.Root> & {
    collapsible?: boolean
  }
>
export const Root = withProvider<
  React.ComponentRef<typeof RadixAccordion.Root>,
  Assign<RootProps, AccordionVariantProps>
>(RadixAccordion.Root, 'root')
 
export const Item = withContext<
  React.ComponentRef<typeof RadixAccordion.Item>,
  Assign<WithFixedClassName<ComponentProps<typeof RadixAccordion.Item>>, JsxStyleProps>
>(RadixAccordion.Item, 'item')
 
export const ItemHeader = withContext<
  React.ComponentRef<typeof RadixAccordion.Header>,
  Assign<WithFixedClassName<ComponentProps<typeof RadixAccordion.Header>>, JsxStyleProps>
>(RadixAccordion.Header, 'itemHeader')
 
export const ItemTrigger = withContext<
  React.ComponentRef<typeof RadixAccordion.Trigger>,
  Assign<WithFixedClassName<ComponentProps<typeof RadixAccordion.Trigger>>, JsxStyleProps>
>(RadixAccordion.Trigger, 'itemTrigger')
 
export const ItemContent = withContext<
  React.ComponentRef<typeof RadixAccordion.Content>,
  Assign<WithFixedClassName<ComponentProps<typeof RadixAccordion.Content>>, JsxStyleProps>
>(RadixAccordion.Content, 'itemContent')
 
type ItemIndicatorBaseProps = React.ComponentPropsWithoutRef<'span'> & {
  asChild?: boolean
  rotateOnOpen?: boolean
}
 
const ItemIndicatorBase = React.forwardRef<HTMLSpanElement, ItemIndicatorBaseProps>(
  ({ children, asChild, rotateOnOpen = true, ...props }, ref) => {
    const Comp = asChild ? Slot : 'span'
    return (
      <Comp ref={ref} data-rotate={String(rotateOnOpen)} {...props}>
        {children ?? <ChevronDown />}
      </Comp>
    )
  },
)
ItemIndicatorBase.displayName = 'AccordionItemIndicator'
 
export const ItemIndicator = withContext<
  HTMLSpanElement,
  Assign<WithFixedClassName<ComponentProps<typeof ItemIndicatorBase>>, JsxStyleProps>
>(ItemIndicatorBase, 'itemIndicator')
 
const Accordion = {
  Root,
  Item,
  ItemHeader,
  ItemTrigger,
  ItemContent,
  ItemIndicator,
}
 
export default Accordion

Update the import paths to match your project setup

Usage

import Accordion from '@/components/ui/accordion'
<Accordion.Root type="single" collapsible>
  <Accordion.Item value="item-1">
    <Accordion.ItemHeader>
      <Accordion.ItemTrigger>Is it accessible?</Accordion.ItemTrigger>
      <Accordion.ItemIndicator />
    </Accordion.ItemHeader>
    <Accordion.ItemContent>
      Yes. It adheres to the WAI-ARIA design pattern.
    </Accordion.ItemContent>
  </Accordion.Item>
</Accordion.Root>

Examples

Variants

The accordion ships with four variants: default, subtle, bordered, and plain.

Loading preview...

Sizes

Three sizes are available: sm, md (default), and lg.

Loading preview...

Multiple

Use type="multiple" to allow multiple items to be open at the same time.

Loading preview...

Controlled

Control the open state externally using value and onValueChange.

Loading preview...

Custom Indicator

Use asChild on Accordion.ItemIndicator to swap the default chevron for any custom icon.

Loading preview...

API Reference

Root Props

PropTypeDefaultDescription
variant'default' | 'subtle' | 'bordered' | 'plain''default'Visual style of the accordion
size'sm' | 'md' | 'lg''md'Controls padding and text size
type'single' | 'multiple'—Whether one or multiple items can be open at a time
collapsiblebooleanfalseAllow closing the open item (single mode only)
valuestring | string[]—Controlled open state
defaultValuestring | string[]—Initial open state (uncontrolled)
onValueChange(value: string | string[]) => void—Callback when the open state changes

Item Props

PropTypeDefaultDescription
valuestring—Unique identifier for the item (required)
disabledbooleanfalseDisables interaction with the item

ItemTrigger Props

PropTypeDefaultDescription
disabledbooleanfalseDisables the trigger button
asChildbooleanfalseRender as child element instead of a button

ItemContent Props

PropTypeDefaultDescription
forceMountbooleanfalseKeep content mounted in the DOM even when closed
asChildbooleanfalseRender as child element

ItemIndicator Props

PropTypeDefaultDescription
rotateOnOpenbooleantrueWhether the indicator rotates when the item is open
asChildbooleanfalseReplace the default ChevronDown with a custom element

Accessibility

Adheres to the Accordion WAI-ARIA design pattern.

Keyboard Interactions

KeyDescription
SpaceWhen focus is on an Accordion.ItemTrigger of a collapsed section, expands the section.
EnterWhen focus is on an Accordion.ItemTrigger of a collapsed section, expands the section.
TabMoves focus to the next focusable element.
Shift + TabMoves focus to the previous focusable element.
ArrowDownMoves focus to the next Accordion.ItemTrigger.
ArrowUpMoves focus to the previous Accordion.ItemTrigger.
HomeWhen focus is on an Accordion.ItemTrigger, moves focus to the first Accordion.ItemTrigger.
EndWhen focus is on an Accordion.ItemTrigger, moves focus to the last Accordion.ItemTrigger.

Built with ❤️ by the carbonteq team. The source code is available on GitHub.

© 2026 Pallas UI. All rights reserved.

Yes. It adheres to the WAI-ARIA design pattern.

default

Yes. It adheres to the WAI-ARIA design pattern.

subtle

Yes. It adheres to the WAI-ARIA design pattern.

bordered

Yes. It adheres to the WAI-ARIA design pattern.

plain

Yes. It adheres to the WAI-ARIA design pattern.

sm

Yes. It adheres to the WAI-ARIA design pattern.

md

Yes. It adheres to the WAI-ARIA design pattern.

lg

Yes. It adheres to the WAI-ARIA design pattern.

Yes. It adheres to the WAI-ARIA design pattern.

Yes. It comes with default styles that match the other components\u2019 aesthetic.

Yes. It adheres to the WAI-ARIA design pattern.

Yes. It adheres to the WAI-ARIA design pattern.