New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

react-timedown-ui

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-timedown-ui

A headless, flexible timedown timer hook and component for React applications

latest
Source
npmnpm
Version
1.1.0
Version published
Maintainers
1
Created
Source

⏰ React Timedown

A flexible, headless countdown timer hook and component for React applications. Built with TypeScript and designed for maximum flexibility.

npm version npm downloads CI codecov license

📚 Documentation

Features

  • 🎯 Headless Design - Complete control over your UI
  • Flexible Input - Accepts seconds, minutes, hours, days, or Date objects
  • 🎨 Custom Formatting - Multiple built-in formats or create your own
  • 🔄 Full Control - Start, pause, resume, and reset functionality
  • 📦 TypeScript Ready - Written in TypeScript with full type definitions
  • 🪶 Lightweight - Zero dependencies (except React)
  • Well Tested - Comprehensive test coverage

Installation

npm install react-timedown-ui

or

yarn add react-timedown-ui

Quick Start

Using the Hook

import { useTimedown } from 'react-timedown-ui';

function MyTimedown() {
  const { time, start, pause, reset, isRunning } = useTimedown({
    seconds: 60, // 60 seconds - CLEAR AND EXPLICIT!
  });

  return (
    <div>
      <div>{time.formatted}</div>
      <button onClick={start}>Start</button>
      <button onClick={pause}>Pause</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

Using the Component (Render Props)

import { Timedown } from 'react-timedown-ui';

function MyTimedown() {
  return (
    <Timedown seconds={60}>
      {({ time, start, pause, reset, isRunning }) => (
        <div>
          <div>{time.formatted}</div>
          <button onClick={start}>Start</button>
          <button onClick={pause}>Pause</button>
          <button onClick={reset}>Reset</button>
        </div>
      )}
    </Timedown>
  );
}

Usage Examples

Hook Examples

Simple Usage - Seconds

// Most straightforward - just pass seconds
const { time, start } = useTimedown({
  seconds: 60, // Clear: 60 seconds
  autoStart: false,
});

Simple Usage - Minutes

// Or use minutes prop
const { time, pause } = useTimedown({
  minutes: 5, // Clear: 5 minutes
  autoStart: true,
});

Simple Usage - Hours

// Or hours
const { time } = useTimedown({
  hours: 2, // Clear: 2 hours
  autoStart: true,
});

Combined Time Units

// Combine multiple units - they add up!
const { time } = useTimedown({
  hours: 1,
  minutes: 30,
  seconds: 45,
  autoStart: true,
});
// Total: 5445 seconds

Using Duration Object

// For complex durations, use the duration prop
const { time } = useTimedown({
  duration: {
    days: 2,
    hours: 5,
    minutes: 30,
    seconds: 15,
  },
  autoStart: true,
});

Countdown Until a Specific Date

const newYear = new Date('2026-01-01T00:00:00');

const { time } = useTimedown({
  until: newYear, // Countdown until New Year
  autoStart: true,
});

With Callbacks

const { time } = useTimedown({
  seconds: 60,
  onComplete: () => {
    console.log('Timedown completed!');
    // Show notification, play sound, etc.
  },
  onTick: (time) => {
    console.log('Current time:', time);
    // Update document title, etc.
  },
});

Custom Format

const { time } = useTimedown({
  seconds: 3665, // 1 hour, 1 minute, 5 seconds
  format: 'custom',
  customFormat: (time) => {
    return `${time.hours}h ${time.minutes}m ${time.seconds}s`;
  },
});

Different Built-in Formats

// Format: HH:MM:SS (default)
const timedown1 = useTimedown({ seconds: 3665 });
// Result: 01:01:05

// Format: MM:SS
const timedown2 = useTimedown({ 
  seconds: 3665,
  format: 'MM:SS' 
});
// Result: 61:05

// Format: DD:HH:MM:SS
const timedown3 = useTimedown({ 
  duration: { days: 2, hours: 5, minutes: 30 },
  format: 'DD:HH:MM:SS' 
});
// Result: 02:05:30:00

// Format: HH:MM:SS:MS
const timedown4 = useTimedown({ 
  seconds: 60,
  format: 'HH:MM:SS:MS' 
});
// Result: 00:01:00:000

Custom End Time

const { time } = useTimedown({
  seconds: 60,
  endTime: 10, // Stop at 10 seconds instead of 0
  onComplete: () => {
    console.log('Reached 10 seconds!');
  },
});

Full Control Example

function AdvancedTimedown() {
  const { 
    time, 
    start, 
    pause, 
    resume, 
    reset,
    isRunning,
    isPaused,
    isCompleted
  } = useTimedown({
    minutes: 5,
  });

  return (
    <div>
      <h1>{time.formatted}</h1>
      
      <div>
        <p>Days: {time.days}</p>
        <p>Hours: {time.hours}</p>
        <p>Minutes: {time.minutes}</p>
        <p>Seconds: {time.seconds}</p>
        <p>Total Seconds: {time.totalSeconds}</p>
      </div>

      <div>
        {!isRunning && !isCompleted && (
          <button onClick={start}>Start</button>
        )}
        {isRunning && (
          <button onClick={pause}>Pause</button>
        )}
        {isPaused && (
          <button onClick={resume}>Resume</button>
        )}
        <button onClick={() => reset()}>Reset</button>
        <button onClick={() => reset(600)}>Reset to 10 minutes</button>
      </div>

      <div>
        <p>Status:</p>
        <p>Running: {isRunning ? 'Yes' : 'No'}</p>
        <p>Paused: {isPaused ? 'Yes' : 'No'}</p>
        <p>Completed: {isCompleted ? 'Yes' : 'No'}</p>
      </div>
    </div>
  );
}

Component Examples (Render Props Pattern)

Basic Component Usage

<Timedown seconds={60}>
  {({ time, start, pause, isRunning }) => (
    <div>
      <h1>{time.formatted}</h1>
      <button onClick={isRunning ? pause : start}>
        {isRunning ? 'Pause' : 'Start'}
      </button>
    </div>
  )}
</Timedown>

Custom Styled Component

<Timedown minutes={5} autoStart={false}>
  {({ time, start, pause, isRunning }) => (
    <div className="custom-timedown">
      <div className="timer-display">
        {time.minutes}:{time.seconds.toString().padStart(2, '0')}
      </div>
      <button onClick={isRunning ? pause : start}>
        {isRunning ? '⏸ Pause' : '▶ Start'}
      </button>
    </div>
  )}
</Timedown>

With Progress Bar

<Timedown seconds={60}>
  {({ time, start, pause, reset, isRunning }) => {
    const progress = (time.totalSeconds / 60) * 100;
    
    return (
      <div>
        <div className="progress-bar">
          <div 
            className="progress-fill" 
            style={{ width: `${progress}%` }} 
          />
        </div>
        <div className="time">{time.formatted}</div>
        <div className="controls">
          <button onClick={isRunning ? pause : start}>
            {isRunning ? 'Pause' : 'Start'}
          </button>
          <button onClick={() => reset()}>Reset</button>
        </div>
      </div>
    );
  }}
</Timedown>

Circular Progress Indicator

<Timedown seconds={60}>
  {({ time, start, isRunning }) => {
    const progress = (time.totalSeconds / 60) * 100;
    const circumference = 2 * Math.PI * 45;
    const offset = circumference - (progress / 100) * circumference;
    
    return (
      <div style={{ 
        position: 'relative', 
        width: '160px', 
        height: '200px',
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        gap: '16px'
      }}>
        <svg width="160" height="160">
          <circle
            cx="80"
            cy="80"
            r="70"
            stroke="#e5e7eb"
            strokeWidth="10"
            fill="none"
          />
          <circle
            cx="80"
            cy="80"
            r="70"
            stroke="url(#gradient)"
            strokeWidth="10"
            fill="none"
            strokeDasharray={circumference}
            strokeDashoffset={offset}
            strokeLinecap="round"
            transform="rotate(-90 80 80)"
          />
          <defs>
            <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
              <stop offset="0%" style={{ stopColor: '#6366f1', stopOpacity: 1 }} />
              <stop offset="100%" style={{ stopColor: '#8b5cf6', stopOpacity: 1 }} />
            </linearGradient>
          </defs>
        </svg>
        <div style={{ 
          position: 'absolute', 
          top: '65px',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          gap: '4px'
        }}>
          <strong style={{ fontSize: '36px', fontWeight: 'bold', color: '#1f2937' }}>
            {time.seconds}
          </strong>
          <span style={{ fontSize: '12px', color: '#6b7280', textTransform: 'uppercase' }}>
            seconds
          </span>
        </div>
        <button 
          onClick={start}
          style={{
            padding: '8px 24px',
            borderRadius: '8px',
            border: 'none',
            background: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
            color: 'white',
            fontWeight: '600',
            cursor: 'pointer',
            transition: 'transform 0.2s',
          }}
          onMouseEnter={(e) => e.currentTarget.style.transform = 'scale(1.05)'}
          onMouseLeave={(e) => e.currentTarget.style.transform = 'scale(1)'}
        >
          {isRunning ? 'Running...' : 'Start'}
        </button>
      </div>
    );
  }}
</Timedown>

API Reference

useTimedown(props) Hook

Props

Time Input (choose ONE approach):

PropTypeDescription
secondsnumberSimple: countdown from X seconds
minutesnumberSimple: countdown from X minutes
hoursnumberSimple: countdown from X hours
daysnumberSimple: countdown from X days
durationDurationComplex: combined time units
untilDateCountdown until a specific date/time

Note: You can combine seconds, minutes, hours, and days - they will add up!

Options:

PropTypeDefaultDescription
autoStartbooleanfalseWhether to start countdown automatically
formatTimeFormat'HH:MM:SS'Time format (see formats below)
customFormat(time: FormattedTime) => stringundefinedCustom format function
intervalnumber1000Update interval in milliseconds
endTimenumber0End countdown at specific second
onComplete() => voidundefinedCallback when countdown completes
onTick(time: FormattedTime) => voidundefinedCallback on each tick

Return Value

{
  time: FormattedTime;      // Current time object
  start: () => void;         // Start the countdown
  pause: () => void;         // Pause the countdown
  resume: () => void;        // Resume the countdown
  reset: (newTime?: ResetTimeInput) => void; // Reset countdown
  isRunning: boolean;        // Whether countdown is running
  isPaused: boolean;         // Whether countdown is paused
  isCompleted: boolean;      // Whether countdown is completed
}

<Timedown> Component

The Timedown component uses the render props pattern, providing complete UI control while handling all countdown logic internally.

Props

Same as useTimedown props plus:

PropTypeDescription
children(timedown: UseTimedownReturn) => ReactNodeRequired - Render function that receives countdown state and methods

Example

<Timedown seconds={60} autoStart>
  {({ time, start, pause, reset, isRunning, isPaused, isCompleted }) => (
    // Your custom UI here
  )}
</Timedown>

Types

Duration

interface Duration {
  seconds?: number;
  minutes?: number;
  hours?: number;
  days?: number;
}

ResetTimeInput

type ResetTimeInput = Duration | Date;

TimeFormat

type TimeFormat = 
  | 'HH:MM:SS'      // 01:30:45
  | 'MM:SS'         // 90:45
  | 'HH:MM:SS:MS'   // 01:30:45:123
  | 'DD:HH:MM:SS'   // 02:01:30:45
  | 'custom';       // Use customFormat function

FormattedTime

interface FormattedTime {
  days: number;
  hours: number;
  minutes: number;
  seconds: number;
  milliseconds: number;
  totalSeconds: number;
  formatted: string;
}

Utility Functions

You can also import utility functions for time conversion and formatting:

import { convertToSeconds, convertSecondsToUnits, formatTime } from 'react-timedown-ui';

// Convert various inputs to seconds
const seconds1 = convertToSeconds(60); // 60
const seconds2 = convertToSeconds({ minutes: 2, seconds: 30 }); // 150
const seconds3 = convertToSeconds(new Date('2025-12-31')); // seconds until date

// Convert seconds to time units
const units = convertSecondsToUnits(3665);
// { days: 0, hours: 1, minutes: 1, seconds: 5, milliseconds: 0, totalSeconds: 3665 }

// Format time
const formatted = formatTime(units, 'HH:MM:SS');
// "01:01:05"

Examples

Check out the Storybook examples for interactive demos and live code examples.

Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct, development process, and how to submit pull requests.

License

MIT © React Timedown Contributors

Support

Made with ❤️ for the React community

Keywords

react

FAQs

Package last updated on 15 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts