Skip to content

Date Range Picker

A click-twice range calendar with a live hover preview and quick presets.

Prominimaleditorial
Category
Components
Added
2026-09-01
Deps
1
Updated
2026-09-01

This is a viberdy Pro component

The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.

Preview

September 2026

SMTWTFS
Start → End

Props

Show presets
Requires lucide-react
"use client";

import { useMemo, useState } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";

const DAY_MS = 86400000;
const WEEKDAYS = ["S", "M", "T", "W", "T", "F", "S"];

function startOfDay(d: Date) {
  return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}
function fmt(d: Date) {
  return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
}
function sameDay(a: Date | null, b: Date | null) {
  return !!a && !!b && a.getTime() === b.getTime();
}
function buildMonth(monthStart: Date) {

  // ---------------------------------------------------------------
  // Full source available with a viberdy Pro subscription.
  // https://viberdy.dev/pricing
  // ---------------------------------------------------------------
}
Notes

About this component

A single <input type="date"> can't express a range, and reaching for a full calendar library for one picker is heavy. The real complexity here isn't drawing a grid of days — it's the selection state machine: start and end are independently nullable, so there are three distinct phases (nothing picked, start picked, full range picked) and each click means something different depending on the phase, including the case where a third click should discard the old range rather than extend it. The non-obvious detail is the hover preview: the visual range while the user is still choosing an end date is computed from start plus a separate hover-position state, never written into the committed range state, so moving the mouse away cleanly reverts to just the start highlight instead of leaving stray selection artifacts. Caveat: month math here is hand-rolled with native Date rather than a date library, which is fine for a single-month view but gets error-prone fast if you extend this to multi-month or timezone-sensitive bookings — reach for date-fns or Temporal at that point.

Curator’s note

The three-phase click state (none, start-only, complete) is what makes this feel like a real range picker instead of two independent date inputs bolted together.

Related

Pairs well with

Matched on shared tags and category — the entries most likely to be used alongside this one.

A text input whose label floats from placeholder position into a caption on focus.

inputformlabel

A real drag-and-drop file zone with a live dragover state and file chips.

uploaddropzonedrag-drop
Pro

A chip-and-search combobox with full keyboard control and a selection cap.

comboboxmulti-selectdropdown