Skip to content

Date Range Picker

Bozhidara Pachilova edited this page Jun 5, 2025 · 17 revisions

Date Range Picker Specification

Contents

  1. Overview
  2. User Stories
  3. Functionality
  4. Test Scenarios
  5. Accessibility
  6. Assumptions and Limitations
  7. References

Owned by

Astrea + Design and Web Development

Developer Name Bozhidara Pachilova, Ivan Kitanov

Designer Name Yordanka Petkova-Radoeva, Silvia Ivanova

Signed off by

  • Radoslav Mirchev | Date: 2025-04-16
  • Radoslav Karaivanov | Date:
  • Svilen Dimchevski | Date:

Revision History

Version Users Date Notes
1 Bozhidara Pachilova 2025-03-10 Initial draft
2 Bozhidara Pachilova 2025-04-14 Spec ready for review
3 Ivan Kitanov 2025-04-14 Minor updates to customRanges property
4 Svilen Dimchevski 2025-04-15 Design Handoff in Figma added

The igc-date-range-picker lets users select start and end dates by either by selecting a date range through a dropdown/dialog popup calendar view or by typing in its input fields - one for start and one for end. It can be customized to match app requirements with features like range restrictions, formats, data range selection, grouping the start and end values together and many more.

The picker has two modes for displaying the date values - single and with two inputs. In single, the input is non-editable and the date range cannot be edited by typing. The two inputs mode, on the other hand, allows typing to edit the start and end dates in separate igc-date-time-inputs. (Note: typing in single input mode might be implemented in the future after adding the ability to edit a date range for the igc-date-time-input.

Objectives

Provide a web component that uses the igc-calendar to select a range value. The igc-calendar is opened either in an igc-popover for dropdown mode, or in an igc-dialog for dialog mode. The date values are editable by typing when the component uses two inputs as editors. In the single input mode, the values can only be updated through calendar selection. The value of the igc-date-range-picker is of type DateRangeValue - { start: Date | null, end: Date | null}.

Reference specifications: Calendar, Date Time Input, Dialog

End-to-end user experience prototype

Acceptance criteria

The igc-date-range-picker must:

  • let users specify a date range by either typing it in two inputs - for start and end value or picking a date range through its calendar component
  • display the date-range picker as a single input field, which displays both start and end dates and is readonly
  • have dropdown and dialog modes for opening the calendar
  • open the calendar by clicking on a toggle icon in dropdown mode
  • open the calendar by clicking on a toggle icon or on the input in dialog mode
  • be form associated and when configured as part of a form, participate in form submission and validation
  • expose CSS parts for styling as well as slots for projecting relevant elements such as prefix, suffix, helper text, separator etc.
  • provide UI with buttons allowing to quickly select among a predefined set of ranges - last week, last month, etc.
  • expose slots for defining additional custom actions
  • expose configuration properties for modifying/localizing the inputs and display format of the date values in the inputs
  • expose configuration properties for modifying/localizing the relevant parts of its calendar component
  • have adequate keyboard support for navigation and selection
  • support the themes available in the library
  • be WAI-ARIA compliant.

Developer stories: As a developer I expect to be able to:

  • set an initial value for the component and/or change the value of the component programmatically if need be
  • set the interaction state of the component - make it disabled, readonly or nonEditable
  • set additional properties such as label, placeholder and/or validators in order to enrich and guide the end user experience
  • use the component in a standard form and have the component participate in form submission and validation
  • choose whether the calendar picker would be a dropdown like experience or a dialog like experience
  • control how the date value would be formatted in the inputs both during editing and display, by specifying a custom pattern/mask
  • choose the component to render either single input displaying the date range values separated by a symbol ("-") or two inputs for start and end date
  • define custom content for the separator between the two inputs
  • hide/show days outside of the current month in the calendar picker
  • set the day that weeks would start in the calendar picker
  • set whether to show/hide week numbers in the calendar picker
  • set special/disabled dates in the calendar picker
  • show a single or two months in the calendar picker
  • set the formatting and localization of dates and elements in the calendar picker
  • listen and react to user interactions through events on the component
  • opt in to show chips allowing to choose among a predefined set of ranges, such as last week, last month, etc.
  • define additional custom actions
  • be able to style parts of the component according to my prefereces.

End-user stories:

As an end-user I expect to be able to:

  • type in and edit a date value inside the start and end inputs in dropdown mode
  • select a date range from the calendar picker of the component and have it automatically filled in the input(s)
  • identify and distinguish the current date, selected date range, special and disabled dates
  • navigate and make edits in the input parts of the component using a keyboard
  • navigate and make selection in the calendar picker part of the component using a keyboard
  • navigate in and out of the component using only a keyboard
  • be informed if the dates I've entered are valid and within range (if such is specified)
  • select a range by clicking a button among a set of predefined date ranges.

3.1. End-User Experience

Design Handoff

3.2. Developer Experience

Value type

interface DateRangeValue {
  start: Date | null;
  end: Date | null;
}

Custom (predefined) date range type

interface CustomDateRange {
  label: string;
  dateRange: DateRangeValue;
}

The predefined ranges chips are ported in a separate internal component named IgcPredefinedRangesAreaComponent.

Default initialization

<igc-date-range-picker label-start="Start label" label-end="End label"></igc-date-range-picker>

With initial value through attribute

<igc-date-range-picker value="{"start":"2025-04-13T21:00:00.000Z","end":"2025-04-14T21:00:00.000Z"}"></igc-date-range-picker>

Display and input formats

<igc-date-range-picker display-format="yyyy-dd-mm" input-format="yyyy-dd-mm"></igc-date-range-picker>

Display and input format should be applied for both inputs.

For reference of the supported formats - the Date Time Input spec.

Slots

<igc-date-range-picker label="..." mode="dialog" display-format="yyyy/MM/dd">
  <p slot="title">...</p>
  <p slot="invalid">Please, select another range</p>
</igc-date-range-picker>

3.3. Behaviors

1. Clearing the inputs

  • on losing focus, igcChange is emitted; start and end are null (detail is { start: null, end: null }); (for both two and single inputs mode)
  • if the control is readOnly, clicking the clear icon should not clear the value

2. IgcChange event emitting when selecting value from the calendar

  • In dropdown mode:
  • on selecting the first date, igcChange is emitted; start and end are the same date; (detail is { start: startDate, end: startDate});
  • on selecting a second date, igcChange is emitted again; (detail is { start: startDate, end: endDate});
  • In dialog mode:
  • igcChange is emitted on pressing the "Done" button, or when closing the dialog by clicking outside of it. Doing so will confirm the selected dates.

3. The inputs value updating while selecting from the calendar:

  • In dropdown mode, the input(s) start and end value are immediately reflected with selection
  • In dialog mode, the input(s) start and end value are immediately reflected with selection. If the "Cancel" button is pressed, the values are reverted back.

4. Both inputs are initially empty. One of them - the start date, is filled by typing (dropdown mode).

  • igcInput is emitted; the detail is { start: dateValue, end: null });
  • On losing focus of the input igcChange is fired; detail is { start: dateValue, end: null });
  • The typed date should be selected in the calendar.

