Signature
Ticker
Scrolling status marquee.
● LIVE
SUBNET NOMINALLINK 0x4A2● ONLINETRACE 0%AUTH VERIFIEDUPLINK STABLE0x4A2 // SYNCEDLATENCY 42MS● SIGNAL LOCKEDCHANNEL CLEAR
"use client";import { Ticker } from "@/registry/okibi/ui/ticker";export default function TickerDemo() { return ( <Ticker className="w-full" // Enough atoms that the duplicated track is comfortably wider than a phone // viewport, so the 0 → -50% loop stays gapless on small screens. items={[ "SUBNET NOMINAL", "LINK 0x4A2", "● ONLINE", "TRACE 0%", "AUTH VERIFIED", "UPLINK STABLE", "0x4A2 // SYNCED", "LATENCY 42MS", "● SIGNAL LOCKED", "CHANNEL CLEAR", ]} /> );}npx shadcn@latest add https://okibi.cndr.dev/r/ticker.jsonInstallation
Install the theme first, then add the component:
npx shadcn@latest add https://okibi.cndr.dev/r/ticker.jsonCopy the source from the Code tab above into components/ui/ticker.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.
Usage
import { Ticker } from "@/components/ui/ticker"
<Ticker items={["UPLINK STABLE", "RX 0x4A2", "PWR 98%"]} speed={20} />Examples
Speed
Tune the marquee loop with speed (seconds per cycle) and swap the inter-item glyph with separator.
● LIVE
SUBNET NOMINALLINK 0x4A2● ONLINETRACE 0%AUTH VERIFIED
SUBNET NOMINALLINK 0x4A2● ONLINETRACE 0%AUTH VERIFIED
"use client";import { Ticker } from "@/registry/okibi/ui/ticker";const ITEMS = [ "SUBNET NOMINAL", "LINK 0x4A2", "● ONLINE", "TRACE 0%", "AUTH VERIFIED",];export default function SpeedDemo() { return ( <div className="w-full space-y-3"> <Ticker className="w-full" items={ITEMS} separator="//" speed={10} /> <Ticker className="w-full" items={ITEMS} separator="//" speed={40} /> </div> );}API Reference
Ticker
| Prop | Type | Default | Description |
|---|---|---|---|
items | ReactNode[] | – | The marquee items. |
separator | ReactNode | "+" | Glyph rendered between items. Defaults to a signal +. |
speed | number | 20 | Loop duration in seconds. |
Accessibility
- A WCAG 2.2.2 stop mechanism is built in: the track is
group-hover:/group-focus-within:paused, and the strip is focusable (tabIndex={0}) with anaria-labelof "Status ticker", so keyboard users can halt the scroll. - The scroll pauses on hover and on focus, giving pointer and keyboard users a way to stop the moving content.
- Under
prefers-reduced-motion(handled globally) the track is simply parked, not hidden — the content stays fully readable. - The duplicated sequence that makes the loop gapless is
aria-hidden, and the inter-item separator isaria-hidden+select-none, so each status is read exactly once.
Guidelines
Do
- Feed it short status atoms via
items— "UPLINK STABLE", "RX 0x4A2", "PWR 98%". - Adjust the loop with
speed(seconds) and swap the inter-item glyph throughseparator. - Provide enough items to fill the viewport width so the seamless loop has no mid-cycle gap.
Don't
- Do not put links, buttons or other interactive nodes in
items; the duplicated copy isaria-hiddenand the strip itself takes focus to pause. - Do not use it for content a reader must catch in full — it is an ambient status marquee, not primary copy.