# Collapsible

Displays an interactive disclosure region that expands and collapses inline content.

Use Collapsible for settings drawers, detail rows, compact status cards, and nested explorers where content should stay in the same document flow.

## Import

```ts
import {
  CollapsibleComponent,
  CollapsibleContentComponent,
  CollapsibleTriggerDirective,
} from '@edsis/component/collapsible';
```

## Composition

The Angular composition follows the shadcn and Radix structure while using a root component, a trigger directive on a native button, and a content component.

```text
Collapsible
├── button[CollapsibleTrigger]
└── CollapsibleContent
```

## Basic usage

Bind `[(open)]` when the parent should control the disclosure state or seed a default open panel.

```ts
readonly detailsOpen = signal(false);
```

```html
<Collapsible [(open)]="detailsOpen" class="w-full max-w-md rounded-lg border border-border p-3">
  <button
    CollapsibleTrigger
    class="inline-flex w-full items-center justify-between gap-2 text-left text-sm font-medium"
  >
    Can I use this in my project?
    <span aria-hidden="true">+</span>
  </button>

  <CollapsibleContent class="pt-3 text-sm text-muted-foreground">
    Yes. The trigger and content follow the disclosure ARIA pattern and stay in normal layout flow.
  </CollapsibleContent>
</Collapsible>
```

## Common patterns

### Controlled state

Use a signal boolean with `[(open)]` when another control needs to observe or update the open state.

```ts
readonly isOpen = signal(false);

toggleFromElsewhere(): void {
  this.isOpen.update((value) => !value);
}
```

### Button composition

`button[CollapsibleTrigger]` is a directive, so it can compose with the local button primitive on the same element.

```html
<Collapsible [(open)]="basicOpen" class="rounded-md border border-border p-2">
  <button Button CollapsibleTrigger variant="ghost" class="w-full justify-between px-2">
    Product details
    <svg
      aria-hidden="true"
      class="h-4 w-4"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      stroke-width="2"
    >
      <polyline points="6 9 12 15 18 9" />
    </svg>
  </button>

  <CollapsibleContent class="px-2 pb-2 pt-1 text-sm text-muted-foreground">
    This panel can reveal additional details without leaving the page.
  </CollapsibleContent>
</Collapsible>
```

### Settings drawer

Wrap the trigger and content inside a card-like surface when the disclosure belongs to a small settings editor.

```html
<Collapsible [(open)]="settingsOpen" class="rounded-lg border border-border p-4">
  <div class="flex items-start gap-3">
    <div class="grid flex-1 grid-cols-2 gap-2">
      <input Input placeholder="Radius X" />
      <input Input placeholder="Radius Y" />
      <CollapsibleContent class="col-span-full grid grid-cols-2 gap-2 pt-0">
        <input Input placeholder="Blur" />
        <input Input placeholder="Spread" />
      </CollapsibleContent>
    </div>

    <button
      Button
      CollapsibleTrigger
      variant="outline"
      size="icon"
      aria-label="Toggle advanced fields"
    >
      <span aria-hidden="true">...</span>
    </button>
  </div>
</Collapsible>
```

### Nested file tree

Nested `Collapsible` roots work well for compact explorers and outline views.

```html
<Collapsible [(open)]="componentsOpen">
  <button CollapsibleTrigger class="inline-flex items-center gap-2 text-sm font-medium">
    components
  </button>

  <CollapsibleContent class="ml-5 mt-2 flex flex-col gap-1">
    <Collapsible [(open)]="uiOpen">
      <button CollapsibleTrigger class="inline-flex items-center gap-2 text-sm font-medium">
        ui
      </button>
      <CollapsibleContent class="ml-5 mt-2 flex flex-col gap-1 text-sm text-muted-foreground">
        <span>button.ts</span>
        <span>collapsible.ts</span>
      </CollapsibleContent>
    </Collapsible>
  </CollapsibleContent>
</Collapsible>
```

### RTL

For right-to-left interfaces, set `dir="rtl"` on a wrapping container or the collapsible root.

```html
<section dir="rtl" lang="ar" class="max-w-md text-right">
  <Collapsible [(open)]="rtlOpen" class="flex flex-col gap-2">
    <button
      CollapsibleTrigger
      class="inline-flex items-center justify-between gap-2 text-sm font-medium"
    >
      تبديل التفاصيل
    </button>
    <CollapsibleContent class="flex flex-col gap-2 text-sm">
      <div class="rounded-md border border-border px-4 py-2">عنوان الشحن</div>
      <div class="rounded-md border border-border px-4 py-2">2x سماعات الاستوديو</div>
    </CollapsibleContent>
  </Collapsible>
</section>
```

## API reference

### `CollapsibleComponent`

| Input          | Type      | Default |
| -------------- | --------- | ------- |
| `open` (model) | `boolean` | `false` |
| `disabled`     | `boolean` | `false` |
| `class`        | `string`  | `''`    |

### `CollapsibleContentComponent`

| Input        | Type      | Default |
| ------------ | --------- | ------- |
| `forceMount` | `boolean` | `false` |
| `class`      | `string`  | `''`    |

### Parts

- `button[CollapsibleTrigger]` is the interactive control. It manages `aria-expanded`, `aria-controls`, `data-state`, and root toggling.
- `CollapsibleContent` is the panel region. It applies `role="region"`, `aria-labelledby`, `data-state`, and optional persistent projection via `forceMount`.
- Lower-level behavior follows the Radix Collapsible model: <https://www.radix-ui.com/primitives/docs/components/collapsible#api-reference>.

## Styling and theming

Pass `class` to the root or content, and use the native `class` attribute on the trigger button. The root and content expose `data-state="open" | "closed"` so surrounding styles or transitions can react to the current disclosure state.

Use theme tokens such as `border-border`, `bg-card`, `text-muted-foreground`, and spacing utilities to match the rest of the library.

## Accessibility

- The primitive follows the disclosure WAI-ARIA pattern.
- Trigger is a native button, so Enter and Space work without extra key handling.
- Trigger receives `aria-controls` and `aria-expanded`; content receives `role="region"` and `aria-labelledby`.
- `disabled` keeps the control visible while preventing interaction.

## Keyboard interactions

- `Enter` toggles the collapsible.
- `Space` toggles the collapsible.
- Tab order follows the DOM order of the trigger and any focusable controls inside the content.

## Angular notes

- `[(open)]` is the Angular equivalent of shadcn's `open` and `onOpenChange` props.
- `button[CollapsibleTrigger]` is a directive, not a component, so it can compose with `button[Button]` on the same element.
- `forceMount` keeps projected content rendered even when the panel is closed, which is useful for measuring or animating content without re-creating it.
- The local API intentionally does not add an `asChild` prop; Angular composition is handled through selectors and host directives instead.

## Source parity

This Angular implementation follows the shadcn Collapsible structure and examples while translating the API to standalone Angular imports, signal-backed state, button-directive composition, and Angular-friendly RTL guidance.
