-
Notifications
You must be signed in to change notification settings - Fork 4
Date picker specification
- Date-picker specification
Team Name: Astrea + Design and Web Development
Developer name: Bozhidara Pachilova
Designer name: Dilyana Dimova
- Damyan Petev
- Svilen Dimchevski
- Simeon Simeonov
- Radoslav Mirchev
Version | Author | Date | Notes |
---|---|---|---|
- | Radoslav Karaivanov | 2024-02-16 | Initial draft |
- | Radoslav Karaivanov | 2024-02-21 | Updated behaviors, ARIA and automation sections |
1.0 | Radoslav Karaivanov | 2024-03-15 | Finalized specification |
1.1 | Radoslav Karaivanov | 2024-04-22 | Added min, max constraint behavior |
1.2 | Radoslav Karaivanov | 2024-06-06 | Aligned dialog mode and focus behaviors with Angular version |
1.3 | Radoslav Karaivanov | 2024-09-25 | Added header-date slot |
The igc-date-picker
lets users select a date by either typing it in its input field or by
selecting it through a dropdown/dialog popup calendar view.
The igc-date-picker
must:
- let users input a date by either typing it in or picking one through its calendar component.
- be form associated and when configured as part of a form, participate in form submission and validation.
- expose configuration properties for modifying/localizing the input and display format of the date value in the input part.
- expose configuration properties for modifying/localizing the relevant parts of its calendar component.
- have adequate keyboard support for navigation and selection.
- be WAI-ARIA compliant.
As an end-user I expect to be able to:
- type in a date value inside the component
- select a date from the calendar picker of the component
- identify and distinguish the current date, selected date, special and disabled dates
- navigate and make edits in the input part 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
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 and/or readonly
- 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 input both during editing and display, by specifying a custom pattern/mask
- 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
- set the number of months rendered 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.
<igc-date-picker label="Start date"></igc-date-picker>
<igc-date-picker label="..." value="2024-01-01"></igc-date-picker>
<igc-date-picker label="..." mode="dialog" displayFormat="yyyy/MM/dd">
<p slot="title">...</p>
<button slot="actions" @click="${...}">Set today</button>
</igc-date-picker>
-
In dialog mode the input part will always be read-only and clicking anywhere on it will open the dialog.
-
When the
non-editable
attribute is set, the input part of the component is transformed into a read-only field. Selection is still available through the calendar picker. -
When the
readonly
attribute is set, the input part of the component is transformed into a read-only field. The picker part allows navigation but no selection. -
When there are
disabledDates
set and the component input is editable, typing in a disabled date must invalidate the component.
Note
This is more of a fringe scenario as in that case making the input non-editable and allowing the user to make a selection through the calendar widget is a better UX.
-
When the
min
ormax
attributes are set, the calendar widget will display dates outside of those constraint ranges as disabled, meaning the end-user won't be able to select them. -
When the picker is opened, regardless of the mode type, focus will be moved inside the calendar widget. If there is a selected value the, its corresponding calendar element will be focused. Otherwise the current active date of the calendar widget will be focused.
-
Once focus is inside the calendar subsequent keyboard navigation should trap focus inside the calendar widget until the user selects a date, presses Escape or clicks outside of the component.
-
When the component is configured in dropdown mode, no calendar header is rendered while in dialog mode this is controlled through the
hide-header
attribute.
The igc-date-picker
supports specifying an input mask pattern to customize and guide the end-user typing in the
input part of the component.
Mask tokens
Token | Description |
---|---|
d |
Date, will be coerced with a leading zero while editing |
dd |
Date with an explicitly set leading zero |
M |
Month, will be coerced with a leading zero while editing |
MM |
Month with an explicitly set leading zero |
yy |
Year, short format |
yyyy |
Year, full format |
Note
If inputFormat
is not explicitly set, it will default to whatever Intl.DateTimeFormat
returns for the currently set locale
of the component.
Similar to the inputFormat
, the displayFormat
property allows for specifying how the value of the component will be displayed in the input
while not editing. It supports a mask pattern and a few predefined formats.
Mask tokens
For the date value of 2024-07-09:
Token | Description | Result |
---|---|---|
d |
Day - minimum digits | 9 |
dd |
Day - zero padded | 09 |
M |
Month - minimum digits | 7 |
MM |
Month - zero padded | 07 |
MMM |
Month - Abbreviated | Jul |
MMMM |
Month - Full | July |
MMMMM |
Month - Narrow | J |
y |
Year - Numeric | 2024 |
yy |
Year - Two digit short form | 24 |
yyy |
Year - Numeric | 2024 |
yyyy |
Year - Numeric | 2024 |
For the predefined formats, the result depends on the locale
of the component.
Predefined
For the date value of 2024-07-09 with locale set to 'en':
Format | Result |
---|---|
short |
7/9/24 |
medium |
Jul 9, 2024 |
long |
July 9, 2024 |
full |
Tuesday, July 9, 2024 |
Note
If displayFormat
is not defined, it will use the value of inputFormat
.
As long as focus is within parts of the date 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 the input part 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 |
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.
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 | Date |
- | The value of the component |
name |
name |
No | string |
- | The name of the component |
min |
min |
No | Date |
- | The minimum value required for the component to remain valid |
max |
max |
No | Date |
- | The maximum 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 |
placeholder |
placeholder |
No | string |
- | The placeholder for the input |
label |
label |
No | string |
- | The label for the component |
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 is not focused Reference |
prompt |
prompt |
No | string |
_ |
The prompt character used for unfilled parts of the input 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 |
No? | 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 |
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 | IgcCalendarResourceStrings |
- | Resource strings for localization of the calendar picker |
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 part of the component of any user input |
stepUp |
(datePart?: DatePart, delta?: number): void |
Increments the passed in date part |
stepDown |
(datePart?: DatePart, delta?: number): void |
Decrements the passed in date part |
select |
(): void |
Selects the text in the input of the component |
setSelectionRange |
(start: number, end: number, direction?: 'none' | 'backward' | 'forward'): void |
Sets the text selection range in the input of the component |
setRangeText |
(replacement: string, start: number, end: number, mode?: 'select' | 'start' | 'end' | 'preserve'): void |
Replaces the selected text in the input and re-applies the mask |
setCustomValidity |
(message: string): void |
Sets a custom validation message. As long as message is not empty, the component is considered invalid |
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 of the component |
Name | Description |
---|---|
prefix | Renders content before the input |
clear-icon | Renders a clear icon template |
calendar-icon | Renders the icon/content for the calendar picker |
calendar-icon-open | Renders the icon/content for the picker in open state |
suffix | Renders content after the input |
helper-text | Renders content below the input |
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 |
Part | Description |
---|---|
label |
The label wrapper that renders content above the target input. |
container |
The main wrapper that holds all main input elements. |
input |
The native input element. |
prefix |
The prefix wrapper. |
suffix |
The suffix wrapper. |
calendar-icon |
The calendar icon wrapper for closed state. |
calendar-icon-open |
The calendar icon wrapper for opened state. |
clear-icon |
The clear icon wrapper. |
actions |
The actions wrapper. |
helper-text |
A 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-picker
. 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-picker
scope.
- should be successfully initialized in the DOM (defined and rendered).
- 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 render slotted elements - prefix, suffix, clear-icon, calendar-icon, helper-text, title, actions
- 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
- should show/hide the picker based on the value of the open attribute
- 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
Note
The rest of the properties/attributes should already be covered by the respective unit tests of the components used in the igc-date-picker.
- should open the picker on calling show()
- should close the picker on calling hide()
- should toggle the open state of the picker on calling toggle()
- should open the calendar picker on Alt + ArrowDown
- should close the calendar picker on Alt + ArrowUp
- should close the picker when in open state on pressing Escape
- should correctly trap keyboard navigation focus once focus is inside the calendar
- 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 the input
- should enforce custom constraint
- when the component is in dropdown mode, the underlying igc-calendar should have
role="dialog"
- the calendar should be labelled by the input part of the component
https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/
The component should work in a Right-To-Left context without additional setup or configuration.
None applicable