Accordion
A stack of panels that open one at a time.
<accordion.Accordion>
<accordion.AccordionItem name="faq" title="Is it accessible?" open>
Yes. It uses the native details element.
</accordion.AccordionItem>
<accordion.AccordionItem name="faq" title="Is it animated?">Yes. The panel height animates.</accordion.AccordionItem>
</accordion.Accordion>Installation
Run the command in the app module.
gx add accordionThe command also installs icons.
The command writes these files.
| File | Path in the app |
|---|---|
Accordion.gx |
ui/accordion/Accordion.gx |
AccordionItem.gx |
ui/accordion/AccordionItem.gx |
Accordion.fixtures.go |
ui/accordion/Accordion.fixtures.go |
AccordionItem.fixtures.go |
ui/accordion/AccordionItem.fixtures.go |
Install icons first.
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package accordion
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the accordion: the accordion items.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div class={gx.Cx("w-full", p.Class)} {...p.Attrs}>{p.Children}</div>package accordion
import "github.com/alternayte/gx/registry/icons"
props {
// Name is the name attribute of the details element.
// Items with the same name form one accordion, and only one of them is open at a time.
Name string
// Title is the text of the summary, the part that opens and closes the item.
Title string
// Open renders the item open. The default is closed.
Open bool = false
// Disabled stops the summary from opening or closing the item.
Disabled bool = false
// Class adds classes to the root element.
Class string = ""
// Children is the content of the item panel.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<details name={p.Name} open={p.Open} class={gx.Cx("group/accordion-item border-border border-b last:border-b-0 [interpolate-size:allow-keywords] [&::details-content]:h-0 [&::details-content]:overflow-hidden [&::details-content]:transition-[height,content-visibility] [&::details-content]:transition-discrete [&::details-content]:duration-200 [&::details-content]:ease-out open:[&::details-content]:h-auto motion-reduce:[&::details-content]:transition-none", p.Class)} {...p.Attrs}>
<summary inert={p.Disabled} class="flex flex-1 list-none items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 inert:pointer-events-none inert:opacity-50 [&::-webkit-details-marker]:hidden">
{p.Title}
<icons.ChevronDown class="pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200 group-open/accordion-item:rotate-180 motion-reduce:transition-none" />
</summary>
<div class="pt-0 pb-4 text-sm">{p.Children}</div>
</details>package accordion
import "github.com/alternayte/gx"
var AccordionFixtures = gx.Fixtures[AccordionProps]{
"Two": {Children: gx.Frag(
AccordionItem(AccordionItemProps{Name: "faq", Title: "Is it accessible?", Open: true, Children: gx.Text("Yes. It uses the native details element.")}),
AccordionItem(AccordionItemProps{Name: "faq", Title: "Is it animated?", Children: gx.Text("Yes. The panel height animates.")}),
)},
}package accordion
import "github.com/alternayte/gx"
// Each fixture has its own name: details elements that share a name form one
// exclusive group across the whole gallery page.
var AccordionItemFixtures = gx.Fixtures[AccordionItemProps]{
"Closed": {Name: "item-closed", Title: "A question", Children: gx.Text("An answer.")},
"Open": {Name: "item-open", Title: "A question", Open: true, Children: gx.Text("An answer.")},
"Disabled": {Name: "item-disabled", Title: "A question", Disabled: true, Children: gx.Text("An answer.")},
}The theme must define these tokens: --border, --muted-foreground, --ring.
Usage
<accordion.Accordion>
<accordion.AccordionItem name="faq" title="Is it accessible?">
Yes. It uses the native details element.
</accordion.AccordionItem>
</accordion.Accordion>The accordion uses <details name>, so the browser gives the open and close behaviour.
The panel height animates in a browser that supports interpolate-size. Other browsers open the panel at once.
Set Disabled to stop an item from opening.
Examples
Accordion: Two
<accordion.Accordion>
<accordion.AccordionItem name="faq" title="Is it accessible?" open>
Yes. It uses the native details element.
</accordion.AccordionItem>
<accordion.AccordionItem name="faq" title="Is it animated?">Yes. The panel height animates.</accordion.AccordionItem>
</accordion.Accordion>AccordionItem: Closed
<accordion.AccordionItem name="item-closed" title="A question">An answer.</accordion.AccordionItem>AccordionItem: Open
<accordion.AccordionItem name="item-open" title="A question" open>An answer.</accordion.AccordionItem>AccordionItem: Disabled
<accordion.AccordionItem name="item-disabled" title="A question" disabled>An answer.</accordion.AccordionItem>API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
accordion.Accordion
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the accordion: the accordion items. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
accordion.AccordionItem
| Prop | Type | Default | Description |
|---|---|---|---|
Name |
string |
Required | Name is the name attribute of the details element. Items with the same name form one accordion, and only one of them is open at a time. |
Title |
string |
Required | Title is the text of the summary, the part that opens and closes the item. |
Open |
bool |
false |
Open renders the item open. The default is closed. |
Disabled |
bool |
false |
Disabled stops the summary from opening or closing the item. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the item panel. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
Do and do not
Do
- Give every item of one accordion the same
Name. - Give each accordion on a page its own
Name. - Put a question in
Titleand the answer in the body.
Don't
- Do not use an accordion for primary navigation.
- Do not open more than one item.
Keyboard
| Key | Action |
|---|---|
| Tab | Moves focus to the summary. |
| Enter, Space | Opens or closes the item. |