YaVendio Registry
Components

YA Accordion

A collapsible accordion component for organizing content into expandable sections

The YaAccordion component provides an accessible way to organize content into collapsible sections. It supports single and multiple open items, with smooth animations and keyboard navigation.

Quick Start

pnpm dlx shadcn@latest add @yavendio/ya-accordion
npx shadcn@latest add @yavendio/ya-accordion
yarn dlx shadcn@latest add @yavendio/ya-accordion
import {
  YaAccordion,
  YaAccordionItem,
  YaAccordionTrigger,
  YaAccordionContent,
} from '@/components/ui/ya-accordion'

export default function Example() {
  return (
    <YaAccordion type="single" collapsible>
      <YaAccordionItem value="item-1">
        <YaAccordionTrigger>Is it accessible?</YaAccordionTrigger>
        <YaAccordionContent>
          Yes. It adheres to the WAI-ARIA design pattern.
        </YaAccordionContent>
      </YaAccordionItem>
    </YaAccordion>
  )
}

Basic Usage

<YaAccordion type="single" collapsible className="w-full">
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Product Information</YaAccordionTrigger>
    <YaAccordionContent>
      <p className="mb-4">
        Our flagship product combines cutting-edge technology with sleek design. Built with
        premium materials, it offers unparalleled performance and reliability.
      </p>
      <p>
        Key features include advanced processing capabilities, and an intuitive user interface
        designed for both beginners and experts.
      </p>
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2">
    <YaAccordionTrigger>Shipping Details</YaAccordionTrigger>
    <YaAccordionContent>
      <p className="mb-4">
        We offer worldwide shipping through trusted courier partners. Standard delivery takes
        3-5 business days, while express shipping ensures delivery within 1-2 business days.
      </p>
      <p>
        All orders are carefully packaged and fully insured. Track your shipment in real-time
        through our dedicated tracking portal.
      </p>
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-3">
    <YaAccordionTrigger>Return Policy</YaAccordionTrigger>
    <YaAccordionContent>
      <p className="mb-4">
        We stand behind our products with a comprehensive 30-day return policy. If you're not
        completely satisfied, simply return the item in its original condition.
      </p>
      <p>
        Our hassle-free return process includes free return shipping and full refunds processed
        within 48 hours of receiving the returned item.
      </p>
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Visual Types

YaAccordion comes with three visual types for different use cases:

TypeDescriptionUsage
cardBorder with shadow when openFAQs, content sections, documentation
folderCompact with icon, badge, and actionsFile managers, navigation trees
simpleMinimal with no borderDropdown menus, inline expansion

Card Type

Folder Type

Simple Type

// Card Type
<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1" type="card">
    <YaAccordionTrigger>Accordion title</YaAccordionTrigger>
    <YaAccordionContent>Content here</YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

// Folder Type
<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1" type="folder">
    <YaAccordionTrigger leftIcon={<FolderOpen />} badge="99">
      Accordion title
    </YaAccordionTrigger>
    <YaAccordionContent>Items list</YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

// Simple Type
<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1" type="simple">
    <YaAccordionTrigger>Accordion title</YaAccordionTrigger>
    <YaAccordionContent>Content here</YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Behavior Types

Single Type

Only one item can be open at a time. The collapsible prop allows closing all items.

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Is it accessible?</YaAccordionTrigger>
    <YaAccordionContent>
      Yes. It adheres to the WAI-ARIA design pattern.
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2">
    <YaAccordionTrigger>Is it styled?</YaAccordionTrigger>
    <YaAccordionContent>
      Yes. It comes with default styles that matches the YaVendio Design System.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Multiple Type

Multiple items can be open simultaneously.

<YaAccordion type="multiple">
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>General Information</YaAccordionTrigger>
    <YaAccordionContent>
      This accordion allows multiple items to be open at the same time.
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2">
    <YaAccordionTrigger>Technical Details</YaAccordionTrigger>
    <YaAccordionContent>
      The multiple type is controlled by the type="multiple" prop.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Collapsible Behavior

Control whether all items can be closed or if at least one must remain open.

With collapsible (can close all items)

Without collapsible (always one open)

No. Without collapsible prop, at least one item must remain open.

// With collapsible - can close all items
<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Can I close this?</YaAccordionTrigger>
    <YaAccordionContent>
      Yes! Click the trigger again to close this item.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

