HTML 77.2%
TypeScript 10.5%
Python 9.6%
JavaScript 2.5%
1'use client';2import { useEffect, useState } from 'react';3import { cn } from '@/lib/cn';4import { fmtAgo } from '@/lib/format';56/** Green live dot with optional pulse ring. */7export function Dot({ pulse = false, className, tone = 'positive' }: { pulse?: boolean; className?: string; tone?: 'positive' | 'warning' | 'danger' | 'muted' }) {8 return <span className={cn('dot', pulse && 'pulse', tone === 'warning' && 'bg-warning', tone === 'danger' && 'bg-danger', tone === 'muted' && 'bg-ink-3', className)} aria-hidden />;9}1011/** "3 min ago" that re-renders every 30 s. Renders the server value first (no hydration mismatch: same formatting). */12export function LiveAgo({ at, prefix = '', className }: { at: string | null | undefined; prefix?: string; className?: string }) {13 const [now, setNow] = useState<number | null>(null);14 useEffect(() => {15 setNow(Date.now());16 const t = setInterval(() => setNow(Date.now()), 30_000);17 return () => clearInterval(t);18 }, []);19 return (20 <time dateTime={at ?? undefined} className={cn('tnum', className)} suppressHydrationWarning>21 {prefix}22 {fmtAgo(at, now ?? undefined)}23 </time>24 );25}26