RelativeTime Component

The RelativeTime component displays human-readable relative timestamps with automatic updates and tooltip functionality.

Overview

This utility component converts timestamps to relative time strings (e.g., “5 minutes ago”, “2 hours ago”) with intelligent refresh intervals and optional tooltip showing exact timestamp. It’s designed for displaying message timestamps, last updated times, and other temporal information.

Location

src/components/RelativeTime.tsx

Features

Flexible Input Support

  • Accepts both timestamp numbers and Date objects
  • Backward compatible with existing timestamp prop
  • Graceful handling of invalid or missing timestamps

Intelligent Update Intervals

  • Recent (< 1 minute): Updates every 10 seconds
  • Hour old (< 1 hour): Updates every minute
  • Day old (< 1 day): Updates every 5 minutes
  • Older: Updates every hour

Stable Rendering

  • Prevents timestamp changes during re-renders using useRef
  • Ensures consistent display even when parent component updates
  • Single initialization prevents time drift issues

Optional Tooltip

  • Shows exact timestamp on hover when showTooltip={true}
  • Uses locale-specific formatting with toLocaleString()
  • Can be disabled for simple text display

Props Interface

interface TimeProps {
  timestamp?: number;           // Original API for backward compatibility
  date?: Date;                 // New API to support Date objects
  className?: string;          // CSS classes (default: "text-xs text-muted-foreground/60")
  fallback?: string;           // Text when timestamp missing (default: "Never")
  showTooltip?: boolean;       // Enable tooltip (default: true)
}

Usage Examples

Basic Usage

import { RelativeTime } from '@/components/RelativeTime';

// Using timestamp
<RelativeTime timestamp={Date.now() - 300000} />
// Output: "5 minutes ago"

// Using Date object
<RelativeTime date={new Date('2024-01-01')} />
// Output: "about 2 months ago"

Custom Styling

<RelativeTime 
  timestamp={message.createdAt}
  className="text-sm text-blue-600"
  fallback="Unknown time"
  showTooltip={false}
/>

In Message Components

function MessageItem({ message }) {
  return (
    <div className="message">
      <div className="content">{message.text}</div>
      <RelativeTime 
        timestamp={message.timestamp}
        className="text-xs text-gray-500"
      />
    </div>
  );
}

Dependencies

  • date-fns - Provides formatDistanceToNow function
  • @/components/ui/tooltip - Tooltip components for hover display
  • React hooks: useState, useEffect, useRef

Implementation Details

Performance Optimizations

  • Uses useRef to store initial timestamp, preventing recalculation
  • Intelligent interval timing reduces unnecessary updates
  • Cleanup of intervals on component unmount

Error Handling

  • Try-catch around formatDistanceToNow with fallback to “Unknown time”
  • Graceful handling of invalid timestamps
  • Console error logging for debugging

Accessibility

  • Tooltip provides additional context for screen readers
  • Semantic time display with proper ARIA attributes
  • Respects user’s locale settings for timestamp formatting

Browser Compatibility

  • toLocaleString(): All modern browsers
  • date-fns: No specific browser requirements
  • Tooltip functionality: All modern browsers
  • Message display components that show timestamps
  • Chat interfaces requiring relative time display
  • Activity feeds and notification systems

Best Practices

  1. Use the Date API for new implementations when possible
  2. Provide fallback text for missing timestamps
  3. Consider disabling tooltips in space-constrained layouts
  4. Use appropriate CSS classes for consistent styling across the app