5. Validation specifics

  • In scenarios when there are two inputs, both of them should reflect the form state, i.e. if the date-range-picker is invalid, both inputs should be in the invalid state.
  • When checking for min/max value validation constraints (rangeUnderflow/rangeOverflow), both the start and end dates are checked to be less/greater than the applied min/max value. The control is invalid if any of the start/end values do not satisfy the condition.

6. Active date

  • The calendar active date is set to activeDate property of the date-range-picker, if set.
  • If the above is not set and there is no value (both start and end are null), the calendar's internal active date is used, which by default is the current date.
  • If a value is assigned to the date-range-picker, the first defined date among the start or end is assigned as active date:
{ start: *start-date*, end: null } -> // active date is *start-date*
{ start: *start-date*, end: *end-date*} -> // active date is *start-date*
{ start: null, end: *end-date*} -> // active date is *end-date*
  • On typing in the inputs, the active date gets assigned to the last modified/typed date.
  • If both values are cleared by typing, the active date remains as the last that was assigned.

7. Custom chips

  • In dropdown mode when selecting a chip value, the dropdown gets closed.
  • In dialog mode when selecting a chip value, the dialog remains opened.

8. Readonly state

  • Keyboard navigation is disabled.
  • Toggling of the calendar picker is disabled.
  • Clearing through the clear icon is disabled.
  • The calendar and clear icons appear visually disabled.

