---
title: Collapsible
description: An interactive component which expands/collapses a panel.
---

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/collapsible"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
)

templ CollapsibleDemo() {
	@collapsible.Collapsible(collapsible.Props{Class: "flex w-[350px] flex-col gap-2"}) {
		<div class="flex items-center justify-between gap-4 px-4">
			<h4 class="text-sm font-semibold">Order #4189</h4>
			@button.Button(button.Props{
				Variant:    button.VariantGhost,
				Size:       button.SizeIcon,
				Class:      "size-8",
				Attributes: collapsible.Trigger(ctx),
			}) {
				@icon.ChevronsUpDown()
				<span class="sr-only">Toggle details</span>
			}
		</div>
		<div class="flex items-center justify-between rounded-md border px-4 py-2 text-sm">
			<span class="text-muted-foreground">Status</span>
			<span class="font-medium">Shipped</span>
		</div>
		@collapsible.Content(collapsible.ContentProps{Class: "flex flex-col gap-2"}) {
			<div class="rounded-md border px-4 py-2 text-sm">
				<p class="font-medium">Shipping address</p>
				<p class="text-muted-foreground">100 Market St, San Francisco</p>
			</div>
			<div class="rounded-md border px-4 py-2 text-sm">
				<p class="font-medium">Items</p>
				<p class="text-muted-foreground">2x Studio Headphones</p>
			</div>
		}
	}
}
```

## Installation

<CodeTabs>

<TabsList>
  <TabsTrigger value="cli">Command</TabsTrigger>
  <TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">

```bash
shadcn-templ add collapsible
```

</TabsContent>

<TabsContent value="manual">

<Steps className="mb-0 pt-2">

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="collapsible" title="components/collapsible/collapsible.templ" />

<ComponentSource name="collapsible" title="components/collapsible/collapsible.js" />

Component scripts are loaded through the shared script bundle, see [JavaScript](/docs/installation#javascript).

<Step>Update the import paths to match your project setup.</Step>

</Steps>

</TabsContent>

</CodeTabs>

## Usage

```go showLineNumbers
import "github.com/axadrn/shadcn-templ/v2/components/collapsible"
```

```templ showLineNumbers
@collapsible.Collapsible() {
	@button.Button(button.Props{Attributes: collapsible.Trigger(ctx)}) {
		Can I use this in my project?
	}
	@collapsible.Content() {
		Yes. Free to use for personal and commercial projects. No attribution required.
	}
}
```

## Composition

Use the following composition to build a `Collapsible`:

```text
collapsible.Collapsible
├── collapsible.Trigger
└── collapsible.Content
```

## Open State

Use the `Open` prop to render the collapsible expanded initially.

```templ showLineNumbers
@collapsible.Collapsible(collapsible.Props{Open: true}) {
	@button.Button(button.Props{Attributes: collapsible.Trigger(ctx)}) {
		Toggle
	}
	@collapsible.Content() {
		Content
	}
}
```

## Basic

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/card"
	"github.com/axadrn/shadcn-templ/v2/components/collapsible"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
)

templ CollapsibleBasic() {
	@card.Card(card.Props{Class: "mx-auto w-full max-w-sm"}) {
		@card.Content() {
			@collapsible.Collapsible(collapsible.Props{Class: "rounded-md data-open:bg-muted"}) {
				@button.Button(button.Props{
					Variant:    button.VariantGhost,
					Class:      "w-full",
					Attributes: collapsible.Trigger(ctx),
				}) {
					Product details
					@icon.ChevronDown(icon.Props{Class: "ml-auto group-data-panel-open/button:rotate-180"})
				}
				@collapsible.Content(collapsible.ContentProps{Class: "flex flex-col items-start gap-2 p-2.5 pt-0 text-sm"}) {
					<div>
						This panel can be expanded or collapsed to reveal additional content.
					</div>
					@button.Button(button.Props{Size: button.SizeXs}) {
						Learn More
					}
				}
			}
		}
	}
}
```

## Settings Panel

Use a trigger button to reveal additional settings.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/card"
	"github.com/axadrn/shadcn-templ/v2/components/collapsible"
	"github.com/axadrn/shadcn-templ/v2/components/field"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/input"
)

templ CollapsibleSettings() {
	@card.Card(card.Props{Class: "mx-auto w-full max-w-xs", Size: card.SizeSm}) {
		@card.Header() {
			@card.Title() {
				Radius
			}
			@card.Description() {
				Set the corner radius of the element.
			}
		}
		@card.Content() {
			@collapsible.Collapsible(collapsible.Props{Class: "flex items-start gap-2"}) {
				@field.Group(field.GroupProps{Class: "grid w-full grid-cols-2 gap-2"}) {
					@field.Field() {
						@field.Label(field.LabelProps{For: "radius-x", Class: "sr-only"}) {
							Radius X
						}
						@input.Input(input.Props{ID: "radius-x", Placeholder: "0", Value: "0"})
					}
					@field.Field() {
						@field.Label(field.LabelProps{For: "radius-y", Class: "sr-only"}) {
							Radius Y
						}
						@input.Input(input.Props{ID: "radius-y", Placeholder: "0", Value: "0"})
					}
					@collapsible.Content(collapsible.ContentProps{Class: "col-span-full grid grid-cols-subgrid gap-2"}) {
						@field.Field() {
							@field.Label(field.LabelProps{For: "radius-top", Class: "sr-only"}) {
								Radius Top
							}
							@input.Input(input.Props{ID: "radius-top", Placeholder: "0", Value: "0"})
						}
						@field.Field() {
							@field.Label(field.LabelProps{For: "radius-bottom", Class: "sr-only"}) {
								Radius Bottom
							}
							@input.Input(input.Props{ID: "radius-bottom", Placeholder: "0", Value: "0"})
						}
					}
				}
				@button.Button(button.Props{
					Variant:    button.VariantOutline,
					Size:       button.SizeIcon,
					Attributes: collapsible.Trigger(ctx),
				}) {
					@icon.Maximize(icon.Props{Class: "group-data-panel-open/button:hidden"})
					@icon.Minimize(icon.Props{Class: "hidden group-data-panel-open/button:inline"})
				}
			}
		}
	}
}
```

## File Tree

Use nested collapsibles to build a file tree.

```templ
package examples

