Subnav
A second row of links under the main navigation, for one section's pages, with counts and the current one marked.
Demo
Narrow, the row scrolls sideways.
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/subnav.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/subnav.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/subnav.qwe
let subnav_demo_links = [ { label: "Code", href: "#code", icon: "M8 6 2 12l6 6M16 6l6 6-6 6" }, { label: "Issues", href: "#subnav", icon: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 8v4M12 16h.01", badge: 24 }, { label: "Pull requests", href: "#pulls", badge: 3 }, { label: "Actions", href: "#actions" }, { label: "Wiki", href: "#wiki" }, { label: "Settings", href: "#settings" }]view SubnavDemo() = <div.demo-stack style="gap: 20px"> <div style="border: 1px solid var(--ui-border); border-radius: var(--ui-radius); overflow: hidden"> <Subnav id="subnav-demo" title="quillo/components" links={subnav_demo_links} current="#subnav"> <Button size="sm" variant="outline" href="#subnav">Watch</Button> </Subnav> <div style="height: 32px"></div> </div> <Subnav id="subnav-demo-pill" variant="pill" label="Period" current="#month" links={[ { label: "Today", href: "#today" }, { label: "This week", href: "#week" }, { label: "This month", href: "#month" }, { label: "This year", href: "#year" } ]}/> <div style="width: 300px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); overflow: hidden"> <Subnav id="subnav-demo-narrow" links={subnav_demo_links} current="#wiki"/> </div> <p.demo-note>Narrow, the row scrolls sideways.</p> </div>Source
ui/subnav.qwe
// Subnav: a second row of links under a site's main navigation, for the pages of one// section (a product's Overview, Features, Pricing; a project's Code, Issues, Pull// requests). The current page is marked, and the row scrolls sideways when narrow.//// <Subnav title="Settings" current={request.path} links={[// { label: "General", href: "/settings" },// { label: "Members", href: "/settings/members", badge: 12 },// { label: "Billing", href: "/settings/billing" }// ]}/>//// links: { label, href, badge?, icon? }; the one whose href is `current` is marked// aria-current="page". badge: a count after the label. icon: a character or an emoji,// or an SVG path (24x24, stroked) when it starts with "M". title: a short heading at// the left of the row (a section's name). children: HTML at the right end (a button,// a search). label: what screen readers call it ("Section"). variant: "underline"// (default: a line under the current link, as a row of tabs) or "pill".import ui/theme.qwe use ui_clslet subnav_css = css`.ui-subnav { display: flex; align-items: center; gap: 16px; border-bottom: 1px solid var(--ui-border); background: var(--ui-bg); color: var(--ui-fg); font: 14px/1.4 var(--ui-font);}.ui-subnav-title { flex: none; padding: 0 0 0 4px; font-weight: 650; }.ui-subnav ul { display: flex; flex: 1; gap: 2px; min-width: 0; margin: 0; padding: 0; list-style: none; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;}.ui-subnav ul::-webkit-scrollbar { display: none; }.ui-subnav-link { display: inline-flex; align-items: center; gap: 7px; height: 42px; padding: 0 10px; border-radius: var(--ui-radius-sm) var(--ui-radius-sm) 0 0; color: var(--ui-muted); font-weight: 500; text-decoration: none; white-space: nowrap; box-shadow: inset 0 -2px 0 transparent; transition: color .12s, background .12s, box-shadow .12s;}.ui-subnav-link:hover { color: var(--ui-fg); background: var(--ui-subtle); }.ui-subnav-link:focus-visible { outline: none; box-shadow: inset 0 -2px 0 transparent, var(--ui-focus); }.ui-subnav-link[aria-current="page"] { color: var(--ui-fg); box-shadow: inset 0 -2px 0 var(--ui-accent); }.ui-subnav-icon { display: inline-grid; place-items: center; width: 16px; height: 16px; font-size: 14px; line-height: 1; }.ui-subnav-icon svg { width: 16px; height: 16px; }.ui-subnav-badge { min-width: 20px; padding: 1px 6px; border-radius: 999px; background: var(--ui-subtle); border: 1px solid var(--ui-border); color: var(--ui-muted); font-size: 12px; font-weight: 600; text-align: center; font-variant-numeric: tabular-nums;}.ui-subnav-link[aria-current="page"] .ui-subnav-badge { color: var(--ui-fg); }.ui-subnav-end { display: flex; flex: none; align-items: center; gap: 8px; padding-right: 4px; }.ui-subnav-pill { border-bottom: 0; padding: 6px 0; }.ui-subnav-pill ul { gap: 4px; }.ui-subnav-pill .ui-subnav-link { height: 32px; border-radius: 999px; box-shadow: none; }.ui-subnav-pill .ui-subnav-link:focus-visible { box-shadow: var(--ui-focus); }.ui-subnav-pill .ui-subnav-link[aria-current="page"] { background: var(--ui-accent-soft); color: var(--ui-accent); box-shadow: none; }@media (prefers-reduced-motion: reduce) { .ui-subnav-link { transition: none; } }`view Subnav(links: list = [], current: str? = null, title: str? = null, label: str = "Section", variant: str = "underline", id: str? = null, class: str? = null, children) { style global subnav_css <nav class={ui_cls(["ui-subnav", variant == "pill" && "ui-subnav-pill", class])} id={id} aria-label={label}> {title != null && <span.ui-subnav-title>{title}</span>} <ul> {for l in links => <li> <a.ui-subnav-link href={l.href} aria-current={current != null && l.href == current ? "page" : null}> {get(l, "icon") != null && <span.ui-subnav-icon aria-hidden="true">{starts_with(l.icon, "M") && len(l.icon) > 2 ? <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d={l.icon}/></svg> : l.icon}</span>} <span>{l.label}</span> {get(l, "badge") != null && <span.ui-subnav-badge>{l.badge}</span>} </a> </li>} </ul> {children != null && <div.ui-subnav-end>{children}</div>} </nav>}Related
AlphabetIndexA to Z links into a list sorted by name; letters with nothing under them stay in place, disabled.4 views · 6 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 downloadsCollapsibleNavSide navigation in groups that fold under their titles, the browser remembering which are open.6 views · 7 downloadsDirectoryNavA long list of names grouped under sticky letter headers, with a row of letters at the top that jumps to each group.5 views · 5 downloadsFilterTabsTabs with counts that filter a list, one selected, moved between with the arrow keys; a hidden input holds the key.5 views · 6 downloads
Thread
Thread 0 posts
On Subnav: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.