Steps
How far along a process is: steps done with a check mark, this one, and those to come; across or down.
Demo
- Account (done)
- Shipping (done)
- Payment
- Review
- Order placed (done)May 2, 09:14
- Shipped (done)May 3, from Lisbon
- Out for deliveryToday
- Delivered
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/steps.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/steps.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/steps.qwe
view StepsDemo() = <div.demo-stack style="gap: 32px"> <Steps steps={["Account", "Shipping", "Payment", "Review"]} current={2}/> <div.demo-row> <Steps vertical={true} current={2} steps={[{ label: "Order placed", hint: "May 2, 09:14" }, { label: "Shipped", hint: "May 3, from Lisbon" }, { label: "Out for delivery", hint: "Today" }, { label: "Delivered" }]}/> </div> </div>Source
ui/steps.qwe
// Steps: how far along a process someone is: the steps done, this one, and those to come.//// <Steps steps={["Account", "Billing", "Confirm"]} current={1}/>// <Steps vertical={true} current={2} steps={[{ label: "Ordered", hint: "May 2" },// { label: "Shipped", hint: "May 3" }, { label: "Out for delivery" }, { label: "Delivered" }]}/>//// steps: strings, or maps of { label, hint? } (a second, quieter line).// current: the index of this step, from 0; those before it show a check mark.// Set it to len(steps) when everything is done. vertical: one under another,// for timelines and narrow places. label: what screen readers call it ("Progress").import ui/theme.qwe use ui_clslet steps_css = css`.ui-steps { display: flex; margin: 0; padding: 0; list-style: none; font: 14px/1.4 var(--ui-font); color: var(--ui-fg); counter-reset: ui-steps; }.ui-steps-item { position: relative; flex: 1 1 0; min-width: 0; display: grid; justify-items: start; gap: 8px; padding-right: 12px; }.ui-steps-item:last-child { flex: none; padding-right: 0; }.ui-steps-item:not(:last-child)::after { content: ""; position: absolute; top: 13px; left: 36px; right: 8px; height: 2px; border-radius: 2px; background: var(--ui-border);}.ui-steps-done:not(:last-child)::after { background: var(--ui-accent); }.ui-steps-mark { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--ui-border); background: var(--ui-surface); color: var(--ui-muted); font: 600 13px/1 var(--ui-font); font-variant-numeric: tabular-nums;}.ui-steps-done .ui-steps-mark { border-color: var(--ui-accent); background: var(--ui-accent); color: var(--ui-accent-fg); }.ui-steps-current .ui-steps-mark { border-color: var(--ui-accent); color: var(--ui-accent); box-shadow: var(--ui-focus); }.ui-steps-mark svg { width: 14px; height: 14px; }.ui-steps-text { display: grid; gap: 1px; }.ui-steps-label { font-weight: 500; }.ui-steps-upcoming .ui-steps-label { color: var(--ui-muted); }.ui-steps-hint { color: var(--ui-muted); font-size: 13px; }.ui-steps-vertical { flex-direction: column; }.ui-steps-vertical .ui-steps-item { grid-template-columns: 28px 1fr; align-items: start; gap: 12px; padding: 0 0 22px; }.ui-steps-vertical .ui-steps-item:last-child { padding-bottom: 0; }.ui-steps-vertical .ui-steps-item:not(:last-child)::after { top: 34px; bottom: 6px; left: 13px; right: auto; width: 2px; height: auto; }.ui-steps-vertical .ui-steps-text { padding-top: 3px; }@media (max-width: 600px) { .ui-steps:not(.ui-steps-vertical) .ui-steps-hint { display: none; } .ui-steps:not(.ui-steps-vertical) .ui-steps-label { font-size: 13px; }}`view Steps(steps: list = [], current: int = 0, vertical: bool = false, label: str = "Progress", class: str? = null) { style global steps_css <ol class={ui_cls(["ui-steps", vertical && "ui-steps-vertical", class])} aria-label={label}> {for [i, s] in enumerate(steps) => { let text = type_of(s) == "str" ? s : s.label let phase = i < current ? "done" : i == current ? "current" : "upcoming" <li class={`ui-steps-item ui-steps-${phase}`} aria-current={phase == "current" ? "step" : null}> <span.ui-steps-mark aria-hidden="true"> {phase == "done" ? <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 8.5l3 3 6-7"/></svg> : i + 1} </span> <span.ui-steps-text> <span.ui-steps-label>{text}{phase == "done" && <span.ui-sr> (done)</span>}</span> {type_of(s) == "map" && s.hint != null && <span.ui-steps-hint>{s.hint}</span>} </span> </li> }} </ol>}Related
ProgressNavNumbered steps as links: the ones done link back, this one is marked, and the ones to come wait their turn.6 views · 4 downloadsAccordionSections that open under their titles, on the browser's own <details>: exclusive with a group.5 views · 7 downloadsAlphabetIndexA to Z links into a list sorted by name; letters with nothing under them stay in place, disabled.4 views · 6 downloadsBackToTopA button in the corner that shows once the page is scrolled down and takes it back to the top.6 views · 8 downloadsBottomNavA fixed bar of icon tabs along the bottom of a phone's screen, with counts and the current one marked.6 views · 7 downloadsBreadcrumbsWhere this page sits: a trail of links up to the home page, the last one marked as this page.5 views · 6 downloads
Thread
Thread 0 posts
On Steps: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.