Collapsible
UI::CollapsibleA section that opens and closes under its trigger, like a branch of a nav tree.
# VelvetKit
## Collapsible (`UI::Collapsible`)
A section that opens and closes under its trigger, like a branch of a nav tree.
Add it: `bin/rails generate velvetkit:add collapsible`
Also adds: `icon`
### Arguments
```ruby
UI::Collapsible.new(open: false, size: :default, trigger_class: nil, content_class: nil, class: nil, **html_attrs)
```
Slots: `with_trigger`
### Notes
A section that opens and closes under its trigger: a tree of links in a
sidebar, "Show more" details, an advanced-settings block.
Built on <details> and <summary>, so it works before any JavaScript loads,
Enter and Space toggle it, screen readers announce it as expanded or
collapsed, and find-in-page opens it to show a match. Browsers that can
animate to auto height slide it open; the rest open it at once.
<%= render(UI::Collapsible.new(open: current_page_is_a_form?)) do |c| %>
<% c.with_trigger { "Forms" } %>
<%= link_to "Input", input_path %>
<% end %>
Collapsibles nest, so a trigger inside the content makes a deeper branch.
### Example: Navigation tree
```erb
<%# A sidebar tree: branches open on click, and the one holding the current page starts open. %>
<nav aria-label="Documentation" class="w-56 text-sm">
<%= render(UI::Collapsible.new(open: true, trigger_class: "font-medium hover:bg-accent", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |c| %>
<% c.with_trigger { "Forms" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Input</a>
<a href="#" aria-current="page" class="block rounded-md bg-primary/10 px-3 py-1.5 font-medium text-primary">Textarea</a>
<%= render(UI::Collapsible.new(trigger_class: "text-muted-foreground hover:bg-accent hover:text-foreground", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |inner| %>
<% inner.with_trigger { "Choices" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Select</a>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Checkbox</a>
<% end %>
<% end %>
<%= render(UI::Collapsible.new(trigger_class: "font-medium hover:bg-accent", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |c| %>
<% c.with_trigger { "Overlays" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Dialog</a>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Sheet</a>
<% end %>
</nav>
```
### Example: Show more
```erb
<div class="max-w-md rounded-lg border p-4">
<p class="text-sm">Payments are collected on the 1st of each month.</p>
<%= render(UI::Collapsible.new(size: :sm, class: "mt-2", trigger_class: "w-auto -ml-2 text-primary hover:underline")) do |c| %>
<% c.with_trigger { "How refunds work" } %>
<p class="px-0 text-sm text-muted-foreground">Cancel within 14 days for a full refund. After that, the rest of the month is credited to your next invoice.</p>
<% end %>
</div>
```
bin/rails generate velvetkit:add collapsible
- Also adds
- Icon
- Stimulus
- None, it's server-rendered
- Installs
- Nothing
Examples
Navigation tree
default.html.erb
<%# A sidebar tree: branches open on click, and the one holding the current page starts open. %>
<nav aria-label="Documentation" class="w-56 text-sm">
<%= render(UI::Collapsible.new(open: true, trigger_class: "font-medium hover:bg-accent", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |c| %>
<% c.with_trigger { "Forms" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Input</a>
<a href="#" aria-current="page" class="block rounded-md bg-primary/10 px-3 py-1.5 font-medium text-primary">Textarea</a>
<%= render(UI::Collapsible.new(trigger_class: "text-muted-foreground hover:bg-accent hover:text-foreground", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |inner| %>
<% inner.with_trigger { "Choices" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Select</a>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Checkbox</a>
<% end %>
<% end %>
<%= render(UI::Collapsible.new(trigger_class: "font-medium hover:bg-accent", content_class: "ml-3 space-y-0.5 border-l pl-2")) do |c| %>
<% c.with_trigger { "Overlays" } %>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Dialog</a>
<a href="#" class="block rounded-md px-3 py-1.5 text-muted-foreground hover:bg-accent hover:text-foreground">Sheet</a>
<% end %>
</nav>
Show more
Payments are collected on the 1st of each month.
How refunds work
Cancel within 14 days for a full refund. After that, the rest of the month is credited to your next invoice.
show_more.html.erb
<div class="max-w-md rounded-lg border p-4">
<p class="text-sm">Payments are collected on the 1st of each month.</p>
<%= render(UI::Collapsible.new(size: :sm, class: "mt-2", trigger_class: "w-auto -ml-2 text-primary hover:underline")) do |c| %>
<% c.with_trigger { "How refunds work" } %>
<p class="px-0 text-sm text-muted-foreground">Cancel within 14 days for a full refund. After that, the rest of the month is credited to your next invoice.</p>
<% end %>
</div>
API
Arguments
UI::Collapsible.new(open: false, size: :default, trigger_class: nil, content_class: nil, class: nil, **html_attrs)
Slots:
with_trigger
Notes
A section that opens and closes under its trigger: a tree of links in a
sidebar, "Show more" details, an advanced-settings block.
Built on <details> and <summary>, so it works before any JavaScript loads,
Enter and Space toggle it, screen readers announce it as expanded or
collapsed, and find-in-page opens it to show a match. Browsers that can
animate to auto height slide it open; the rest open it at once.
<%= render(UI::Collapsible.new(open: current_page_is_a_form?)) do |c| %>
<% c.with_trigger { "Forms" } %>
<%= link_to "Input", input_path %>
<% end %>
Collapsibles nest, so a trigger inside the content makes a deeper branch.