3.3. Globalization/Localization The following strings should be exposed for localization:

  • The "to" separator between two inputs
  • The "Cancel" and "Done" buttons of the calendar dialog.
  • The predefined ranges chips labels
  • The resource strings of the calendar

i.e.

export interface IgcDateRangePickerResourceStrings
  extends IgcCalendarResourceStrings {
  separator: string;
  done: string;
  cancel: string;
  last7Days: string;
  last30Days: string;
  //..
}

3.4. Keyboard Navigation

As long as focus is within parts of the date range picker component:

Key combination Description
Escape If the picker is shown closes the picker and returns focus to the input part. Otherwise it is a no-op

When any of the input parts of the component is focused:

Key combination Description
ArrowLeft / ArrowRight Moves the caret one character in the desired direction
Ctrl + ArrowLeft Moves the caret to the beginning of the current input mask section or to the start of the previous one it is already at the beginning
Ctrl + ArrowRight Moves the caret to the end of the current input mask section or to the end of the next one it is already at the end
ArrowUp Increments by one step the currently "focused" part of the input mask
ArrowDown Decrements by one step the currently "focused" part of the input mask
Home Moves the caret at the beginning of the mask
End Moves the caret at the end of the mask
Ctrl + ; Sets the current date as the value of the component (start input - start value, end input - end value)
Alt + ArrowDown Opens the calendar dropdown
Alt + ArrowUp Closes the calendar dropdown

When focus is within the calendar picker, the keyboard navigation follows the behaviors described in this section of the calendar specification.

3.5. API

Options

Property Attribute Reflected Property Type Default Description
open open Yes boolean false Whether the calendar picker is open
mode mode No 'dropdown' | 'dialog' dropdown Whether to display the calendar picker in a dropdown or a modal dialog
keepOpenOnSelect keep-open-on-select Yes boolean false Whether the calendar picker should be kept open on selection
keepOpenOnOutsideClick keep-open-on-outside-click Yes boolean false Whether the calendar picker should be kept open when clicking outside of it
value value No DateRangeValue { start: null; end: null } The value of the component
min min No Date - The minimum start value required for the component to remain valid
max max No Date - The maximum end value allowed for the component to remain valid
required required Yes boolean false Makes the component required in a form context
disabled disabled Yes boolean false Disables the component
readOnly readonly Yes boolean false Makes the component readonly
nonEditable non-editable Yes boolean false Whether to allow typing in the input(s)
placeholder placeholder No string - The placeholder for the input (single input)
placeholderStart placeholder-start No string - The placeholder for the start input (two inputs)
placeholderEnd placeholder-end No string - The placeholder for the end input (two inputs)
label label No string - The label for the component (single input)
labelStart label-start No string - The label for the start input (two inputs)
labelEnd label-end No string - The label for the end input (two inputs)
outlined outlined Yes boolean false Whether the input part will have outline appearance in the Material theme
locale locale No string en The locale used to display the value and used for formatting the display of the calendar dates
inputFormat input-format No string Default for locale Date mask pattern when editing in the input part of the component Reference
displayFormat display-format No string inputFormat Date pattern to apply to the input value when the input(s) is not focused Reference
prompt prompt No string _ The prompt character used for unfilled parts of the input(s) mask
weekStart week-start No typed string sunday Sets the start day of the week
showWeekNumbers show-week-numbers Yes boolean false Whether to show the number of the week in the calendar days view
hideOutsideDays hide-outside-days Yes boolean false Whether to show dates that do not belong to the current month
hideHeader hide-header Yes boolean false Whether to show the calendar header. Applicable only in dialog mode
headerOrientation header-orientation Yes 'vertical' | 'horizontal' horizontal Whether to align the calendar header vertically or horizontally. Applicable only in dialog mode.
orientation orientation No 'vertical' | 'horizontal' horizontal Whether to align multiple months horizontally or vertically
visibleMonths visible-months No number 1 | 2 The number of months to show in the calendar days view
disabledDates - No DateRangeDescriptor[] - The disabled dates for the calendar picker
specialDates - No DateRangeDescriptor[] - The special dates for the calendar picker
activeDate active-date No Date The current date if not set Sets the date which is shown in view and is highlighted
resourceStrings - No IgcDateRangePickerResourceStrings Resource strings for localization of the date-range picker and the calendar
useTwoInputs use-two-inputs Yes boolean false Indicates whether the picker should use two inputs to display and edit the date range
usePredefinedRanges use-predefined-ranges Yes boolean false Indicates whether an area with chips of predefined date ranges to select from will be rendered
customRanges - No CustomDateRange[] [] Renders chips with custom ranges based on the elements of the array.

