# Accordion

> Stack of collapsible sections, one open at a time or several, with a rotating chevron and animated height. Wraps Base UI Accordion.

Source: https://docs.nasaqui.com/components/accordion

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/accordion.json
```

A vertical list of headings that each reveal a panel. By default opening one closes the others; with `multiple`
any number can stay open. The panel animates height and opacity over 200ms, the same motion as `Collapsible`.

## When to use

- FAQs, settings groups, and long content the user scans by heading.

## When not to use

- One independent show/hide: use `Collapsible`.
- Switching between peer views: use `Tabs`.

## Import

```tsx
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "@fadymondy/nasaq/web";

export function Faq() {
  return (
    <Accordion defaultValue={["plan"]}>
      <AccordionItem value="plan">
        <AccordionTrigger>Can I change my plan later?</AccordionTrigger>
        <AccordionPanel>Yes, any time from the billing page.</AccordionPanel>
      </AccordionItem>
      <AccordionItem value="pay">
        <AccordionTrigger>Which payment methods do you accept?</AccordionTrigger>
        <AccordionPanel>Mada, Visa and Mastercard.</AccordionPanel>
      </AccordionItem>
    </Accordion>
  );
}
```

## Anatomy

```
<Accordion>            data-slot="accordion"
└─ <AccordionItem>     data-slot="accordion-item"
   ├─ <AccordionTrigger>  data-slot="accordion-trigger" (inside accordion-header), data-panel-open when open
   └─ <AccordionPanel>    data-slot="accordion-panel"
```

## API

### Accordion

All Base UI `Accordion.Root` props:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `multiple` | `boolean` | `false` | Allow several open panels. |
| `value` / `defaultValue` | `string[]` | none | Values of the open items. Always an array. |
| `onValueChange` | `(value, details) => void` | none | Called when the open set changes. |
| `disabled` | `boolean` | `false` | Disable every item. |
| `keepMounted` | `boolean` | `false` | Keep closed panels in the DOM. |
| `hiddenUntilFound` | `boolean` | `false` | Let browser find-in-page open panels. |
| `loopFocus` | `boolean` | `true` | Wrap arrow-key focus at the ends. |

### AccordionItem

Base UI `Accordion.Item`: `value` (required to control it), `disabled`.

### AccordionTrigger / AccordionPanel

Base UI `Trigger` and `Panel` props. The trigger adds the chevron; the panel wraps children in a padded block.

## Examples

Several open, in Arabic:

```tsx
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "@fadymondy/nasaq/web";

export function SettingsAr() {
  return (
    <Accordion multiple defaultValue={["n", "l"]}>
      <AccordionItem value="n">
        <AccordionTrigger>الإشعارات</AccordionTrigger>
        <AccordionPanel>اختر متى نراسلك.</AccordionPanel>
      </AccordionItem>
      <AccordionItem value="l">
        <AccordionTrigger>اللغة</AccordionTrigger>
        <AccordionPanel>العربية أو الإنجليزية.</AccordionPanel>
      </AccordionItem>
    </Accordion>
  );
}
```

## Accessibility

| Key | Action |
| --- | --- |
| Tab | Moves between triggers. |
| Enter / Space | Toggles the focused panel. |
| ArrowDown / ArrowUp | Moves focus to the next / previous trigger. |
| Home / End | First / last trigger. |

- Triggers are buttons inside headings with `aria-expanded` and `aria-controls`. Localise the trigger text.

## RTL & i18n

The title sits at the inline start and the chevron at the inline end. The chevron points down and rotates 180 degrees, so it never needs mirroring.

## Styling & tokens

`border-border`, `bg-card`, `hover:bg-nq-hover`, focus ring `nq-focus`, `text-muted-foreground` panel text. State attributes:
`data-panel-open` (trigger), `data-open`, `data-disabled`. `className` merges onto each part. Reduced motion turns the animation off.

## Do / Don't

- Do write trigger titles as questions or short nouns.
- Don't hide content the user must see to complete a task.

## Related

[collapsible](https://docs.nasaqui.com/components/collapsible), [tabs](https://docs.nasaqui.com/components/tabs).

## Lab

https://docs.nasaqui.com/?path=/docs/components-layout-accordion--docs

## Code

### React

```tsx
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "@fadymondy/nasaq/web";

export function Faq() {
  return (
    <Accordion defaultValue={["plan"]}>
      <AccordionItem value="plan">
        <AccordionTrigger>Can I change my plan later?</AccordionTrigger>
        <AccordionPanel>Yes, any time from the billing page.</AccordionPanel>
      </AccordionItem>
      <AccordionItem value="pay">
        <AccordionTrigger>Which payment methods do you accept?</AccordionTrigger>
        <AccordionPanel>Mada, Visa and Mastercard.</AccordionPanel>
      </AccordionItem>
    </Accordion>
  );
}
```

### shadcn

```tsx
import { Accordion, AccordionItem, AccordionPanel, AccordionTrigger } from "@/components/ui/accordion";

