Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Date Range Picker

Dual-calendar picker for selecting a start/end date range with presets and full keyboard navigation.

Components Date Range Picker
input interactive beta
<arc-date-range-picker>

Overview

DateRangePicker extends the single DatePicker model to a start/end range. The read-only input displays the committed range in a compact human-readable form (e.g. "Jan 5 – Feb 2, 2026") while the `start` and `end` properties hold ISO strings (YYYY-MM-DD). The derived `value` getter returns the two dates joined as an ISO 8601 interval ("2026-01-05/2026-02-02") — the same string is submitted with the parent form via ElementInternals, and `form.reset()` restores the initial range. Selection follows the familiar two-click model: the first click (or Enter on a focused day) sets the start date, and while the end is pending, hovering or keyboard-focusing another day previews the resulting range with a soft highlight. The second click commits the range (automatically swapping if the second date is earlier), fires `arc-change` with `{ start, end }`, and closes the popup. A third click begins a new range. The popup shows a configurable number of month panels (two by default) that sit side by side and wrap into a vertical stack when horizontal space runs out, with shared previous/next month navigation. An optional `presets` array renders a left rail of one-click quick ranges such as "Last 7 days" — each entry is `{ label, days }` and resolves to a range ending today. The day grids use a roving tabindex with Arrow/Home/End/PageUp/PageDown navigation that pages months automatically at the edges, endpoint days carry ", range start"/", range end" label suffixes, and a polite live region announces selection progress ("Start date set. Choose end date.") for screen reader users. Escape closes the popup and restores focus to the input.

Guidelines

When to use

  • Provide presets for the ranges users pick most often (7/30/90 days) to reduce interaction cost
  • Use the start and end ISO strings (or the interval value) for APIs — never parse the display text
  • Set min and max when only a bounded window is meaningful (e.g. report data availability)
  • Listen to arc-change to react to committed ranges; it fires only when both dates are set
  • Set months={1} in narrow layouts like popover filters where two panels would overflow

When not to use

  • Do not use it for a single date — use DatePicker instead
  • Do not treat the first click as a committed value; arc-change fires only after the end date is chosen
  • Do not hand-build preset buttons outside the component when the presets prop covers the need
  • Do not place it inside an overflow: hidden container, as the popup will be clipped
  • Do not set min greater than max, which disables every day in the calendar

Features

  • Two-click range selection with automatic start/end swap when picked out of order
  • Live range preview highlight while hovering or keyboard-focusing the end date
  • ISO 8601 interval value ("start/end") submitted through native form association
  • Configurable number of side-by-side month panels (default 2) that stack when space is tight
  • Optional preset rail for one-click quick ranges like "Last 7 days"
  • Min/max bounds that disable out-of-range days
  • Roving-tabindex day grid with Arrow, Home/End, and PageUp/PageDown month paging
  • Polite live-region announcements of selection progress for assistive technology
  • Escape and outside-click dismissal with focus restoration to the input

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-date-range-picker
  label="Reporting Period"
  presets='[{"label":"Last 7 days","days":7},{"label":"Last 30 days","days":30}]'
></arc-date-range-picker>
import { DateRangePicker } from '@arclux/arc-ui-react';

export default function Example() {
  return (
    <DateRangePicker
      label="Reporting Period"
      presets={[{ label: 'Last 7 days', days: 7 }, { label: 'Last 30 days', days: 30 }]}
      onArcChange={(e) => console.log(e.detail.start, e.detail.end)}
    ></DateRangePicker>
  );
}
<script setup>
import { DateRangePicker } from '@arclux/arc-ui-vue';

const presets = [{ label: 'Last 7 days', days: 7 }, { label: 'Last 30 days', days: 30 }];
</script>

<template>
  <DateRangePicker label="Reporting Period" :presets="presets" />
</template>
<script>
  import { DateRangePicker } from '@arclux/arc-ui-svelte';

  const presets = [{ label: 'Last 7 days', days: 7 }, { label: 'Last 30 days', days: 30 }];
</script>

<DateRangePicker label="Reporting Period" presets={presets} />
import { Component } from '@angular/core';
import { DateRangePicker } from '@arclux/arc-ui-angular';

@Component({
  imports: [DateRangePicker],
  template: `
    <arc-date-range-picker label="Reporting Period" [presets]="presets"></arc-date-range-picker>
  `,
})
export class MyComponent {
  presets = [{ label: 'Last 7 days', days: 7 }, { label: 'Last 30 days', days: 30 }];
}
import { DateRangePicker } from '@arclux/arc-ui-solid';

export default function Example() {
  return (
    <DateRangePicker
      label="Reporting Period"
      presets={[{ label: 'Last 7 days', days: 7 }]} />
  );
}
import { DateRangePicker } from '@arclux/arc-ui-preact';

export default function Example() {
  return (
    <DateRangePicker
      label="Reporting Period"
      presets={[{ label: 'Last 7 days', days: 7 }]} />
  );
}

API

autoValidates boolean false
Runs its own constraint logic — owns the whole validity flag set.
value string
Read-derived ISO 8601 interval ("start/end") when both dates are set, otherwise an empty string. This is the value submitted with forms. Assigning "start/end" sets both dates.
size 'sm' | 'md' | 'lg' 'md'
Control size. `md` is the default; `sm` and `lg` scale the field padding.
locale string ''
BCP 47 tag used for month and weekday names. Defaults to the document's `lang`, then the browser's language.
first-day-of-week number 0
Which day the week starts on, 1 = Monday … 7 = Sunday. Defaults to the locale's own convention.
start string ''
Range start date as an ISO string (YYYY-MM-DD). Empty when unset. Set both start and end to pre-select a range.
end string ''
Range end date as an ISO string (YYYY-MM-DD). Empty when unset or while an end date is pending.
name string ''
Form field name used when the interval value is submitted with a form.
min string ''
Minimum selectable date as an ISO string. Earlier days are dimmed and non-interactive.
max string ''
Maximum selectable date as an ISO string. Later days are dimmed and non-interactive.
months number 2
Number of month panels shown in the popup. Panels sit side by side and stack vertically when the popup is too narrow.
presets Array<{label:string,days:number}> []
Quick ranges rendered as a left rail. Each preset selects the last N days ending today and closes the popup. Hidden when empty.
placeholder string 'Select date range'
Placeholder text shown in the input when no range is selected.
disabled boolean false
Disables the picker, reducing opacity and preventing the popup from opening.
required boolean false
Marks the control invalid (valueMissing) until a complete range is selected.
label string ''
Label text rendered above the input in uppercase accent font styling.
open boolean false
Whether the calendar dropdown is visible. Reflected so it can be opened programmatically or styled from CSS.
formAssociated boolean true
properties object { required: { type: Boolean, reflect: true }, readonly: { type: Boolean, reflect: true }, }
Lit merges static properties up the prototype chain, so every consumer gets these without declaring them. `required` participates in constraint validation below; `readonly` reflects for styling and is enforced by each component's interaction handlers (the mixin can't know which gestures mutate state).
form
validity
validationMessage
readonly boolean false

Events

arc-change detail: { start: string, end: string }
Fired when a complete range is committed (second day clicked or preset applied). detail: { start, end }

See Also