Marketing

AnnouncementBar

A slim bar at the top with one message, a badge and a link, closed for good once dismissed.

#marketing#notification#feedback#page#interactive

Demo

Preview

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

Read the post →
New

Teams now get usage-based pricing.

See pricing →

Close it to call on_dismiss.

Maintenance Sunday 02:00–03:00 UTC.

Your export is ready.

Learn more →

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

Example

The code of the preview above.

demos/announcement_bar.qwe
component AnnouncementBarDemoLive() {    state closed = false    <div.demo-stack>        <AnnouncementBar badge="New" tone="neutral" href="#announcement_bar" link="See pricing" on_dismiss={() => { closed = true }}>            Teams now get usage-based pricing.        </AnnouncementBar>        <p.demo-note>{closed ? "Dismissed: on_dismiss was called." : "Close it to call on_dismiss."}</p>    </div>}view AnnouncementBarDemo() =    <div.demo-stack>        <AnnouncementBar href="#announcement_bar" link="Read the post" remember="demo-v2">Quillo 2.0 is out: live queries, typed records and a debugger.</AnnouncementBar>        <AnnouncementBarDemoLive/>        <AnnouncementBar tone="warning" dismissable={false}>Maintenance Sunday 02:00–03:00 UTC.</AnnouncementBar>        <AnnouncementBar tone="success" href="#announcement_bar">Your export is ready.</AnnouncementBar>    </div>

Source

ui/announcement_bar.qwe
// AnnouncementBar: a slim line across the very top of the page, one message and// a link, with a close button. Closed, it stays away. For a taller notice with// a title and tones that scroll with the page, use Banner.////   <AnnouncementBar href="/blog/2.0" link="Read the post" remember="v2">Quillo 2.0 is out.</AnnouncementBar>//   <AnnouncementBar badge="New" tone="neutral" href="/pricing">Teams now get usage-based pricing.</AnnouncementBar>//// The message is its children. badge: a small label before it ("New", "Beta").// href and link: the link after it ("Learn more" by default). tone: "accent"// (default), "neutral", "info", "success", "warning" or "danger", the line's// colour. dismissable: the close button (true). remember: a name for this// announcement; once closed it stays closed in this browser (in localStorage),// 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 as the page scrolls.// label: its name for screen readers ("Announcement"). on_dismiss: called// with nothing when it is closed, inside one of your components.import ui/theme.qwe use ui_clslet announcement_bar_css = css`.ui-announce-host { display: contents; }.ui-announce { display: flex; align-items: center; gap: 10px; min-height: 36px; padding: 6px 12px;  font: 13px/1.4 var(--ui-font); --t: var(--ui-accent); --tf: var(--ui-accent-fg); background: var(--t); color: var(--tf); }.ui-announce-neutral { --t: var(--ui-fg); --tf: var(--ui-bg); }.ui-announce-info { --t: var(--ui-info); --tf: #fff; }.ui-announce-success { --t: var(--ui-success); --tf: #fff; }.ui-announce-warning { --t: var(--ui-warning); --tf: #fff; }.ui-announce-danger { --t: var(--ui-danger); --tf: #fff; }.ui-announce-sticky { position: sticky; top: 0; z-index: 40; }.ui-announce-body { display: flex; flex: 1; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px 12px; min-width: 0; text-align: center; }.ui-announce-badge { flex: none; padding: 1px 7px; border-radius: 999px; background: color-mix(in srgb, var(--tf) 22%, transparent);  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }.ui-announce-text { margin: 0; }.ui-announce-link { flex: none; color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; border-radius: 3px; }.ui-announce-link:hover { text-decoration-thickness: 2px; }.ui-announce-link:focus-visible, .ui-announce-x:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }.ui-announce-x { flex: none; display: grid; place-items: center; width: 24px; height: 24px; margin: -2px -4px -2px 0; border: 0;  border-radius: var(--ui-radius-sm); background: transparent; color: inherit; font-size: 18px; line-height: 1; opacity: .8; cursor: pointer; }.ui-announce-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 16%, transparent); }.ui-announce-pad { flex: none; width: 20px; }`component AnnouncementBar(href: str? = null, link: str = "Learn more", badge: str? = null, tone: str = "accent",                          dismissable: bool = true, remember: str? = null, sticky: bool = false, label: str = "Announcement",                          on_dismiss = null, class: str? = null, children) {    style global announcement_bar_css    state shown = true    let key = remember != null ? `ui-announcement:${remember}` : null    let close = () => {        shown = false        if key != null { js("localStorage.setItem", key, "1") }        if on_dismiss != null { on_dismiss() }    }    <div class="ui-announce-host" @mount={(_el) => {        if key != null && js("localStorage.getItem", key) == "1" { shown = false }    }}>        {shown && <div class={ui_cls(["ui-announce", `ui-announce-${tone}`, sticky && "ui-announce-sticky", class])}                       role="region" aria-label={label}>            {dismissable && <span.ui-announce-pad></span>}            <div.ui-announce-body>                {badge != null && <span.ui-announce-badge>{badge}</span>}                <p.ui-announce-text>{children}</p>                {href != null && <a.ui-announce-link href={href}>{link} →</a>}            </div>            {dismissable && <button.ui-announce-x type="button" aria-label="Dismiss" @click={close}>×</button>}        </div>}    </div>}
Thread
65Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.