OfflineBanner
A banner across the top of the page for as long as the browser is offline, gone by itself when the connection is back.
Demo
Nothing shows while online. Turn the network off to see the banners.
The second is the default: fixed across the top of the window, with a Try again button here.
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/offline_banner.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/offline_banner.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/offline_banner.qwe
component OfflineBannerDemoLive() { state seen = [] <div.demo-stack> <OfflineBanner sticky={false} title="No connection." text="You can keep writing: your changes are sent when it is back." on_change={(on) => { seen = push(seen, on ? "online" : "offline") }}/> <p.demo-note>{len(seen) == 0 ? "Nothing shows while online. Turn the network off to see the banners." : `Seen: ${join(seen, ", ")}.`}</p> </div>}view OfflineBannerDemo() = <div.demo-stack> <OfflineBannerDemoLive/> <OfflineBanner reload={true}/> <p.demo-note>The second is the default: fixed across the top of the window, with a Try again button here.</p> </div>Source
ui/offline_banner.qwe
// OfflineBanner: a banner across the top of the page for as long as the browser// is offline, saying what still works; it goes by itself when the connection is// back. Nothing shows while online.//// <OfflineBanner/>// <OfflineBanner title="No connection" text="You can keep writing: your changes are sent when it is back." sticky={false}/>//// title ("You are offline"), text ("Some things may not work until the// connection is back."): what it says. sticky: fixed across the top of the// window (true); false puts it in the flow of the page where it is written.// dismissable: a close button that hides it for this outage (true); it shows// again the next time the connection drops. reload: a "Try again" button that// reloads the page (false). It is an alert, so screen readers hear it at once.// on_change(online): inside one of your components, called with true or false// as the connection comes and goes. (ConnectionStatus is the smaller cousin: a// pill or a dot, and "Back online" when it returns.)import ui/theme.qwe use ui_clslet offline_banner_css = css`.ui-offline-host { display: contents; }.ui-offline { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: var(--ui-warning-soft); color: var(--ui-fg); border-bottom: 1px solid color-mix(in srgb, var(--ui-warning) 35%, transparent); font: 14px/1.45 var(--ui-font); }.ui-offline-sticky { position: fixed; top: 0; left: 0; right: 0; z-index: 60; box-shadow: var(--ui-shadow); animation: ui-offline-in .2s ease-out; }.ui-offline-flow { border: 1px solid color-mix(in srgb, var(--ui-warning) 35%, transparent); border-radius: var(--ui-radius-sm); }.ui-offline-icon { flex: none; width: 20px; height: 20px; color: var(--ui-warning); }.ui-offline-body { flex: 1; min-width: 0; }.ui-offline-title { font-weight: 600; margin-right: 6px; }.ui-offline-text { color: color-mix(in srgb, var(--ui-fg) 80%, transparent); }.ui-offline-btn { flex: none; height: 30px; padding: 0 12px; border: 1px solid color-mix(in srgb, var(--ui-warning) 45%, var(--ui-border)); border-radius: var(--ui-radius-sm); background: var(--ui-surface); color: var(--ui-fg); font: 500 13px/1 var(--ui-font); cursor: pointer; }.ui-offline-btn:hover { background: var(--ui-subtle); }.ui-offline-x { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border: 0; border-radius: var(--ui-radius-sm); background: transparent; color: inherit; font-size: 20px; line-height: 1; opacity: .7; cursor: pointer; }.ui-offline-x:hover { opacity: 1; background: color-mix(in srgb, var(--ui-warning) 18%, transparent); }.ui-offline-btn:focus-visible, .ui-offline-x:focus-visible { outline: none; box-shadow: var(--ui-focus); }@keyframes ui-offline-in { from { transform: translateY(-100%); } }@media (prefers-reduced-motion: reduce) { .ui-offline-sticky { animation: none; } }`component OfflineBanner(title: str = "You are offline", text: str = "Some things may not work until the connection is back.", sticky: bool = true, dismissable: bool = true, reload: bool = false, on_change = null, class: str? = null) { style global offline_banner_css state online = true state closed = false <div class="ui-offline-host" @mount={(_el) => { online = js("navigator.onLine") != false let w = js("window") let went = (_e = null) => { online = false; closed = false; on_change && on_change(false) } let came = (_e = null) => { online = true; on_change && on_change(true) } w.addEventListener("offline", went) w.addEventListener("online", came) () => { w.removeEventListener("offline", went); w.removeEventListener("online", came) } }}> {!online && !closed && <div class={ui_cls(["ui-offline", sticky ? "ui-offline-sticky" : "ui-offline-flow", class])} role="alert"> <svg.ui-offline-icon viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5a10 10 0 0 1 14 0M8.5 16a5 5 0 0 1 7 0M12 19.5h.01M3 3l18 18"/></svg> <div.ui-offline-body><span.ui-offline-title>{title}</span><span.ui-offline-text>{text}</span></div> {reload && <button.ui-offline-btn type="button" @click={() => { js("location.reload") }}>Try again</button>} {dismissable && <button.ui-offline-x type="button" aria-label="Dismiss" @click={() => { closed = true }}>×</button>} </div>} </div>}Related
LiveAnnouncerA hidden aria-live region the page writes messages to with live_announcer_say(), politely or at once.6 views · 6 downloadsConnectionStatusSays when the browser goes offline, as a bar across the top or a pill, and that it is back online for a moment.6 views · 7 downloadsNotificationDotA small dot or a count on the corner of anything, in tones and four positions, with a label for screen readers.5 views · 7 downloadsSnackbarA short message along the bottom of the window with one action, shown from anywhere by calling snackbar_show().6 views · 6 downloadsNotificationListNotifications grouped by day (Today, Yesterday, then dates), read or unread, with links, mark-read and dismiss buttons and Mark all as read.7 views · 6 downloadsConfettiA burst of confetti over the page on a canvas, fired by a button, on mount, or by confetti_fire().6 views · 10 downloads
Thread
Thread 0 posts
On OfflineBanner: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.