Feedback

Banner

An announcement across the top of the page in six tones, with a link, closed for the session once dismissed.

#feedback#notification#page#no-js

Demo

Preview

Quillo 1.0 is out: live queries, typed records and a debugger.

See what's new →

MaintenanceSunday 02:00–03:00 UTC: the dashboard will be read-only.

Your data export is ready.

Read the report →

Payments are delayed by up to an hour. We're on it.

Heads upThis is a preview environment; data resets every night.

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

Example

The code of the preview above.

demos/banner.qwe
view BannerDemo() =    <div.demo-stack>        <Banner href="#banner" link="See what's new">Quillo 1.0 is out: live queries, typed records and a debugger.</Banner>        <Banner tone="warning" title="Maintenance" remember="demo-maintenance">Sunday 02:00–03:00 UTC: the dashboard will be read-only.</Banner>        <Banner tone="success" variant="soft" href="#banner" link="Read the report">Your data export is ready.</Banner>        <Banner tone="danger" dismissable={false}>Payments are delayed by up to an hour. We're on it.</Banner>        <Banner tone="neutral" variant="soft" title="Heads up">This is a preview environment; data resets every night.</Banner>    </div>

Source

ui/banner.qwe
// Banner: an announcement across the top of the page, with a link and a close// button. It hides itself when closed, so it works placed straight in a page.////   <Banner href="/changelog" link="See what's new">Quillo 1.0 is out.</Banner>//   <Banner tone="warning" title="Maintenance" remember="maint-0412">Sunday 02:00–03:00 UTC.</Banner>//   <Banner tone="danger" dismissable={false} sticky={true}>Payments are delayed. We're on it.</Banner>//// The message is its children. tone: "accent" (default), "neutral", "info",// "success", "warning" or "danger". variant: "solid" (default), filled with the// tone, or "soft", tinted with a line under it. title: a bold start to the message.// href and link: a link after the message ("Learn more" by default). dismissable:// the close button (true). remember: a name for this announcement; once closed it// stays closed for the rest of the browser session (in sessionStorage), on every// page that shows it, until the name changes. Without it, it shows again on the// next page. sticky: it stays at the top of the window as the page scrolls.// label: its name for screen readers ("Announcement"); it is a region they can// jump to. on_dismiss: called with nothing when it is closed, inside one of your// components.import ui/theme.qwe use ui_clslet banner_css = css`.ui-banner-host { display: contents; }.ui-banner { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 8px 16px;  font: 14px/1.45 var(--ui-font); --t: var(--ui-accent); --ts: var(--ui-accent-soft); --tf: var(--ui-accent-fg); }.ui-banner-neutral { --t: var(--ui-fg); --ts: var(--ui-subtle); --tf: var(--ui-bg); }.ui-banner-info { --t: var(--ui-info); --ts: var(--ui-info-soft); --tf: var(--ui-bg); }.ui-banner-success { --t: var(--ui-success); --ts: var(--ui-success-soft); --tf: var(--ui-bg); }.ui-banner-warning { --t: var(--ui-warning); --ts: var(--ui-warning-soft); --tf: var(--ui-bg); }.ui-banner-danger { --t: var(--ui-danger); --ts: var(--ui-danger-soft); --tf: var(--ui-bg); }.ui-banner-solid { background: var(--t); color: var(--tf); }.ui-banner-soft { background: var(--ts); color: var(--ui-fg); border-bottom: 1px solid color-mix(in srgb, var(--t) 25%, transparent); }.ui-banner-sticky { position: sticky; top: 0; z-index: 40; }.ui-banner-body { display: flex; flex: 1; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 2px 14px;  min-width: 0; text-align: center; }.ui-banner-text { margin: 0; }.ui-banner-text strong { margin-right: 6px; font-weight: 650; }.ui-banner-link { flex: none; color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px;  text-decoration-thickness: 1px; white-space: nowrap; border-radius: 3px; }.ui-banner-soft .ui-banner-link { color: var(--t); }.ui-banner-neutral.ui-banner-soft .ui-banner-link { color: var(--ui-fg); }.ui-banner-link:hover { text-decoration-thickness: 2px; }.ui-banner-link:focus-visible, .ui-banner-x:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }.ui-banner-x { flex: none; display: grid; place-items: center; width: 28px; height: 28px; margin: -4px -6px -4px 0;  border: 0; border-radius: var(--ui-radius-sm); background: transparent; color: inherit; font-size: 20px; line-height: 1;  opacity: .75; cursor: pointer; }.ui-banner-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }.ui-banner-pad { flex: none; width: 22px; }`component Banner(tone: str = "accent", variant: str = "solid", title: str? = null, href: str? = null,                 link: str = "Learn more", dismissable: bool = true, remember: str? = null, sticky: bool = false,                 label: str = "Announcement", on_dismiss = null, class: str? = null, children) {    style global banner_css    state shown = true    let key = remember != null ? `ui-banner:${remember}` : null    let close = () => {        shown = false        if key != null { js("sessionStorage.setItem", key, "1") }        if on_dismiss != null { on_dismiss() }    }    <div class="ui-banner-host" @mount={(_el) => {        if key != null && js("sessionStorage.getItem", key) == "1" { shown = false }    }}>        {shown && <div class={ui_cls(["ui-banner", `ui-banner-${tone}`, `ui-banner-${variant}`, sticky && "ui-banner-sticky", class])}                       role="region" aria-label={label}>            {dismissable && <span.ui-banner-pad></span>}            <div.ui-banner-body>                <p.ui-banner-text>{title != null && <strong>{title}</strong>}{children}</p>                {href != null && <a.ui-banner-link href={href}>{link} →</a>}            </div>            {dismissable && <button.ui-banner-x type="button" aria-label="Dismiss" @click={close}>×</button>}        </div>}    </div>}
Thread
76Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.