Feedback

ErrorPage

A 404 or 500 page: the code large, what it means, a search box if wanted, and links to go on from.

#feedback#page#status#navigation#no-js

Demo

Preview

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

Example

The code of the preview above.

demos/error_page.qwe
view ErrorPageDemo() =    <div.demo-stack>        <ErrorPage id="error-page-demo-404" search="#error_page"                   links={[{ label: "Go home", href: "#error_page" }, { label: "Read the docs", href: "#error_page" }]}/>        <div.demo-row style="align-items: stretch">            <div style="flex: 1; min-width: 260px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius)">                <ErrorPage id="error-page-demo-500" code={500} reference="req_8f3a21" home="#error_page"/>            </div>            <div style="flex: 1; min-width: 260px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius)">                <ErrorPage code={403} title="Members only" text="This area is for members of the workspace. Ask an admin to invite you."                           links={[{ label: "Sign in", href: "#error_page" }, { label: "Go home", href: "#error_page" }]}/>            </div>        </div>    </div>

Source

ui/error_page.qwe
// ErrorPage: a page for an HTTP error, with the code large, what it means, and// where to go from here. A route can answer with it:////   route GET /*rest = respond(404, <html><body class="ui-root"><ErrorPage code={404}/></body></html>)//   <ErrorPage code={500} title="Something broke" text="We have been told. Try again in a minute."//              links={[{ label: "Status page", href: "https://status.example.com" }]}/>//// code: the HTTP status (404). title and text: by default, what the code means, for 400, 401, 403, 404, 408, 410, 429, 500, 502, 503 and 504.// links: maps of { label, href } shown as buttons, the first one solid; by// default one to the home page ("Go home", "/"). home: that link's href.// children: more HTML under the text (a list of likely pages).// search: an action URL; a search box is shown that sends `q` there (for a 404).// reference: a short id to quote to support, shown small. size: "md" (default) or "lg", for a page of its own.import ui/theme.qwe use ui_clslet error_page_css = css`.ui-errpage { display: grid; justify-items: center; gap: 10px; padding: 56px 24px; text-align: center;  font: 15px/1.55 var(--ui-font); color: var(--ui-fg); }.ui-errpage-code { font: 800 72px/1 var(--ui-font); letter-spacing: -.03em; color: var(--ui-accent-soft);  -webkit-text-stroke: 1.5px var(--ui-accent); font-variant-numeric: tabular-nums; }.ui-errpage-title { margin: 4px 0 0; font-size: 24px; font-weight: 650; line-height: 1.25; }.ui-errpage-text { max-width: 46ch; color: var(--ui-muted); }.ui-errpage-text > :first-child { margin-top: 0; }.ui-errpage-text > :last-child { margin-bottom: 0; }.ui-errpage-search { display: flex; gap: 8px; width: min(100%, 420px); margin-top: 12px; }.ui-errpage-search input { flex: 1; min-width: 0; height: 38px; padding: 0 12px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm);  background: var(--ui-surface); color: var(--ui-fg); font: 14px var(--ui-font); }.ui-errpage-search input:focus { outline: none; border-color: var(--ui-accent); box-shadow: var(--ui-focus); }.ui-errpage-search button, .ui-errpage-link { display: inline-flex; align-items: center; justify-content: center; height: 38px; padding: 0 16px;  border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm); background: var(--ui-surface); color: var(--ui-accent);  font: 500 14px/1 var(--ui-font); text-decoration: none; cursor: pointer; white-space: nowrap; }.ui-errpage-search button:hover, .ui-errpage-link:hover { border-color: var(--ui-accent); background: var(--ui-accent-soft); }.ui-errpage-search button:focus-visible, .ui-errpage-link:focus-visible { outline: none; box-shadow: var(--ui-focus); }.ui-errpage-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 14px; }.ui-errpage-link-main { background: var(--ui-accent); border-color: transparent; color: var(--ui-accent-fg); }.ui-errpage-link-main:hover { background: color-mix(in srgb, var(--ui-accent) 88%, var(--ui-fg)); }.ui-errpage-ref { margin-top: 18px; color: var(--ui-muted); font-size: 12px; font-family: var(--ui-mono); }.ui-errpage-lg { padding: 96px 24px; min-height: 70vh; align-content: center; }.ui-errpage-lg .ui-errpage-code { font-size: 112px; }.ui-errpage-lg .ui-errpage-title { font-size: 30px; }@media (max-width: 480px) { .ui-errpage-code { font-size: 56px; } .ui-errpage-lg .ui-errpage-code { font-size: 80px; } }`// What an HTTP status means, as a title and a sentence.fn error_page_words(code: int) -> list =    match code {        400 => ["Bad request", "The request could not be understood. Check the address and try again."]        401 => ["Sign in to continue", "You need to be signed in to see this page."]        403 => ["No access", "You do not have permission to see this page."]        404 => ["Page not found", "The page may have moved, or the address has a typo."]        408 => ["The request timed out", "It took too long. Try again."]        410 => ["This page is gone", "It was removed and is not coming back."]        429 => ["Too many requests", "Slow down a little and try again in a minute."]        500 => ["Something went wrong", "It is on our side, and we have been told. Try again in a minute."]        502 => ["Bad gateway", "A server on the way did not answer properly. Try again in a minute."]        503 => ["Down for a moment", "The service is being worked on. Try again shortly."]        504 => ["The server took too long", "It did not answer in time. Try again in a minute."]        _ => ["Something went wrong", "Try again, or go back to the home page."]    }view ErrorPage(code: int = 404, title: str? = null, text: str? = null, links: list? = null, home: str = "/", search: str? = null,               reference: str? = null, size: str = "md", id: str? = null, class: str? = null, children) {    style global error_page_css    let words = error_page_words(code)    let shown = links ?? [{ label: "Go home", href: home }]    <section class={ui_cls(["ui-errpage", size != "md" && `ui-errpage-${size}`, class])} id={id} role="alert"             aria-labelledby={id != null ? `${id}-title` : null}>        <span.ui-errpage-code aria-hidden="true">{code}</span>        <h1.ui-errpage-title id={id != null ? `${id}-title` : null}><span.ui-sr>Error {code}: </span>{title ?? words[0]}</h1>        <div.ui-errpage-text>{text ?? words[1]}</div>        {children}        {search != null && <form.ui-errpage-search method="get" action={search} role="search">            <input type="search" name="q" aria-label="Search" placeholder="Search the site"/>            <button type="submit">Search</button>        </form>}        {len(shown) > 0 && <div.ui-errpage-links>            {for [i, l] in enumerate(shown) => <a key={i} class={ui_cls(["ui-errpage-link", i == 0 && "ui-errpage-link-main"])} href={l.href}>{l.label}</a>}        </div>}        {reference != null && <span.ui-errpage-ref>Reference {reference}</span>}    </section>}
Thread
56Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.