# Accordion

A stack of headings that each expand to reveal a section of content.

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

function AccordionDemo() {
  return (
    <Accordion defaultValue={["summary"]} className="max-w-md">
      <AccordionItem value="summary">
        <AccordionTrigger>What happened</AccordionTrigger>
        <AccordionContent>
          <p>
            A lookalike domain, acme-login.co, was registered on 21 October and
            serves a copy of the Acme sign-in page.
          </p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="impact">
        <AccordionTrigger>Who is affected</AccordionTrigger>
        <AccordionContent>
          <p>
            Employees and customers who sign in at acme.com. No credentials have
            been observed in leak sources yet.
          </p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="action">
        <AccordionTrigger>Recommended action</AccordionTrigger>
        <AccordionContent>
          <p>
            Request a takedown from the registrar and add the domain to the
            email gateway block list.
          </p>
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}
```

## Usage

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

```tsx
<Accordion defaultValue={["summary"]}>
  <AccordionItem value="summary">
    <AccordionTrigger>What happened</AccordionTrigger>
    <AccordionContent>A lookalike domain was registered.</AccordionContent>
  </AccordionItem>
</Accordion>
```

Use an accordion to shorten a long page of secondary detail: alert explanations, remediation
steps, settings grouped by topic. The value is always an array, even when only one item can be
open. Give every item a stable `value` so you can open it from `defaultValue` or control it
with `value` and `onValueChange`.

Do not hide information the user needs to act on. For a single show/hide region, use
[Collapsible](/components/collapsible). To switch between views of equal weight, use
[Tabs](/components/tabs).

## Examples

### Multiple open items

By default, opening an item closes the others. Set `multiple` to let several stay open, for
example when the user compares groups of findings.

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

function AccordionMultiple() {
  return (
    <Accordion multiple defaultValue={["web", "mail"]} className="max-w-md">
      <AccordionItem value="web">
        <AccordionTrigger>Web servers (12)</AccordionTrigger>
        <AccordionContent>
          <p>4 hosts expose TLS 1.0. 2 certificates expire within 30 days.</p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="mail">
        <AccordionTrigger>Mail servers (3)</AccordionTrigger>
        <AccordionContent>
          <p>SPF and DMARC are configured. DKIM is missing on mx2.acme.com.</p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="dns">
        <AccordionTrigger>DNS servers (2)</AccordionTrigger>
        <AccordionContent>
          <p>No findings in the last scan.</p>
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}
```

### Disabled item

Disable an item whose content is not ready yet. Say why in the trigger label.

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

function AccordionDisabledItem() {
  return (
    <Accordion className="max-w-md">
      <AccordionItem value="detection">
        <AccordionTrigger>Detection rule</AccordionTrigger>
        <AccordionContent>
          <p>Typosquatting, edit distance 2 from a monitored domain.</p>
        </AccordionContent>
      </AccordionItem>
      <AccordionItem value="evidence" disabled>
        <AccordionTrigger>Evidence (processing)</AccordionTrigger>
        <AccordionContent>
          <p>Screenshots and WHOIS records.</p>
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  )
}
```

## Accessibility

- Each trigger is a button inside a heading, with `aria-expanded` and `aria-controls` pointing
  to its panel. Arrow keys move focus between triggers; Enter and Space toggle the item.
- The heading is always an `<h3>`. Place the accordion where an `<h3>` fits the outline of
  the page, under an `<h2>`.
- Closed panels are unmounted by default, so the browser's find-in-page skips them. Set
  `hiddenUntilFound` on `Accordion` when users need to search the hidden text.

## API reference

`import { ... } from "@zenoxai/ui/components/accordion"`

### Accordion

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| defaultValue | `AccordionValue<any>` |  | The uncontrolled value of the item(s) that should be initially expanded.  To render a controlled accordion, use the `value` prop instead. |
| disabled | `boolean` | `false` | Whether the component should ignore user interaction. |
| hiddenUntilFound | `boolean` | `false` | Allows the browser's built-in page search to find and expand the panel contents.  Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM. |
| keepMounted | `boolean` | `false` | Whether to keep the element in the DOM while the panel is closed. This prop is ignored when `hiddenUntilFound` is used. |
| loopFocus | `boolean` |  | Deprecated following the [APG guidance update](https://github.com/w3c/aria-practices/pull/3434) to remove roving focus.  This prop no longer affects keyboard focus behavior. @deprecated |
| multiple | `boolean` | `false` | Whether multiple items can be open at the same time. |
| onValueChange | `((value: AccordionValue<any>, eventDetails: AccordionRootChangeEventDetails) => void)` |  | Event handler called when an accordion item is expanded or collapsed. Provides the new value as an argument. |
| orientation | `"horizontal" \| "vertical"` | `'vertical'` | Deprecated following the [APG guidance update](https://github.com/w3c/aria-practices/pull/3434) to remove roving focus.  This prop no longer affects keyboard focus behavior. @deprecated |
| render | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, State<any>>` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |
| value | `AccordionValue<any>` |  | The controlled value of the item(s) that should be expanded.  To render an uncontrolled accordion, use the `defaultValue` prop instead. |

### AccordionItem

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| disabled | `boolean` | `false` | Whether the component should ignore user interaction. |
| onOpenChange | `((open: boolean, eventDetails: AccordionItemChangeEventDetails) => void)` |  | Event handler called when the panel is opened or closed. |
| render | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, AccordionItemState>` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |
| value | `any` |  | A unique value that identifies this accordion item. If no value is provided, a unique ID will be generated automatically. Use when controlling the accordion programmatically, or to set an initial open state. @example ```tsx <Accordion.Root value={['a']}>   <Accordion.Item value="a" /> // initially open   <Accordion.Item value="b" /> // initially closed </Accordion.Root> ``` |

### AccordionTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| nativeButton | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| render | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, AccordionTriggerState>` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

### AccordionContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| hiddenUntilFound | `boolean` | `false` | Allows the browser's built-in page search to find and expand the panel contents.  Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM. |
| keepMounted | `boolean` | `false` | Whether to keep the element in the DOM while the panel is closed. This prop is ignored when `hiddenUntilFound` is used. |
| render | `ReactElement<unknown, string \| JSXElementConstructor<any>> \| ComponentRenderFn<HTMLProps, AccordionPanelState>` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

