Menu

Change language

GitHub repo

Relative Time

relative-timeui

Live relative timestamp — "2 minutes ago", "yesterday", "in 3 days" — via Intl.RelativeTimeFormat. `display` switches the label to relative, absolute, or both. `timeZone` (IANA or `UTC`) formats the clock and tooltip; omit it for the browser local zone. `parseAs` treats naive ISO strings as local or UTC. Renders a semantic <time>. Pass `now` to freeze the clock for tests and SSR.

Installation

$npx shadcn@latest add https://uipkge.dev/r/react/relative-time.json
Named registry:npx shadcn@latest add @uipkge-react/relative-timeInstalls to:components/ui/relative-time/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
date

Instant to display. Accepts a Date, ISO string, or epoch ms.

Date | string | number—required
now

Clock used for the delta. Pass in tests and SSR to keep output stable.

Date | string | number—optional
formatStyle

Intl relative style.

RelativeTimeStyle—optional
numeric

`auto` yields "yesterday"; `always` yields "1 day ago".

RelativeTimeNumeric—optional
locale

BCP 47 locale. Defaults to the runtime locale.

string—optional
display

Visible label: relative (default), absolute clock, or both.

RelativeTimeDisplay—optional
timeZone

IANA zone for absolute text and the title tooltip. Omit for the browser local zone. Pass `UTC` for UTC.

string—optional
parseAs

How to parse date strings with no offset. `local` is JS default; `utc` treats naive ISO as UTC.

RelativeTimeParseAs—optional
updateInterval

Tick interval in ms. `0` freezes the clock.

number—optional

Used by

Files installed (3)

  • components/ui/relative-time/relative-time.tsx2.7 kB
    'use client'
    
    import * as React from 'react'
    import { cn } from '@/lib/utils'
    import {
      formatAbsoluteTime,
      formatVisibleTime,
      toDate,
      type RelativeTimeDisplay,
      type RelativeTimeNumeric,
      type RelativeTimeParseAs,
      type RelativeTimeStyle,
    } from './format-relative-time'
    
    export interface RelativeTimeProps extends Omit<React.TimeHTMLAttributes<HTMLTimeElement>, 'dateTime'> {
      /** Instant to display. Accepts a Date, ISO string, or epoch ms. */
      date: Date | string | number
      /** Clock used for the delta. Pass in tests and SSR to keep output stable. */
      now?: Date | string | number
      /** Intl relative style. */
      formatStyle?: RelativeTimeStyle
      /** `auto` yields "yesterday"; `always` yields "1 day ago". */
      numeric?: RelativeTimeNumeric
      /** BCP 47 locale. Defaults to the runtime locale. */
      locale?: string
      /** Visible label: relative (default), absolute clock, or both. */
      display?: RelativeTimeDisplay
      /** IANA zone for absolute text and the title tooltip. Omit for the browser local zone. Pass `UTC` for UTC. */
      timeZone?: string
      /** How to parse date strings with no offset. `local` is JS default; `utc` treats naive ISO as UTC. */
      parseAs?: RelativeTimeParseAs
      /** Tick interval in ms. `0` freezes the clock. */
      updateInterval?: number
    }
    
    const RelativeTime = React.forwardRef<HTMLTimeElement, RelativeTimeProps>(
      (
        {
          date,
          now,
          formatStyle = 'long',
          numeric = 'auto',
          locale,
          display = 'relative',
          timeZone,
          parseAs = 'local',
          updateInterval = 30_000,
          className,
          children,
          ...props
        },
        ref,
      ) => {
        const [tick, setTick] = React.useState(0)
    
        React.useEffect(() => {
          if (updateInterval <= 0 || now !== undefined) return
          const timer = setInterval(() => setTick((n) => n + 1), updateInterval)
          return () => clearInterval(timer)
        }, [updateInterval, now])
    
        const resolvedDate = toDate(date, parseAs)
        const resolvedNow = now === undefined ? new Date() : toDate(now, parseAs)
        void tick
    
        const label = formatVisibleTime(resolvedDate, resolvedNow, {
          display,
          style: formatStyle,
          numeric,
          locale,
          timeZone,
        })
        const absolute = formatAbsoluteTime(resolvedDate, locale, timeZone)
    
        return (
          <time
            ref={ref}
            data-uipkge=""
            data-slot="relative-time"
            data-display={display}
            data-timezone={timeZone || 'local'}
            data-parse-as={parseAs}
            dateTime={resolvedDate.toISOString()}
            title={absolute}
            className={cn('text-muted-foreground text-sm tabular-nums', className)}
            {...props}
          >
            {children ?? label}
          </time>
        )
      },
    )
    RelativeTime.displayName = 'RelativeTime'
    
    export { RelativeTime }
    
  • components/ui/relative-time/format-relative-time.ts2.3 kB
  • components/ui/relative-time/index.ts0.3 kB

Raw manifest:https://uipkge.dev/r/react/relative-time.json