agency-web/app/components/Ticker.tsx

67 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useEffect, useRef, useState } from "react";
type Item = { v: string; up?: boolean; label: string };
/**
* A Bloomberg-style revenue ticker tape. Infinite CSS marquee with live-
* feeling deltas. The visible tape is aria-hidden (decorative motion); a
* single screen-reader summary conveys the same facts statically.
*
* Numbers are illustrative SAMPLES (matches the content note).
*/
const ITEMS: Item[] = [
{ v: "+$2.41M", up: true, label: "Q ARR added" },
{ v: "3.8×", up: true, label: "ROAS" },
{ v: "34%", up: true, label: "CPA" },
{ v: "+217%", up: true, label: "Demo reqs" },
{ v: "+183%", up: true, label: "Organic" },
{ v: "+128", up: true, label: "Bookings/mo" },
{ v: "+52%", up: true, label: "ROAS 90d" },
{ v: "92%", up: true, label: "Retention" },
{ v: "+$40M", up: true, label: "Client revenue" },
];
export default function Ticker() {
const [tick, setTick] = useState(0);
const reduce = useRef(false);
// gentle "last digit flicker" to feel live (skipped on reduced motion)
useEffect(() => {
reduce.current = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (reduce.current) return;
const id = setInterval(() => setTick((t) => t + 1), 2600);
return () => clearInterval(id);
}, []);
const Row = ({ aria }: { aria: boolean }) => (
<ul className="ticker__row" aria-hidden={aria ? undefined : true}>
{ITEMS.map((it, i) => (
<li className="ticker__item" key={i}>
<span className="ticker__arr" aria-hidden="true">
{it.up ? "▲" : "▼"}
</span>
<span className="ticker__val">{it.v}</span>
<span className="ticker__lab">{it.label}</span>
</li>
))}
</ul>
);
return (
<div className="ticker" data-tick={tick % 2}>
{/* SR-only static summary of the same data */}
<p className="sr-only">
Sample results across recent client programs: 3.8 times average return
on ad spend, plus 217 percent qualified demo requests, plus 183 percent
organic traffic, 92 percent client retention, and over 40 million
dollars in client revenue generated.
</p>
<div className="ticker__track" aria-hidden="true">
<Row aria />
<Row aria />
</div>
</div>
);
}