Navigation

LinkList

A plain list of links, each with a line saying where it leads, an icon and a short note at the right.

#navigation#link#list#no-js

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/link_list.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/link_list.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/link_list.qwe
view LinkListDemo() =    <div.demo-row style="align-items: flex-start; gap: 32px">        <div style="flex: 1 1 300px; max-width: 420px">            <LinkList id="link-list-demo" heading="Read next" items={[                { label: "Getting started", href: "#start", description: "Install Quillo and write a first page with a route and a view.",                  icon: "M12 3 2 8l10 5 10-5zM2 14l10 5 10-5" },                { label: "Components", href: "#link_list", description: "The UI kit, each component with its examples and its props.",                  icon: "M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z" },                { label: "Source on GitHub", href: "https://github.com/quillolang", external: true,                  description: "The language, the kit and the examples.", icon: "M8 6 2 12l6 6M16 6l6 6-6 6" }            ]}/>        </div>        <div style="flex: 1 1 300px; max-width: 420px">            <LinkList id="link-list-demo-divided" label="Downloads" divided={true} arrows={true} items={[                { label: "Quillo 0.5.0 for macOS", href: "#mac", description: "Apple silicon and Intel", meta: "14 MB" },                { label: "Quillo 0.5.0 for Linux", href: "#linux", description: "x86-64 and arm64", meta: "12 MB" },                { label: "Quillo 0.5.0 for Windows", href: "#win", meta: "15 MB" }            ]}/>        </div>    </div>

Source

ui/link_list.qwe
// LinkList: a plain list of links, each with a line saying what it leads to: a// page's related reading, a resources section, the sections of a help centre.////   <LinkList items={[//       { label: "Getting started", href: "/docs/start", description: "Install Quillo and write a first page." },//       { label: "Components", href: "/components", description: "The UI kit, with every example." },//       { label: "Source", href: "https://github.com/quillolang", external: true }//   ]}/>//// items: { label, href, description?, icon?, external?, meta? }. icon: a character or// an emoji, or an SVG path (24x24, stroked) when it starts with "M". external: the// link opens in a new tab, and an icon says so. meta: a quiet short text at the right// (a date, a size). divided: a line between the items. arrows: a chevron at the right// of each. label: what screen readers call the list ("Links"); heading: a title above it.import ui/theme.qwe use ui_clslet link_list_css = css`.ui-linklist { font: 14px/1.5 var(--ui-font); color: var(--ui-fg); }.ui-linklist-heading { margin: 0 0 8px; font-size: 13px; font-weight: 650; color: var(--ui-muted); letter-spacing: .04em; text-transform: uppercase; }.ui-linklist ul { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }.ui-linklist-divided ul { gap: 0; }.ui-linklist-divided li + li { border-top: 1px solid var(--ui-border); }.ui-linklist-link {  display: flex; align-items: flex-start; gap: 12px; padding: 10px 10px; border-radius: var(--ui-radius-sm);  color: inherit; text-decoration: none; transition: background .12s;}.ui-linklist-divided .ui-linklist-link { border-radius: 0; padding-left: 4px; padding-right: 4px; }.ui-linklist-link:hover { background: var(--ui-subtle); }.ui-linklist-link:focus-visible { outline: none; box-shadow: var(--ui-focus); }.ui-linklist-icon { display: inline-grid; place-items: center; flex: none; width: 22px; height: 22px; margin-top: 1px; font-size: 18px; line-height: 1; color: var(--ui-accent); }.ui-linklist-icon svg { width: 20px; height: 20px; }.ui-linklist-text { flex: 1; min-width: 0; display: grid; gap: 1px; }.ui-linklist-label { font-weight: 600; color: var(--ui-fg); }.ui-linklist-link:hover .ui-linklist-label { color: var(--ui-accent); text-decoration: underline; text-underline-offset: 3px; }.ui-linklist-label svg { width: 12px; height: 12px; margin-left: 4px; vertical-align: -1px; color: var(--ui-muted); }.ui-linklist-desc { color: var(--ui-muted); }.ui-linklist-meta { flex: none; margin-top: 2px; color: var(--ui-muted); font-size: 12px; white-space: nowrap; }.ui-linklist-chev { flex: none; width: 16px; height: 16px; margin-top: 3px; color: var(--ui-strong); }.ui-linklist-link:hover .ui-linklist-chev { color: var(--ui-accent); }@media (prefers-reduced-motion: reduce) { .ui-linklist-link { transition: none; } }`view LinkList(items: list = [], heading: str? = null, label: str = "Links", divided: bool = false, arrows: bool = false,              id: str? = null, class: str? = null) {    style global link_list_css    <nav class={ui_cls(["ui-linklist", divided && "ui-linklist-divided", class])} id={id}         aria-label={heading == null ? label : null} aria-labelledby={heading != null && id != null ? `${id}-heading` : null}>        {heading != null && <p.ui-linklist-heading id={id != null ? `${id}-heading` : null}>{heading}</p>}        <ul>            {for it in items => {                let ext = get(it, "external") == true                <li>                    <a.ui-linklist-link href={it.href} target={ext ? "_blank" : null} rel={ext ? "noopener" : null}>                        {get(it, "icon") != null && <span.ui-linklist-icon aria-hidden="true">{starts_with(it.icon, "M") && len(it.icon) > 2                            ? <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"                                   stroke-linejoin="round"><path d={it.icon}/></svg>                            : it.icon}</span>}                        <span.ui-linklist-text>                            <span.ui-linklist-label>{it.label}{ext && <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>}                                {ext && <span.ui-sr> (opens in a new tab)</span>}</span>                            {get(it, "description") != null && <span.ui-linklist-desc>{it.description}</span>}                        </span>                        {get(it, "meta") != null && <span.ui-linklist-meta>{it.meta}</span>}                        {arrows && <svg.ui-linklist-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>}                    </a>                </li>            }}        </ul>    </nav>}
Thread
56Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.