Collapsible
A block shown and hidden under a line you click, on the browser's own <details>; open by default or not.
Demo
Advanced options3 settings
Show the full log4 lines
$ quillo check app.qwe app.qwe: ok (12 routes, 48 functions) $ quillo run app.qwe quillo: 12 routes listening on http://127.0.0.1:8080
The details are closed.
Two in one group: opening one closes the other.
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/collapsible.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/collapsible.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/collapsible.qwe
component CollapsibleDemoLive() { state seen = false <div.demo-stack> <Collapsible id="collapsible-demo-live" title="Details" variant="button" on_toggle={(o) => { seen = o }}> <p style="margin: 0">Opened with the trigger, or by find-in-page.</p> </Collapsible> <p.demo-note>The details are {seen ? "open" : "closed"}.</p> </div>}view CollapsibleDemo() = <div.demo-stack> <Collapsible id="collapsible-demo-options" title="Advanced options" hint="3 settings"> <div.demo-stack style="gap: 8px"> <Switch label="Send a copy to me"/> <Switch label="Keep the thread open"/> <Switch label="Mark as internal" checked={true}/> </div> </Collapsible> <Collapsible id="collapsible-demo-log" title="Show the full log" open={true} variant="box" hint="4 lines"> <pre style="margin: 0; font: 13px/1.6 var(--ui-mono)">{"$ quillo check app.qwe\napp.qwe: ok (12 routes, 48 functions)\n$ quillo run app.qwe\nquillo: 12 routes listening on http://127.0.0.1:8080"}</pre> </Collapsible> <CollapsibleDemoLive/> <p.demo-note>Two in one group: opening one closes the other.</p> <Collapsible id="collapsible-demo-a" group="collapsible-demo-group" title="Shipping"><p style="margin: 0">Free over €50; two to four working days.</p></Collapsible> <Collapsible id="collapsible-demo-b" group="collapsible-demo-group" title="Returns"><p style="margin: 0">Within 30 days, in the original packaging.</p></Collapsible> </div>Source
ui/collapsible.qwe
// Collapsible: a block that shows and hides under a line you click, on the// browser's own <details>, so it works without JavaScript, with the keyboard and// with find-in-page (which opens it). Open to start with, or not.//// <Collapsible title="Advanced options"> <Switch .../> <Switch .../> </Collapsible>// <Collapsible title="Show the full log" open={true} variant="box" hint="412 lines"> <pre>...</pre> </Collapsible>// <Collapsible title="Details" on_toggle={(open) => { seen = open }}> ... </Collapsible>//// title: the line that opens it. hint: quieter text after the title (a count).// open: open to start with (false). variant: "plain" (default, a line with a// chevron), "box" (in a bordered box) or "button" (the line looks like a button).// group: collapsibles with the same group are exclusive: opening one closes the// others (<details name>). id: the <details>'s id.// on_toggle(open): inside one of your components, called with true when it opens// and false when it closes.import ui/theme.qwe use ui_clslet collapsible_css = css`.ui-collapsible { min-width: 0; color: var(--ui-fg); font: 15px/1.5 var(--ui-font); interpolate-size: allow-keywords; }.ui-collapsible > summary { display: flex; align-items: center; gap: 8px; width: fit-content; max-width: 100%; padding: 6px 8px; margin: 0 -8px; border-radius: var(--ui-radius-sm); font-weight: 500; cursor: pointer; list-style: none; user-select: none;}.ui-collapsible > summary::-webkit-details-marker { display: none; }.ui-collapsible > summary:hover { color: var(--ui-accent); }.ui-collapsible > summary:focus-visible { outline: none; box-shadow: var(--ui-focus); }.ui-collapsible-chev { flex: none; width: 16px; height: 16px; transition: transform .2s; }.ui-collapsible[open] > summary .ui-collapsible-chev { transform: rotate(90deg); }.ui-collapsible-hint { color: var(--ui-muted); font-size: 13px; font-weight: 400; }.ui-collapsible-body { padding: 8px 0 4px; }.ui-collapsible-body > :first-child { margin-top: 0; }.ui-collapsible-body > :last-child { margin-bottom: 0; }.ui-collapsible-box { border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface); }.ui-collapsible-box > summary { width: auto; margin: 0; padding: 12px 16px; border-radius: var(--ui-radius); }.ui-collapsible-box > .ui-collapsible-body { padding: 0 16px 16px; }.ui-collapsible-button > summary { margin: 0; padding: 0 14px; height: 36px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm); background: var(--ui-surface); font-size: 14px;}.ui-collapsible-button > summary:hover { border-color: var(--ui-strong); background: var(--ui-subtle); color: var(--ui-fg); }.ui-collapsible-button > .ui-collapsible-body { padding-top: 12px; }.ui-collapsible::details-content { block-size: 0; overflow: hidden; transition: block-size .2s, content-visibility .2s allow-discrete; }.ui-collapsible[open]::details-content { block-size: auto; }@media (prefers-reduced-motion: reduce) { .ui-collapsible-chev, .ui-collapsible::details-content { transition: none; } }`view Collapsible(title: str, hint: str? = null, open: bool = false, variant: str = "plain", group: str? = null, id: str? = null, on_toggle = null, class: str? = null, children) { style global collapsible_css <details class={ui_cls(["ui-collapsible", variant != "plain" && `ui-collapsible-${variant}`, class])} id={id} name={group} open={open} @toggle={(e) => { on_toggle && on_toggle(e.target.open) }}> <summary> <svg.ui-collapsible-chev viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg> <span>{title}</span> {hint != null && <span.ui-collapsible-hint>{hint}</span>} </summary> <div.ui-collapsible-body>{children}</div> </details>}Related
AppShellAn app's frame: a sidebar of links, a top bar and the page; the sidebar is a drawer on phones.10 views · 7 downloadsDockA floating bar of icon buttons fixed to the bottom or a side of the page, with badges and the current one marked.6 views · 7 downloadsFieldsetA <fieldset> with a legend and a line about it, its fields stacked, in a row or in a grid; disabled as one.6 views · 7 downloadsFooterA site's footer: brand and tagline, columns of links under titles, and a bottom line with the small print.6 views · 6 downloadsMasterDetailA list on the left and the item picked in detail on the right; one at a time with a Back button when narrow.6 views · 6 downloadsNavbarThe bar along the top of a site: name, links and actions; the links fold into a menu when narrow.5 views · 6 downloads
Thread
Thread 0 posts
On Collapsible: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.