import (
	"github.com/axadrn/shadcn-templ/v2/components/button"
	"github.com/axadrn/shadcn-templ/v2/components/card"
	"github.com/axadrn/shadcn-templ/v2/components/collapsible"
	"github.com/axadrn/shadcn-templ/v2/components/icon"
	"github.com/axadrn/shadcn-templ/v2/components/tabs"
)

type fileTreeItem struct {
	Name  string
	Items []fileTreeItem
}

var fileTree = []fileTreeItem{
	{Name: "components", Items: []fileTreeItem{
		{Name: "ui", Items: []fileTreeItem{
			{Name: "button.templ"},
			{Name: "card.templ"},
			{Name: "dialog.templ"},
			{Name: "input.templ"},
			{Name: "select.templ"},
			{Name: "table.templ"},
		}},
		{Name: "login_form.templ"},
		{Name: "register_form.templ"},
	}},
	{Name: "utils", Items: []fileTreeItem{
		{Name: "utils.go"},
		{Name: "cn.go"},
		{Name: "api.go"},
	}},
	{Name: "internal", Items: []fileTreeItem{
		{Name: "middleware.go"},
		{Name: "session.go"},
		{Name: "storage.go"},
	}},
	{Name: "types", Items: []fileTreeItem{
		{Name: "types.go"},
		{Name: "api.go"},
	}},
	{Name: "public", Items: []fileTreeItem{
		{Name: "favicon.ico"},
		{Name: "logo.svg"},
		{Name: "images"},
	}},
	{Name: "main.go"},
	{Name: "layout.templ"},
	{Name: "globals.css"},
	{Name: "go.mod"},
	{Name: "go.sum"},
	{Name: "README.md"},
	{Name: ".gitignore"},
}

templ fileTreeEntry(item fileTreeItem) {
	if len(item.Items) > 0 {
		@collapsible.Collapsible() {
			@button.Button(button.Props{
				Variant:    button.VariantGhost,
				Size:       button.SizeSm,
				Class:      "w-full justify-start transition-none hover:bg-accent hover:text-accent-foreground",
				Attributes: collapsible.Trigger(ctx),
			}) {
				@icon.ChevronRight(icon.Props{Class: "transition-transform group-data-panel-open/button:rotate-90"})
				@icon.Folder()
				{ item.Name }
			}
			@collapsible.Content(collapsible.ContentProps{Class: "mt-1 ml-5"}) {
				<div class="flex flex-col gap-1">
					for _, child := range item.Items {
						@fileTreeEntry(child)
					}
				</div>
			}
		}
	} else {
		@button.Button(button.Props{
			Variant: button.VariantLink,
			Size:    button.SizeSm,
			Class:   "w-full justify-start gap-2 text-foreground",
		}) {
			@icon.File()
			<span>{ item.Name }</span>
		}
	}
}

templ CollapsibleFileTree() {
	@card.Card(card.Props{Class: "mx-auto w-full max-w-[16rem] gap-2", Size: card.SizeSm}) {
		@card.Header() {
			@tabs.Tabs(tabs.Props{DefaultValue: "explorer", ID: "file-tree-tabs"}) {
				@tabs.List(tabs.ListProps{Class: "w-full"}) {
					@tabs.Trigger(tabs.TriggerProps{Value: "explorer"}) {
						Explorer
					}
					@tabs.Trigger(tabs.TriggerProps{Value: "outline"}) {
						Outline
					}
				}
			}
		}
		@card.Content() {
			<div class="flex flex-col gap-1">
				for _, item := range fileTree {
					@fileTreeEntry(item)
				}
			</div>
		}
	}
}
```

## API Reference

### Collapsible

The `Collapsible` component is the root that manages the open state and links trigger and content.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Open`  | `bool`   | `false` |
| `Class` | `string` | -       |

### Trigger

`collapsible.Trigger(ctx)` returns the attributes that turn any element into the trigger, usually spread onto a Button. The trigger carries `data-panel-open` while the panel is open.

| Prop  | Type              | Default |
| ----- | ----------------- | ------- |
| `ctx` | `context.Context` | -       |

### Content

The `collapsible.Content` component holds the content revealed by the trigger.

| Prop    | Type     | Default |
| ------- | -------- | ------- |
| `Class` | `string` | -       |
