Ticker
A news ticker: a labelled strip of headlines sliding past, each a link when it has one, in CSS alone.
Demo
- Quillo 0.5 ships with live data over one WebSocket
- Rain expected along the coast tonight
- Final: Benfica 2 – 1 Porto
- Metro line B closed this weekend for works
- Markets open higher after a quiet night
- Vote count at 62%
- Turnout 71%
- Results at 22:00
- All systems normal
- Last incident 41 days ago
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/ticker.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/ticker.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/ticker.qwe
let ticker_demo_news = [ { text: "Quillo 0.5 ships with live data over one WebSocket", href: "https://quillolang.org/blog/0.5" }, "Rain expected along the coast tonight", { text: "Final: Benfica 2 – 1 Porto", href: "https://example.com/match" }, "Metro line B closed this weekend for works", "Markets open higher after a quiet night",]view TickerDemo() = <div.demo-stack> <Ticker label="Breaking" items={ticker_demo_news} speed={28}/> <Ticker label="Live" tone="danger" speed={40} items={["Vote count at 62%", "Turnout 71%", "Results at 22:00"]}/> <Ticker label="Status" tone="success" items={["All systems normal", "Last incident 41 days ago"]} name="Service status"/> </div>Source
ui/ticker.qwe
// Ticker: a news ticker: a label at the left ("Breaking", "Live") and headlines// sliding past it without end, each a link when it has one. CSS alone moves it;// it pauses while the pointer or the focus is on it, and stands still (scrolling// by hand) for people who ask their system for less motion.//// <Ticker label="Breaking" items={["Markets open higher", "Rain expected tonight"]}/>// <Ticker label="Live" tone="danger" speed={40} items={[{ text: "Final: 2–1", href: "/match/9" }, ...]}/>//// items: strings, or maps of { text, href? }. label: the text at the left;// tone: its colour, "accent" (default), "danger", "success" or "neutral".// speed: seconds for one full loop (30). name: what screen readers call the// ticker (the label by default); they read the items once.import ui/theme.qwe use ui_clslet ticker_css = css`.ui-ticker { display: flex; align-items: stretch; overflow: hidden; width: 100%; border: 1px solid var(--ui-border); border-radius: var(--ui-radius-sm); background: var(--ui-surface); color: var(--ui-fg); font: 14px/1.4 var(--ui-font);}.ui-ticker-label { flex: none; display: flex; align-items: center; padding: 8px 14px; background: var(--ui-accent); color: var(--ui-accent-fg); font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;}.ui-ticker-danger .ui-ticker-label { background: var(--ui-danger); color: #fff; }.ui-ticker-success .ui-ticker-label { background: var(--ui-success); color: #fff; }.ui-ticker-neutral .ui-ticker-label { background: var(--ui-fg); color: var(--ui-bg); }.ui-ticker-view { flex: 1; min-width: 0; overflow: hidden; mask-image: linear-gradient(to right, transparent, #000 24px, #000 calc(100% - 24px), transparent); -webkit-mask-image: linear-gradient(to right, transparent, #000 24px, #000 calc(100% - 24px), transparent);}.ui-ticker-track { display: flex; width: max-content; height: 100%; animation: ui-ticker var(--t, 30s) linear infinite; }.ui-ticker:hover .ui-ticker-track, .ui-ticker:focus-within .ui-ticker-track { animation-play-state: paused; }.ui-ticker-list { display: flex; flex: none; align-items: center; margin: 0; padding: 0 0 0 20px; list-style: none; }.ui-ticker-list li { display: flex; align-items: center; white-space: nowrap; }.ui-ticker-list li::after { content: ""; width: 5px; height: 5px; margin: 0 20px; border-radius: 50%; background: var(--ui-strong); }.ui-ticker-list a { color: inherit; text-decoration: none; }.ui-ticker-list a:hover { color: var(--ui-accent); text-decoration: underline; }.ui-ticker-list a:focus-visible { outline: none; box-shadow: var(--ui-focus); border-radius: 3px; }@keyframes ui-ticker { to { transform: translateX(-50%); } }@media (prefers-reduced-motion: reduce) { .ui-ticker-view { overflow-x: auto; mask-image: none; -webkit-mask-image: none; } .ui-ticker-track { animation: none; } .ui-ticker-list[aria-hidden] { display: none; }}`fn ticker_items(items: list) -> list = items | map((it) => type_of(it) == "map" ? { text: str(it.text), href: get(it, "href") } : { text: str(it), href: null })view Ticker(items: list = [], label: str = "News", tone: str = "accent", speed: num = 30, name: str? = null, class: str? = null) { style global ticker_css let its = ticker_items(items) let row = (hidden: bool) => <ul.ui-ticker-list aria-hidden={hidden ? "true" : null}> {for [i, it] in enumerate(its) => <li key={i}> {it.href != null ? <a href={it.href} tabindex={hidden ? "-1" : null}>{it.text}</a> : it.text} </li>} </ul> <div class={ui_cls(["ui-ticker", tone != "accent" && `ui-ticker-${tone}`, class])} role="marquee" aria-label={name ?? label} style={`--t: ${speed}s`}> <span.ui-ticker-label aria-hidden="true">{label}</span> <div.ui-ticker-view> <div.ui-ticker-track> {row(false)} {row(true)} </div> </div> </div>}Related
MarqueeContent scrolling sideways without end, in CSS alone: seamless, paused on hover, still when motion is reduced.8 views · 6 downloadsAudioPlayerAn audio clip with play, a seek bar that says the time, and a button cycling through playback speeds.6 views · 7 downloadsCameraCaptureTakes a photo with the camera into a hidden input as a data URL, with retake, and says so when there is no camera.6 views · 6 downloadsCoverImageA wide picture with a title, subtitle and actions over a gradient, in three heights.7 views · 7 downloadsEmbedFrameAnother page in a frame that keeps its shape and fills its width, with a title, permissions and a sandbox.5 views · 4 downloadsFigureAn image (or anything) with a caption and a credit under it, as a figure with its figcaption.7 views · 8 downloads
Thread
Thread 0 posts
On Ticker: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.