Skip to content
oks-ui
Tutorial

React Date Range Picker with Presets

· 2 min read · oks-ui team

A month calendar with a date range selected across six days, and a preset chip beside it.
ShareXLinkedIn
On this page
  1. 1. A single date first
  2. 2. Turn it into a range
  3. 3. Add presets
  4. 4. Limit what can be picked
  5. 5. One trigger or two
  6. 6. Adding a time
  7. Useful extras
  8. Filtering data by the range

Reports, bookings and analytics all need the same control: pick a start date and an end date. Most users don't want to click through a calendar for "last month", so a good range picker also offers presets. This tutorial builds one with oks-ui's FormFieldSet of type datepicker.

import { FormFieldSet } from "oks-ui/form-field-set";
import "oks-ui/form-field-set.css";

1. A single date first

With type="datepicker", the value is a string in YYYY-MM-DD format:

const [date, setDate] = useState("");

<FormFieldSet
  type="datepicker"
  name="dueDate"
  label="Due date"
  value={date}
  onChange={(v) => setDate(String(v ?? ""))}
/>

2. Turn it into a range

Add range and the value becomes an object with a start and an end:

type Range = { start: string; end: string };
const [period, setPeriod] = useState<Range>({ start: "", end: "" });

<FormFieldSet
  type="datepicker"
  name="period"
  label="Report period"
  range
  monthsToShow={2}
  value={period}
  onChange={(v) => setPeriod(v as Range)}
/>

monthsToShow={2} puts two months side by side, which makes ranges across a month boundary much easier to pick.

Advertisement

3. Add presets

showPresets adds a list of common ranges next to the calendar. Choose which ones with presets:

<FormFieldSet
  type="datepicker"
  name="period"
  label="Report period"
  range
  showPresets
  presets={["today", "thisWeek", "lastWeek", "thisMonth", "lastMonth", "last3Months", "custom"]}
  value={period}
  onChange={(v) => setPeriod(v as Range)}
/>

The available presets are today, yesterday, thisWeek, lastWeek, fortnight, thisMonth, lastMonth, last3Months, thisYear, lastYear and custom. custom switches to the calendar for a free choice. Presets are for ranges only; a single-date picker ignores them.

4. Limit what can be picked

Three props keep users away from impossible dates:

  • minDate / maxDate — nothing before or after. A report can't cover the future; a booking can't start in the past.
  • blockedDates — individual dates that can't be chosen, such as public holidays.
const today = new Date();

<FormFieldSet
  type="datepicker"
  name="period"
  label="Report period"
  range
  showPresets
  maxDate={today}
  blockedDates={["2026-12-25", "2027-01-01"]}
  value={period}
  onChange={(v) => setPeriod(v as Range)}
/>

Dates accept either a Date object or a YYYY-MM-DD string.

5. One trigger or two

By default a range opens from a single field showing both dates. For forms where start and end are separate questions — "check-in" and "check-out" — use two triggers:

<FormFieldSet type="datepicker" name="stay" label="Your stay" range rangeTrigger="dual" />

6. Adding a time

For schedules, add withTime. The value then includes the time as YYYY-MM-DDTHH:mm:

<FormFieldSet type="datepicker" name="publishAt" label="Publish at" withTime />

Useful extras

  • clearable adds a clear button, with onClear if you need to react to it.
  • displayFormat="iso" shows dates as 2026-09-29 instead of the default readable format.
  • Inside an oks-ui Form, drop value and onChange — the form collects the value under the field's name, and validation={{ rules: { required: true } }} makes sure both dates are filled in.

Filtering data by the range

Because the value is plain strings in YYYY-MM-DD form, comparing dates is simple string comparison:

const inRange = orders.filter(
  (o) => (!period.start || o.date >= period.start) && (!period.end || o.date <= period.end),
);

See the date picker component page for every option.

Advertisement

Was this post helpful?

ShareXLinkedIn