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-agoOr install the full npm package:
npm install bigbulluiUsage
import { TimeAgo } from "@/components/ui/time-ago"
<TimeAgo date={new Date()} live />Source code
time-ago.tsxZero 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
| Prop | Type | Description |
|---|---|---|
| date | Date | number | string | The date to calculate relative time from |
| live | boolean | Whether to live-update the relative time every 30s |