// Without collapsible - always one open
<YaAccordion type="single" defaultValue="item-1">
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Can I close this?</YaAccordionTrigger>
    <YaAccordionContent>
      No. At least one item must remain open.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Default Value

Set which item is open by default using the defaultValue prop.

This item is open by default using defaultValue="item-2"

<YaAccordion type="single" collapsible defaultValue="item-2">
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>First Item</YaAccordionTrigger>
    <YaAccordionContent>This item starts closed.</YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2">
    <YaAccordionTrigger>Second Item (Default Open)</YaAccordionTrigger>
    <YaAccordionContent>This item is open by default.</YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

States

Controlled State

Use the value and onValueChange props for controlled behavior.

Currently open: item-1

Content for section 1

'use client'

import { useState } from 'react'
import { YaAccordion, YaAccordionItem, YaAccordionTrigger, YaAccordionContent } from '@/components/ui/ya-accordion'

export default function ControlledAccordion() {
  const [value, setValue] = useState('item-1')

  return (
    <>
      <p>Currently open: {value || 'None'}</p>
      <YaAccordion type="single" collapsible value={value} onValueChange={setValue}>
        <YaAccordionItem value="item-1">
          <YaAccordionTrigger>Section 1</YaAccordionTrigger>
          <YaAccordionContent>Content for section 1</YaAccordionContent>
        </YaAccordionItem>
        <YaAccordionItem value="item-2">
          <YaAccordionTrigger>Section 2</YaAccordionTrigger>
          <YaAccordionContent>Content for section 2</YaAccordionContent>
        </YaAccordionItem>
      </YaAccordion>
    </>
  )
}

Disabled State

Disable individual accordion items using the disabled prop.

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Available Section</YaAccordionTrigger>
    <YaAccordionContent>This section is fully interactive.</YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2" disabled>
    <YaAccordionTrigger>Disabled Section</YaAccordionTrigger>
    <YaAccordionContent>This content cannot be accessed.</YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Folder Type

The folder type is designed for hierarchical navigation and file management interfaces.

Basic Folder

import { FolderOpen } from 'lucide-react'

<YaAccordion type="single" collapsible className="space-y-2">
  <YaAccordionItem value="item-1" type="folder">
    <YaAccordionTrigger leftIcon={<FolderOpen />} badge="3">
      AI Research Topics
    </YaAccordionTrigger>
    <YaAccordionContent>
      <div className="space-y-2">
        <div className="text-sm">Item 1: The Evolution of AI</div>
        <div className="text-sm">Item 2: Ethical Considerations</div>
        <div className="text-sm">Item 3: Applications in Healthcare</div>
      </div>
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2" type="folder">
    <YaAccordionTrigger leftIcon={<FolderOpen />}>
      Empty Folder
    </YaAccordionTrigger>
    <YaAccordionContent>
      <div className="text-sm text-muted-foreground">No items yet</div>
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Folder with Actions

import { FolderOpen, MoreVertical } from 'lucide-react'