Methods

Name Type signature Description
show (): void Shows the component picker
hide (): void Hides the component picker
toggle (): void Toggles between the open state of the picker
clear (): void Clears the input parts of the component of any user input
select (value: DateRangeValue | null): void Selects a date range value in the picker
setCustomValidity (message: string): void Sets a custom validation message. As long as message is not empty, the component is considered invalid

Events

Name Cancellable Description
igcOpening Yes Emitted when the calendar picker is opening
igcOpened No Emitted after the picker is shown
igcClosing Yes Emitted when the calendar picker is closing
igcClosed No Emitted when the calendar picker is closed
igcChange No Emitted when the value of the component is changed
igcInput No Emitted when typing in the input part(s) of the component

Slots

Name Description
separator Renders the separator element between the two inputs
prefix Renders content before the input (single input)
prefix-start Renders content before the start input (two inputs)
prefix-end Renders content before the end input (two inputs)
clear-icon Renders a clear icon template
clear-icon-start Renders a clear icon template for the start input (two inputs)
clear-icon-end Renders a clear icon template for the end input (two inputs)
calendar-icon Renders the icon/content for the calendar picker (applied to both inputs in two inputs mode)
calendar-icon-start Renders the icon/content for the calendar picker for the start input (two inputs)
calendar-icon-end Renders the icon/content for the calendar picker for the end input (two inputs)
calendar-icon-open Renders the icon/content for the picker in open state (applied to both inputs in two inputs mode)
calendar-icon-open-start Renders the icon/content for the picker in open state for the start input (two inputs)
calendar-icon-open-end Renders the icon/content for the picker in open state for the end input (two inputs)
suffix Renders content after the input (single input)
suffix-start Renders content after the start input (two inputs)
suffix-end Renders content after the end input (two inputs)
helper-text Renders content below the input(s)
title Renders content for the calendar title. Applicable only in dialog mode
header-date Renders content instead of the current date/range in the calendar header. Applicable only in dialog mode
actions Renders content in the action part of the picker in open state

CSS Shadow Parts

Part Description
separator The separator element between the two inputs.
ranges The wrapper that renders the custom and predefined ranges.
label The label wrapper that renders content above the target input.
calendar-icon The calendar icon wrapper for closed state. (single input)
calendar-icon-start The calendar icon wrapper for closed state for the start input (two inputs).
calendar-icon-end The calendar icon wrapper for closed state for the end input (two inputs).
calendar-icon-open The calendar icon wrapper for opened state.
calendar-icon-open-start The calendar icon wrapper for opened state for the start input (two inputs).
calendar-icon-open-end The calendar icon wrapper for opened state for the end input (two inputs).
actions The wrapper for the custom actions area.
clear-icon The clear icon wrapper. (single input)
clear-icon-start The clear icon wrapper for the start input (two inputs).
clear-icon-end The clear icon wrapper for the end input (two inputs).
input The native input element.
prefix The prefix wrapper.
suffix The suffix wrapper.
helper-text The helper-text wrapper that renders content below the target input.

Note

All CSS Parts of the Calendar component can also be used to style the igc-date-range-picker calendar. Keep in mind that the content and the label parts of the calendar component are renamed respectively to calendar-content and calendar-label in the igc-date-range-picker scope.

Automation

Rendering and initialization

  • should be successfully initialized in the DOM (defined and rendered).
  • should not set an invalid date range as a value
  • should be successfully initialized with an initial value
  • should be successfully initialized in open state in dropdown mode
  • should be successfully initialized in open state in dialog mode
  • should pass automated WAI-ARIA tests in closed state
  • should pass automated WAI-ARIA tests in open state in dropdown mode
  • should pass automated WAI-ARIA tests in open state in dialog mode