export function Faq() {
  return (
    <Accordion defaultValue={["plan"]}>
      <AccordionItem value="plan">
        <AccordionTrigger>Can I change my plan later?</AccordionTrigger>
        <AccordionPanel>Yes, any time from the billing page.</AccordionPanel>
      </AccordionItem>
      <AccordionItem value="pay">
        <AccordionTrigger>Which payment methods do you accept?</AccordionTrigger>
        <AccordionPanel>Mada, Visa and Mastercard.</AccordionPanel>
      </AccordionItem>
    </Accordion>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqAccordion, NqAccordionItem, NqAccordionPanel, NqAccordionTrigger } from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqAccordion :default-value="['plan']">
    <NqAccordionItem value="plan">
      <NqAccordionTrigger>Can I change my plan later?</NqAccordionTrigger>
      <NqAccordionPanel>Yes, any time from the billing page.</NqAccordionPanel>
    </NqAccordionItem>
    <NqAccordionItem value="pay">
      <NqAccordionTrigger>Which payment methods do you accept?</NqAccordionTrigger>
      <NqAccordionPanel>Mada, Visa and Mastercard.</NqAccordionPanel>
    </NqAccordionItem>
  </NqAccordion>
</template>
```

### Blade

```blade
<x-nq::accordion :default-value="['plan']">
    <x-nq::accordion.item value="plan">
        <x-nq::accordion.trigger>Can I change my plan later?</x-nq::accordion.trigger>
        <x-nq::accordion.panel>Yes, any time from the billing page.</x-nq::accordion.panel>
    </x-nq::accordion.item>
    <x-nq::accordion.item value="pay">
        <x-nq::accordion.trigger>Which payment methods do you accept?</x-nq::accordion.trigger>
        <x-nq::accordion.panel>Mada, Visa and Mastercard.</x-nq::accordion.panel>
    </x-nq::accordion.item>
</x-nq::accordion>
```

### HTML + Alpine

```html
<div data-slot="accordion" x-data="nqAccordion(JSON.parse('[\u0022plan\u0022]'), false)" x-modelable="value" x-id="['nq-accordion']"
    x-on:keydown="onKeydown($event)"
        class="flex w-full flex-col rounded-card border border-border bg-card">
    <div data-slot="accordion-item" x-data="{ v: 'plan' }"
    :data-open="isOpen(v) ? '' : undefined" :data-closed="isOpen(v) ? undefined : ''"
     data-open         class="border-b border-border first:rounded-t-card last:rounded-b-card last:border-b-0">
    <h3 data-slot="accordion-header" class="m-0 flex">
    <button type="button" data-slot="accordion-trigger" x-on:click="toggle(v)"
        :id="$id('nq-accordion', 'trigger-' + v)" :aria-controls="$id('nq-accordion', 'panel-' + v)"
        :aria-expanded="isOpen(v)" :data-panel-open="isOpen(v) ? '' : undefined"
        aria-expanded="true"  data-panel-open                 class="group flex w-full items-center justify-between gap-3 px-4 py-3 text-start text-label text-foreground outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50">
        Can I change my plan later?
        <svg data-slot="icon" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground transition-transform duration-200 ease-nq motion-reduce:transition-none group-data-panel-open:rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg>    </button>
</h3>
        <div data-slot="accordion-panel" role="region" x-nq-presence="isOpen(v)"
    :id="$id('nq-accordion', 'panel-' + v)" :aria-labelledby="$id('nq-accordion', 'trigger-' + v)"
     data-open     class="h-(--accordion-panel-height) overflow-hidden text-body-sm text-muted-foreground transition-[height,opacity] duration-200 ease-nq motion-reduce:transition-none data-starting-style:h-0 data-starting-style:opacity-0 data-ending-style:h-0 data-ending-style:opacity-0">
    <div class="px-4 pb-4">Yes, any time from the billing page.</div>
</div>
</div>
    <div data-slot="accordion-item" x-data="{ v: 'pay' }"
    :data-open="isOpen(v) ? '' : undefined" :data-closed="isOpen(v) ? undefined : ''"
     data-closed         class="border-b border-border first:rounded-t-card last:rounded-b-card last:border-b-0">
    <h3 data-slot="accordion-header" class="m-0 flex">
    <button type="button" data-slot="accordion-trigger" x-on:click="toggle(v)"
        :id="$id('nq-accordion', 'trigger-' + v)" :aria-controls="$id('nq-accordion', 'panel-' + v)"
        :aria-expanded="isOpen(v)" :data-panel-open="isOpen(v) ? '' : undefined"
        aria-expanded="false"                 class="group flex w-full items-center justify-between gap-3 px-4 py-3 text-start text-label text-foreground outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-nq-focus data-disabled:pointer-events-none data-disabled:opacity-50">
        Which payment methods do you accept?
        <svg data-slot="icon" aria-hidden="true" class="size-4 shrink-0 text-muted-foreground transition-transform duration-200 ease-nq motion-reduce:transition-none group-data-panel-open:rotate-180" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m6 9 6 6 6-6"/>
</svg>    </button>
</h3>
        <div data-slot="accordion-panel" role="region" x-nq-presence="isOpen(v)"
    :id="$id('nq-accordion', 'panel-' + v)" :aria-labelledby="$id('nq-accordion', 'trigger-' + v)"
     data-closed style="display:none"     class="h-(--accordion-panel-height) overflow-hidden text-body-sm text-muted-foreground transition-[height,opacity] duration-200 ease-nq motion-reduce:transition-none data-starting-style:h-0 data-starting-style:opacity-0 data-ending-style:h-0 data-ending-style:opacity-0">
    <div class="px-4 pb-4">Mada, Visa and Mastercard.</div>
</div>
</div>
</div>
```