<YaAccordion type="single" collapsible className="space-y-2">
  <YaAccordionItem value="item-1" type="folder">
    <YaAccordionTrigger
      leftIcon={<FolderOpen />}
      badge="12"
      actions={
        <div
          role="button"
          tabIndex={0}
          className="hover:opacity-70 cursor-pointer"
          onClick={(e) => e.stopPropagation()}
          onKeyDown={(e) => {
            if (e.key === 'Enter' || e.key === ' ') {
              e.stopPropagation()
            }
          }}
        >
          <MoreVertical className="size-4" />
        </div>
      }
    >
      Project Files
    </YaAccordionTrigger>
    <YaAccordionContent>
      <div className="space-y-2">
        <div className="text-sm">📄 README.md</div>
        <div className="text-sm">📄 package.json</div>
      </div>
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Actions: Use <div role="button"> instead of <button> to avoid nested button issues. Always use onClick={(e) => e.stopPropagation() and handle keyboard events with onKeyDown for accessibility.

Simple Type

The simple type provides a minimal, unobtrusive accordion for inline content expansion.

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1" type="simple">
    <YaAccordionTrigger>What is Next.js?</YaAccordionTrigger>
    <YaAccordionContent>
      Next.js is a React framework that provides building blocks to create web applications.
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="item-2" type="simple">
    <YaAccordionTrigger>What is React?</YaAccordionTrigger>
    <YaAccordionContent>
      React is a JavaScript library for building user interfaces.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Examples

FAQ Section

<YaAccordion type="single" collapsible className="w-full">
  <YaAccordionItem value="faq-1">
    <YaAccordionTrigger>What payment methods do you accept?</YaAccordionTrigger>
    <YaAccordionContent>
      We accept all major credit cards, PayPal, and bank transfers for orders over $500.
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="faq-2">
    <YaAccordionTrigger>How long does shipping take?</YaAccordionTrigger>
    <YaAccordionContent>
      Standard shipping takes 3-5 business days. Express and overnight options available.
    </YaAccordionContent>
  </YaAccordionItem>
  <YaAccordionItem value="faq-3">
    <YaAccordionTrigger>What is your return policy?</YaAccordionTrigger>
    <YaAccordionContent>
      We offer a 30-day money-back guarantee. Items must be in original condition.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

With Action Buttons

import { YaButton } from '@/components/ui/ya-button'

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Account Settings</YaAccordionTrigger>
    <YaAccordionContent>
      <div className="space-y-4">
        <p>Manage your account preferences and settings.</p>
        <div className="flex gap-2">
          <YaButton variant="secondary" size="sm">Edit Profile</YaButton>
          <YaButton variant="tertiary" size="sm">Change Password</YaButton>
        </div>
      </div>
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Nested Accordions

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>Level 1: Main Category</YaAccordionTrigger>
    <YaAccordionContent>
      <p className="mb-4">This is the main category content.</p>
      <YaAccordion type="single" collapsible className="border-l-2 border-primary pl-4">
        <YaAccordionItem value="nested-1">
          <YaAccordionTrigger>Level 2: Subcategory A</YaAccordionTrigger>
          <YaAccordionContent>Content for subcategory A</YaAccordionContent>
        </YaAccordionItem>
        <YaAccordionItem value="nested-2">
          <YaAccordionTrigger>Level 2: Subcategory B</YaAccordionTrigger>
          <YaAccordionContent>Content for subcategory B</YaAccordionContent>
        </YaAccordionItem>
      </YaAccordion>
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Props

YaAccordion

PropTypeDefaultDescription
type'single' | 'multiple'requiredWhether one or multiple items can be open
collapsiblebooleanfalseAllow closing all items (single type only)
defaultValuestring | string[]-Default open item(s) (uncontrolled)
valuestring | string[]-Controlled open item(s)
onValueChange(value: string | string[]) => void-Callback when open items change
disabledbooleanfalseDisable all items
classNamestring-Additional classes

YaAccordionItem

PropTypeDefaultDescription
valuestringrequiredUnique value for the item
type'card' | 'folder' | 'simple''card'Visual style type
disabledbooleanfalseDisable this item
classNamestring-Additional classes

YaAccordionTrigger

PropTypeDefaultDescription
leftIconReactNode-Icon on the left (folder type)
badgestring | number-Badge counter (folder type)
actionsReactNode-Action buttons (folder type)
classNamestring-Additional classes
childrenReactNode-Trigger content

YaAccordionContent

PropTypeDefaultDescription
classNamestring-Additional classes
forceMountbooleanfalseKeep content mounted when hidden
childrenReactNode-Content to display

Accessibility

<YaAccordion type="single" collapsible>
  <YaAccordionItem value="item-1">
    <YaAccordionTrigger>
      What is your refund policy?
    </YaAccordionTrigger>
    <YaAccordionContent>
      We offer full refunds within 30 days of purchase.
    </YaAccordionContent>
  </YaAccordionItem>
</YaAccordion>

Best Practices

DoDon't
Use descriptive, concise trigger textGeneric labels like "Item 1", "Section A"
Group related content in single itemsToo many nested levels (max 2)
Use single type for FAQsMultiple type for simple Q&A
Keep content scannableVery long content blocks
Provide default open for important infoHide critical information

TypeScript

import { type VariantProps } from 'class-variance-authority'
import { yaAccordionItemVariants } from '@/components/ui/ya-accordion'

type AccordionItemType = VariantProps<typeof yaAccordionItemVariants>['type']

interface MyComponentProps {
  accordionType?: AccordionItemType
}

On this page