bigbullui logobigbullui
Componentmedia

TimeAgo

Relative time display showing '5 MIN AGO' with live re-render tick every 30s

Preview

Live Preview
0 SECS AGO

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add time-ago

Or install the full npm package:

npm install bigbullui

Usage

import { TimeAgo } from "@/components/ui/time-ago"

<TimeAgo date={new Date()} live />

Source code

time-ago.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

"use client";
import * as React from "react";
import { cn } from "./lib/utils";

export type TimeAgoProps = {
  date: Date | number | string;
  live?: boolean;
};

function formatTimeAgo(date: Date | number | string): string {
  const now = new Date();
  const target = typeof date === "number" ? new Date(date) : new Date(date);
  const diffMs = now.getTime() - target.getTime();
  const diffSec = Math.floor(diffMs / 1000);
  const diffMin = Math.floor(diffSec / 60);
  const diffHour = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHour / 24);

  if (diffDay > 0) {
    return `${diffDay} DAY${diffDay === 1 ? "" : "S"} AGO`;
  }
  if (diffHour > 0) {
    return `${diffHour} HR${diffHour === 1 ? "" : "S"} AGO`;
  }
  if (diffMin > 0) {
    return `${diffMin} MIN${diffMin === 1 ? "" : "S"} AGO`;
  }
  return `${diffSec} SEC${diffSec === 1 ? "" : "S"} AGO`;
}

const TimeAgo = ({ date, live = true }: TimeAgoProps) => {
  const [text, setText] = React.useState(() => formatTimeAgo(date));

  if (live) {
    React.useEffect(() => {
      const interval = setInterval(() => {
        setText(formatTimeAgo(date));
      }, 30_000);
      return () => clearInterval(interval);
    }, [date]);
  }

  return (
    <div
      className={cn(
        "font-mono text-[10px] uppercase tracking-[0.15em] text-muted-foreground",
        "animate-[fade-in-up_0.3s_ease-out_both]",
        "motion-reduce:animate-none"
      )}
    >
      {text}
    </div>
  );
};

export { TimeAgo };

Props

PropTypeDescription
dateDate | number | stringThe date to calculate relative time from
livebooleanWhether to live-update the relative time every 30s