# Relative Date Label

> A date field that writes the date back as today, tomorrow, in 3 days, last Friday or 2 weeks ago in the viewer's language, picking the unit that reads best. Use this when a date should be read at a glance as how far away it is, not only as a number.

A shadcn/ui block from the [@tealmac](https://ui.tealmac.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/tealmac/relative-date-label).

- Page, with a live preview: https://shadcn.exchange/r/tealmac/relative-date-label
- Screenshot: https://shadcn.exchange/shot/tealmac/relative-date-label/light.png
- Registry item: https://ui.tealmac.com/r/relative-date-label.json
- Listed: 2026-11-01, source last changed 2026-11-01

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/tealmac/relative-date-label.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@tealmac/date-field`, `@tealmac/date-time-core`

## Files

### `registry/patterns/relative-date-label/relative-date-label.tsx`

```tsx
"use client"

import * as React from "react"

import { DateField } from "@/components/ui/date-field"
import {
  diffDays,
  resolveLocale,
  today as todayISO,
} from "@/components/ui/date-time-core"

export interface RelativeDateLabelProps {
  value?: string | null
  defaultValue?: string | null
  onValueChange?: (value: string | null) => void
  today?: string
  locale?: string
}

/** "tomorrow", "in 3 days", "2 weeks ago", "last year": the unit that reads best. */
export function relativeDateLabel(
  date: string,
  today: string,
  locale?: string
) {
  const n = diffDays(today, date)
  const abs = Math.abs(n)
  const rtf = new Intl.RelativeTimeFormat(resolveLocale(locale), {
    numeric: "auto",
  })
  if (abs < 14) return rtf.format(n, "day")
  if (abs < 60) return rtf.format(Math.round(n / 7), "week")
  if (abs < 365) return rtf.format(Math.round(n / 30.44), "month")
  return rtf.format(Math.round(n / 365.25), "year")
}

export function RelativeDateLabel({
  value,
  defaultValue = null,
  onValueChange,
  today,
  locale,
}: RelativeDateLabelProps) {
  const loc = resolveLocale(locale)
  const now = today ?? todayISO()
  const [inner, setInner] = React.useState<string | null>(defaultValue)
  const date = value === undefined ? inner : value

  return (
    <div className="flex flex-wrap items-center gap-3">
      <DateField
        label="Date"
        locale={loc}
        value={date}
        onValueChange={(next) => {
          if (value === undefined) setInner(next)
          onValueChange?.(next)
        }}
      />
      <p
        role="status"
        className="text-muted-foreground text-sm first-letter:uppercase"
      >
        {date ? relativeDateLabel(date, now, loc) : ""}
      </p>
    </div>
  )
}
```
