Navigation

Accordion

Sections that open under their titles, on the browser's own <details>: exclusive with a group.

#navigation#list#no-js

Demo

Preview
What does it cost?

Nothing for one project and up to three people. Teams pay per seat, monthly or yearly.

Can I cancel at any time?

Yes, from Settings, Billing. You keep access until the end of the period you paid for.

Where is my data kept?Servers, backups and exports

In the EU, on servers in Frankfurt, with nightly backups kept for 30 days.

The same group: opening one closes the others. Below, flush and independent.

Shipping

Free over €50; two to four working days.

Returns

Within 30 days, in the original packaging.

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/accordion.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/accordion.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/accordion.qwe
view AccordionDemo() =    <div.demo-stack>        <Accordion>            <AccordionItem group="faq" title="What does it cost?" open={true}>                <p>Nothing for one project and up to three people. Teams pay per seat, monthly or yearly.</p>            </AccordionItem>            <AccordionItem group="faq" title="Can I cancel at any time?">                <p>Yes, from Settings, Billing. You keep access until the end of the period you paid for.</p>            </AccordionItem>            <AccordionItem group="faq" title="Where is my data kept?" hint="Servers, backups and exports">                <p>In the EU, on servers in Frankfurt, with nightly backups kept for 30 days.</p>            </AccordionItem>        </Accordion>        <p.demo-note>The same group: opening one closes the others. Below, flush and independent.</p>        <Accordion flush={true}>            <AccordionItem title="Shipping"><p>Free over €50; two to four working days.</p></AccordionItem>            <AccordionItem title="Returns"><p>Within 30 days, in the original packaging.</p></AccordionItem>        </Accordion>    </div>

Source

ui/accordion.qwe
// Accordion: sections that open and close under their titles, on the browser's own// <details>, so they work without JavaScript, with the keyboard, and with find-in-page.////   <Accordion>//       <AccordionItem title="What does it cost?" open={true}><p>Nothing to start.</p></AccordionItem>//       <AccordionItem title="Can I cancel?"><p>Any time, from Settings.</p></AccordionItem>//   </Accordion>//// AccordionItem: title (the line you click), open (open to start with), children.// group: items with the same group are exclusive, as radio buttons are: opening// one closes the others (<details name>). Give every item of the accordion the// same group, unique on the page. hint: a quieter line under the title.// Accordion: flush={true} drops the box around the items, for a list in a card.import ui/theme.qwe use ui_clslet accordion_css = css`.ui-accordion { border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface);  font: 15px/1.5 var(--ui-font); color: var(--ui-fg); interpolate-size: allow-keywords; }.ui-accordion-flush { border-width: 1px 0 0; border-radius: 0; background: transparent; }.ui-accordion-item + .ui-accordion-item, .ui-accordion-flush .ui-accordion-item { border-top: 1px solid var(--ui-border); }.ui-accordion-flush .ui-accordion-item:first-child { border-top: 0; }.ui-accordion-flush { border-bottom: 1px solid var(--ui-border); }.ui-accordion-item > summary {  display: flex; align-items: center; gap: 12px; padding: 14px 16px; cursor: pointer; list-style: none;  font-weight: 500; border-radius: var(--ui-radius);}.ui-accordion-flush .ui-accordion-item > summary { padding-left: 2px; padding-right: 2px; }.ui-accordion-item > summary::-webkit-details-marker { display: none; }.ui-accordion-item > summary:hover { color: var(--ui-accent); }.ui-accordion-item > summary:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--ui-accent); }.ui-accordion-title { flex: 1; display: grid; gap: 1px; }.ui-accordion-hint { color: var(--ui-muted); font-size: 13px; font-weight: 400; }.ui-accordion-chev {  flex: none; width: 8px; height: 8px; margin: -4px 4px 0; border: solid var(--ui-muted); border-width: 0 1.5px 1.5px 0;  transform: rotate(45deg); transition: transform .2s;}.ui-accordion-item[open] > summary .ui-accordion-chev { transform: translateY(3px) rotate(-135deg); }.ui-accordion-body { padding: 0 16px 16px; color: var(--ui-muted); }.ui-accordion-flush .ui-accordion-body { padding-left: 2px; padding-right: 2px; }.ui-accordion-body > :first-child { margin-top: 0; }.ui-accordion-body > :last-child { margin-bottom: 0; }.ui-accordion-item::details-content { block-size: 0; overflow: hidden; transition: block-size .2s, content-visibility .2s allow-discrete; }.ui-accordion-item[open]::details-content { block-size: auto; }@media (prefers-reduced-motion: reduce) {  .ui-accordion-chev, .ui-accordion-item::details-content { transition: none; }}`view Accordion(flush: bool = false, class: str? = null, children) {    style global accordion_css    <div class={ui_cls(["ui-accordion", flush && "ui-accordion-flush", class])}>{children}</div>}view AccordionItem(title: str, hint: str? = null, open: bool = false, group: str? = null, class: str? = null, children) {    style global accordion_css    <details class={ui_cls(["ui-accordion-item", class])} name={group} open={open}>        <summary>            <span.ui-accordion-title>{title}{hint != null && <span.ui-accordion-hint>{hint}</span>}</span>            <span.ui-accordion-chev aria-hidden="true"></span>        </summary>        <div.ui-accordion-body>{children}</div>    </details>}
Thread
57Useful? Like it, or add to its thread below.

Thread 0 posts

On Accordion: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.