Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelogApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip
ARC UIARC Radiant Components
v4.9DocsComponentsTokensSynthesizer
Getting StartedFrameworksServer RenderingDesign TokensThemingTheme SynthesizerTypographyUtilitiesAll ComponentsAccessibilityBrowser SupportChangelogContributingStatsApp ShellAspect GridAuth ShellCenterContainerDashboard GridFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbarAnchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkStepper NavTabsTop BarTree ViewAccordionAspect RatioAvatarAvatar GroupCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSkeletonSpinnerStackVideoVirtual ListActivity HeatmapAnimated NumberBadgeBar ListChartClockComparisonCountdown TimerData GridDescription ListDiffGaugeJSON TreeKanbanLevel MeterListMeterSparklineStatStepperTagTimelineUptimeValue CardWaveformBlockquoteCode BlockCode GroupGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriterButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerField ListFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree SelectAlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuHover CardLoading OverlayNotification PanelPopoverProgressSheetToastTooltip

Date Range Picker

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

ComponentsDate Range Picker
inputinteractivebeta
<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>

API

autoValidatesbooleanfalse
Runs its own constraint logic and owns the whole validity flag set.
valuestring
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.
localestring''
BCP 47 tag used for month and weekday names. Defaults to the document's lang, then the browser's language.
first-day-of-weeknumber0
Which day the week starts on, 1 = Monday … 7 = Sunday. Defaults to the locale's own convention.
startstring''
Range start date as an ISO string (YYYY-MM-DD). Empty when unset. Set both start and end to pre-select a range.
endstring''
Range end date as an ISO string (YYYY-MM-DD). Empty when unset or while an end date is pending.
namestring''
Form field name used when the interval value is submitted with a form.
minstring''
Minimum selectable date as an ISO string. Earlier days are dimmed and non-interactive.
maxstring''
Maximum selectable date as an ISO string. Later days are dimmed and non-interactive.
placeholderstring'Select date range'
Placeholder text shown in the input when no range is selected.
disabledbooleanfalse
Disables the picker, reducing opacity and preventing the popup from opening.
labelstring''
Label text rendered above the input in uppercase accent font styling.
monthsnumber2
Number of month panels shown in the popup. Panels sit side by side and stack vertically when the popup is too narrow.
presetsArray<{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.
requiredbooleanfalse
Marks the control invalid (valueMissing) until a complete range is selected.
openbooleanfalse
Whether the calendar dropdown is visible. Reflected so it can be opened programmatically or styled from CSS. Held at false while disabled.
size'sm' | 'md' | 'lg''md'
Control size. md is the default; sm and lg scale the field padding.
formAssociatedbooleantrue
propertiesobject{ // flag(), unlike `disabled`. The exclusion in props.js is specifically // about form-associated *platform* semantics: a `disabled` content // attribute that is merely present makes the element actually disabled // per the HTML spec, and formDisabledCallback assigns the property back, // so no converter can win. Neither of these is platform-mapped: // `required` is enforced by _computeValidity() below and `readonly` by // each component's own interaction handlers, so the stock converter buys // nothing here and costs the usual bug: `required="false"` read as true, // blocking submission of a form the author meant to leave optional. // Finding #48's shape, across all 26 form controls at once. required: flag(false), readonly: flag(false), }
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
readonlybooleanfalse

Methods

checkValidity()boolean
Whether the control currently satisfies its constraints, per the native constraint-validation API. Fires invalid on the element when it does not, and reports nothing to the user.
reportValidity()boolean
As checkValidity(), but also shows the browser's validation message against the control when it fails.

Events

arc-changedetail:{ value: string, start: string, end: string }
Fired when a complete range is committed (second day clicked or preset applied). detail.value is the ISO 8601 interval string, the same shape as the value property; start and end carry the two ends separately.

See Also