Feedback

ConnectionStatus

Says when the browser goes offline, as a bar across the top or a pill, and that it is back online for a moment.

#feedback#status#notification#interactive

Demo

Preview
Online

Turn the network off (or the browser's Offline setting) to see it.

A bar across the top of the window shows while offline; it is the default, and nothing shows while all is well.

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

Example

The code of the preview above.

demos/connection_status.qwe
component ConnectionStatusDemoLive() {    state changes = []    <div.demo-stack>        <div.demo-row>            <ConnectionStatus position="inline" seconds={2} on_change={(on) => { changes = push(changes, on ? "online" : "offline") }}/>            <ConnectionStatus position="inline" always={true} seconds={2}/>        </div>        <p.demo-note>{len(changes) == 0 ? "Turn the network off (or the browser's Offline setting) to see it." : `Seen: ${join(changes, ", ")}.`}</p>    </div>}view ConnectionStatusDemo() =    <div.demo-stack>        <ConnectionStatusDemoLive/>        <ConnectionStatus/>        <p.demo-note>A bar across the top of the window shows while offline; it is the default, and nothing shows while all is well.</p>    </div>

Source

ui/connection_status.qwe
// ConnectionStatus: says when the browser loses its connection, and when it is// back. Nothing shows while all is well; offline, a bar (or a pill) says so, and// once back it says "Back online" for a moment.////   <ConnectionStatus/>//   <ConnectionStatus position="inline" offline_text="No connection: changes will be sent when it is back"/>//   <ConnectionStatus always={true} position="inline"/>              a dot that says Online or Offline//// position: "top" (default), a bar fixed across the top of the window, "bottom",// or "inline", a pill in the flow of the page. offline_text ("You are offline"),// online_text ("Back online"): what it says. seconds: how long "Back online"// stays (3). always: shown all the time, with a dot and a word (Online or// Offline), for a status bar. It is a status region: screen readers hear each// change. on_change(online): inside one of your components, called with true or// false when the connection comes or goes.import ui/theme.qwe use ui_clslet connection_status_css = css`.ui-conn-host { display: contents; }.ui-conn { display: inline-flex; align-items: center; gap: 8px; font: 500 14px/1.4 var(--ui-font); color: var(--ui-fg);  --t: var(--ui-danger); --ts: var(--ui-danger-soft); }.ui-conn-online { --t: var(--ui-success); --ts: var(--ui-success-soft); }.ui-conn-top, .ui-conn-bottom { position: fixed; left: 0; right: 0; z-index: 60; justify-content: center; min-height: 40px; padding: 8px 16px;  background: var(--ts); border-bottom: 1px solid color-mix(in srgb, var(--t) 30%, transparent); animation: ui-conn-in .2s ease-out; }.ui-conn-top { top: 0; }.ui-conn-bottom { bottom: 0; border-bottom: 0; border-top: 1px solid color-mix(in srgb, var(--t) 30%, transparent); }.ui-conn-inline { padding: 5px 12px 5px 10px; border-radius: 999px; background: var(--ts); font-size: 13px; }.ui-conn-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--t); }.ui-conn-offline .ui-conn-dot { animation: ui-conn-blink 1.2s ease-in-out infinite; }.ui-conn-icon { flex: none; width: 18px; height: 18px; color: var(--t); }@keyframes ui-conn-in { from { opacity: 0; transform: translateY(-6px); } }@keyframes ui-conn-blink { 50% { opacity: .35; } }@media (prefers-reduced-motion: reduce) { .ui-conn-top, .ui-conn-bottom { animation: none; } .ui-conn-offline .ui-conn-dot { animation: none; } }`component ConnectionStatus(position: str = "top", offline_text: str = "You are offline", online_text: str = "Back online",                           seconds: int = 3, always: bool = false, on_change = null, class: str? = null) {    style global connection_status_css    state online = true    state back = 0          // counts the times it came back, so "Back online" shows afresh each time    state told = 0          // the `back` already hidden    let celebrating = online && back > told    if celebrating { every(seconds * 1000, () => { told = back }) }    let shown = !online || celebrating || always    let word = online ? (celebrating ? online_text : "Online") : offline_text    <div class="ui-conn-host" @mount={(_el) => {        online = js("navigator.onLine") != false        let w = js("window")        let went = (_e = null) => { online = false; on_change && on_change(false) }        let came = (_e = null) => { online = true; back += 1; on_change && on_change(true) }        w.addEventListener("offline", went)        w.addEventListener("online", came)        () => { w.removeEventListener("offline", went); w.removeEventListener("online", came) }    }}>        <div class={ui_cls(["ui-conn-host-inner"])} role="status">            {shown && <div class={ui_cls(["ui-conn", `ui-conn-${position}`, online ? "ui-conn-online" : "ui-conn-offline", class])}>                {always                    ? <span.ui-conn-dot aria-hidden="true"></span>                    : <svg.ui-conn-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.01"/>                          {!online && <path d="M3 3l18 18"/>}                      </svg>}                <span>{word}</span>            </div>}        </div>    </div>}
Thread
67Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.