Nasaq
Components

RealtimeCounter

A live active-users card - a large count, a per-minute mini chart and ranked lists such as top pages and countries.

PreviewOpen ↗

Code

import { RealtimeCounter } from "@fadymondy/nasaq/web";export function Now() {  return (    <RealtimeCounter      value={87}      perMinute={[62, 70, 66, 81, 79, 87]}      sections={[{ id: "pages", title: "Top active pages", ltr: true, rows: [{ id: "a", label: "/pricing", value: 14 }] }]}    />  );}

Analytics · beta

Live examples and controls: RealtimeCounter in the lab.

Install

npx shadcn@latest add https://docs.nasaqui.com/r/realtime-counter.json

RealtimeCounter shows how many people are on the site right now. The count is announced politely to screen readers, a bar chart shows users per minute, and sections list the top active pages or countries. The host polls and passes new values; the component only presents them.

When to use

  • The "Right now" card of an analytics page.
  • Live counts with a short history.

When not to use

Import

import { RealtimeCounter } from "@fadymondy/nasaq/web";

Quick start

import { RealtimeCounter } from "@fadymondy/nasaq/web";

export function Now() {
  return (
    <RealtimeCounter
      value={87}
      perMinute={[62, 70, 66, 81, 79, 87]}
      sections={[{ id: "pages", title: "Top active pages", ltr: true, rows: [{ id: "a", label: "/pricing", value: 14 }] }]}
    />
  );
}

Anatomy

RealtimeCounter        data-slot="realtime-counter"  (a Card)
  live dot + count     aria-live="polite" region
  MiniBar              users per minute
  sections             ranked rows

API

RealtimeCounter

PropTypeDefaultDescription
valuenumberrequiredActive users now.
perMinutereadonly number[]noneUsers per minute, oldest first.
sectionsreadonly RealtimeSection[]none{ id, title, rows: { id, label, value }[], ltr? }.
updatedAtnumber | Date | stringnoneWhen the data was read; shown as a relative time.
livebooleantrueShows the pulsing dot; set false when polling is paused.
title / descriptionReactNodenoneCard header.
classNamestringnoneExtra classes on the root.
labelsPartial<RealtimeCounterLabels>noneReplace any built-in English or Arabic string.

Examples

Polling from the host:

import { RealtimeCounter } from "@fadymondy/nasaq/web";
import { useEffect, useState } from "react";

export function Live({ read }: { read: () => Promise<number> }) {
  const [n, setN] = useState(0);
  useEffect(() => {
    const id = setInterval(() => void read().then(setN), 5000);
    return () => clearInterval(id);
  }, [read]);
  return <RealtimeCounter value={n} />;
}

Paused:

import { RealtimeCounter } from "@fadymondy/nasaq/web";

export const Paused = () => <RealtimeCounter value={0} live={false} />;

Accessibility

The count is in a polite live region, so changes are announced without interrupting. The pulsing dot is decorative and stops under prefers-reduced-motion. The mini chart has a text summary.

RTL & i18n

  • Sections align to the inline start; the mini chart runs right to left.
  • Set ltr on a section of paths.
  • Every figure uses the active locale with Western digits and is bidi-isolated (Num), so +12.4% keeps its order in Arabic.

Styling & tokens

  • Colours come from tokens (--primary, --nq-success, --nq-warning, --nq-danger, --nq-tag-*); never pass raw hex.
  • Live dot uses --nq-success.

Do / Don't

  • Do throttle polling to every few seconds.
  • Don't animate the count digit by digit.

Lab

https://docs.nasaqui.com/?path=/docs/components-analytics-realtime-counter--docs

On this page