Date Range Filter

A controlled date-range picker with responsive calendars, quick presets, and explicit clear and apply actions.

Calendar and preset selections stay in a draft until Apply is pressed, preventing partial ranges from repeatedly filtering a table.

Choose a preset or a custom range.

Applied filter

Saturday, August 1, 2026 through Friday, August 7, 2026

If selected dates lose contrast on hover, update both endpoint classes:

range-calendar-day.svelte
hover:text-foreground hover:text-primary-foreground

Installation

pnpm dlx shadcn-svelte@latest add http://sveltekit-prerender/r/date-range-filter.json

Step-by-step guide

The component is controlled and table-agnostic. Start with local state, then connect that state to a table column only when needed.

Create the range state

Import the component value type and initialize an optional range.

filters.svelte

Render the controlled filter

Bind the value for the shortest setup. It changes only after Apply or Clear.

filters.svelte

Register TanStack's date filter

For a table column, enable filtering and register filterFn_inDateRange. Both endpoints are inclusive.

table.svelte.ts

Send the applied range to the column

Translate the component's named range into the [start, end] tuple expected by the table filter.

filters.svelte

Custom presets

Replace the built-in choices with domain-specific ranges. Each preset receives the current local date when selected, so relative ranges do not become stale.

Choose a custom preset

Calendar only and date limits

Pass presets={false} for a focused calendar. This example also limits the selectable dates, starts weeks on Monday, and uses British English date formatting.

Calendar only · 2026 dates · weeks start on Monday

Behavior

The default presets are Today, Last 7 days, Last 30 days, and This month. An applied range can be removed directly from the clear button beside the trigger. Dates are returned at local midnight. Two months appear on desktop and the component switches to one month below the mobile breakpoint. min and max constrain the calendar and disable presets outside those boundaries.

Accessibility

The trigger announces the applied range and the adjacent clear control has a filter-specific accessible label. The popover restores focus on close, while the range calendar provides keyboard day navigation, month controls, selected-range semantics, and localized labels.

Props

Date range filter props

NameTypeDefaultDescription
valueDateRangeFilterValue | undefinedundefinedBindable applied range. Draft calendar changes do not update it until Apply.
onValueChange(value) => voidundefinedCalled when a range is applied or cleared.
titlestring"Date"Filter name displayed in the trigger.
placeholderstring"Select date range"Trigger text shown before a range is applied.
presetsDateRangeFilterPreset[] | falsedefault presetsPreset choices, or false to render the calendar without presets.
minDateundefinedEarliest selectable date.
maxDateundefinedLatest selectable date.
numberOfMonthsnumber2Months displayed on desktop. Mobile always displays one.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 60First day of the calendar week.
localestring"en-US"Locale for calendar labels and date formatting.
clearTextstring"Clear"Clear action label.
applyTextstring"Apply"Apply action label.
disabledbooleanfalseDisables the filter trigger.
openbooleanfalseBindable popover open state.
classstringundefinedClasses applied to the trigger button.
contentClassstringundefinedClasses applied to the popover content.

DateRangeFilterValue

NameTypeDefaultDescription
startDate | undefinedrequiredInclusive start date at local midnight.
endDate | undefinedrequiredInclusive end date at local midnight.

DateRangeFilterPreset

NameTypeDefaultDescription
labelstringrequiredPreset button label.
getValue(referenceDate: Date) => DateRangeFilterValuerequiredBuilds the preset range from the current local date.