Attributes and properties

  • should set value through attribute correctly in case the date values are valid ISO 8601 strings
  • should show/hide the picker based on the value of the open attribute
  • should keep the calendar selection and input values on changing the mode
  • should keep the calendar selection and input values on changing to two inputs and back to single
  • should set the active date of the calendar to the start of the range when value is initially set
  • should keep the picker open when keepOpenOnOutsideClick is enabled and a click if fired outside of the component
  • should keep the picker open when keepOpenOnSelect is enabled and a selection is made in the calendar picker
  • should not toggle the picker when readonly is set
  • should not clear the value through the clear icon, if readonly is set
  • should not allow to modify the value through selection or typing when readOnly is true
  • should modify value only through calendar selection and not input when nonEditable is true
  • should set properties of the calendar correctly
  • should set properties of the input(s) correctly
  • should set and render UI for a predefined set of ranges to select
  • should render slotted elements

Methods and events

  • Verify all API methods are invoked correctly and achieve their purpose.
  • Verify all events are emitted correctly.

Interactions

  • Verify the above listed key combinations work as expected.
  • should select a single date in dropdown mode and emit igcChange
  • should select a range of dates in dropdown mode and emit igcChange
  • should select a range of dates in dialog mode and emit igcChange when done is clicked
  • should not emit igcChange when cancel is clicked and the value should be the initial value (dialog mode)
  • should emit or not igcInput according to nonEditable property
  • should show/hide the calendar on clicking the toggle icon in dropdown & dialog mode & emit the open/close events
  • should show the calendar on clicking the input in dialog mode and emit the open/close events
  • should swap the selected dates after input & on losing focus if the end is earlier than the start

Predefined range values

  • should not render any chips when usePredefinedRanges is false and there are no custom ranges added
  • should render all predefined ranges and content in the actions slot
  • should emit igcChange when the chips are clicked
  • should render only custom chips, when usePredefinedRanges is false

Form integration

  • should be form associated
  • should not participate in form submission if the value is empty/invalid
  • should participate in form submission if there is a value and the value adheres to the validation constraints
  • should reset to its default value state on form reset
  • should reflect disabled ancestor state (fieldset/form)
  • should enforce required constraint
  • should enforce min value constraint
  • should enforce max value constraint
  • should invalidate the component if a disabled date is typed it in any of the inputs
  • should enforce custom constraint

Localization

  • should use the value of inputFormat for displayFormat, if it is not defined
  • should default inputFormat to whatever Intl.DateTimeFormat returns for the current locale
  • should properly set displayFormat to the set of predefined formats - 'short', 'medium', 'long', 'full'
  • should expose the default strings for localization
  • should update the masked value with the locale - single input
  • should set the mask of the single input per the display format (like dd/MM/yyyy - dd/MM/yyyy)

Validation

  • should render validation slots

Note

The rest of the properties/attributes should already be covered by the respective unit tests of the components used in the igc-calendar and igc-date-time-input.

ARIA Support

When the component is in dropdown mode, the underlying igc-calendar should have role="dialog"

RTL Support

The component should work in a Right-To-Left context without additional setup or configuration.

In the POC phase, the approach to slot the two inputs like:

 <igc-date-range-picker>
      <igc-date-range-input
        label="Start date"
        slot="start"
        name="date-range-start-name"
      >
      </igc-date-range-input>
      <igc-date-range-input
        label="End date"
        slot="end"
        name="date-range-end-name"
      ></igc-date-range-input>
    </igc-date-range-picker>

was tested, but discarded. There are potentially two approaches. First is to create such a wrapper component for the igc-date-time-input and pass properties to it. This would allow defining the needed icons, however, comes with the overhead of setting all properties through an additional layer. Second might be to slot igc-date-time-inputs directly and possibly hook into a lifecycle method to "enforce" the toggle and clear icons, which might not be a best practice either.

The inputs will be rendered by the component and can be customized through properties - such as labelStart, labelEnd, etc.

Assumptions Limitation Notes

Specify all referenced external sources

Clone this wiki locally