FooterNav
Columns of grouped links for a site's footer, each under its title, wrapping on narrow screens.
Demo
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/footer_nav.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/footer_nav.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/footer_nav.qwe
view FooterNavDemo() = <div.demo-stack> <FooterNav id="footer-nav-demo" current="#footer_nav" groups={[ { title: "Product", links: [ { label: "Features", href: "#features" }, { label: "Pricing", href: "#pricing" }, { label: "Components", href: "#footer_nav" }, { label: "Changelog", href: "#changelog", badge: "New" } ] }, { title: "Resources", links: [ { label: "Documentation", href: "#docs" }, { label: "Guides", href: "#guides" }, { label: "GitHub", href: "https://github.com/quillolang", external: true } ] }, { title: "Company", links: [ { label: "About", href: "#about" }, { label: "Blog", href: "#blog" }, { label: "Careers", href: "#careers" } ] }, { title: "Legal", links: [ { label: "Privacy", href: "#privacy" }, { label: "Terms", href: "#terms" } ] } ]}/> </div>Source
ui/footer_nav.qwe
// FooterNav: the columns of grouped links at the bottom of a site (Product, Company,// Resources, Legal), each under its title. The columns share the width and wrap on// narrow screens, two to a row and then one.//// <FooterNav groups={[// { title: "Product", links: [{ label: "Features", href: "/features" }, { label: "Pricing", href: "/pricing" }] },// { title: "Company", links: [{ label: "About", href: "/about" }, { label: "Blog", href: "/blog" }] }// ]}/>//// groups: { title, links: [{ label, href, external?, badge? }] }. external: the link// opens in a new tab, with an icon saying so. badge: a short text after the label// ("New"). current: the href of this page, marked aria-current="page".// label: what screen readers call it ("Footer"). columns: how many across at most// (the number of groups by default, up to 6).import ui/theme.qwe use ui_clslet footer_nav_css = css`.ui-footernav { font: 14px/1.5 var(--ui-font); color: var(--ui-fg); }.ui-footernav-cols { display: grid; grid-template-columns: repeat(var(--ui-footernav-cols, 4), minmax(0, 1fr)); gap: 28px 24px; }.ui-footernav-title { margin: 0 0 10px; font-size: 13px; font-weight: 650; letter-spacing: .02em; }.ui-footernav ul { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }.ui-footernav-link { display: inline-flex; align-items: center; gap: 6px; border-radius: 4px; color: var(--ui-muted); text-decoration: none; transition: color .12s;}.ui-footernav-link:hover { color: var(--ui-fg); text-decoration: underline; text-underline-offset: 3px; }.ui-footernav-link:focus-visible { outline: none; box-shadow: var(--ui-focus); }.ui-footernav-link[aria-current="page"] { color: var(--ui-fg); font-weight: 500; }.ui-footernav-link svg { width: 12px; height: 12px; flex: none; }.ui-footernav-badge { padding: 0 6px; border-radius: 999px; background: var(--ui-accent-soft); color: var(--ui-accent); font-size: 11px; font-weight: 600; line-height: 18px;}@media (max-width: 760px) { .ui-footernav-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }@media (max-width: 400px) { .ui-footernav-cols { grid-template-columns: 1fr; } }@media (prefers-reduced-motion: reduce) { .ui-footernav-link { transition: none; } }`view FooterNav(groups: list = [], current: str? = null, columns: int? = null, label: str = "Footer", id: str? = null, class: str? = null) { style global footer_nav_css let cols = columns ?? min([len(groups), 6]) ?? 1 <nav class={ui_cls(["ui-footernav", class])} id={id} aria-label={label}> <div.ui-footernav-cols style={`--ui-footernav-cols: ${max([cols, 1])}`}> {for [i, g] in enumerate(groups) => <div.ui-footernav-group> <p.ui-footernav-title id={id != null ? `${id}-g${i}` : null}>{g.title}</p> <ul aria-label={g.title}> {for l in g.links => <li> <a.ui-footernav-link href={l.href} aria-current={current != null && l.href == current ? "page" : null} target={get(l, "external") == true ? "_blank" : null} rel={get(l, "external") == true ? "noopener" : null}> <span>{l.label}</span> {get(l, "external") == true && <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 4h6v6M20 4l-9 9M18 14v6H4V6h6"/></svg>} {get(l, "external") == true && <span.ui-sr> (opens in a new tab)</span>} {get(l, "badge") != null && <span.ui-footernav-badge>{l.badge}</span>} </a> </li>} </ul> </div>} </div> </nav>}Related
MegaMenuA top bar whose items open wide panels of grouped links under the whole bar, on hover and from the keyboard, with no script.5 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 downloadsAlphabetIndexA to Z links into a list sorted by name; letters with nothing under them stay in place, disabled.4 views · 6 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 downloads
Thread
Thread 0 posts
On FooterNav: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.