v1.6.x-dev NDS IQ v6

Date Picker - National Design System

Interactive calendar component for selecting dates with support for both Gregorian and Hijri calendars

Date Picker Input

Text input with calendar dropdown for single date or date range selection

<div class="nds-form-container nds-date-picker"> <div class="nds-form-header"> <label for="date-picker-1"> <span class="nds-label">Select date</span> </label> </div> <div class="nds-form-control"> <div class="nds-form-action"> <button type="button" class="nds-btn nds-subtle nds-md date-picker-toggle" aria-label="Calendar Toggler"> <i class="nds-icon nds-hgi-calendar-03" aria-hidden="true"></i> </button> </div> <input type="text" id="date-picker-1" class="nds-input nds-date-input" placeholder="DD/MM/YYYY" data-year-before="40" data-year-after="5"> </div> <div class="nds-form-footer" data-feedback-target hidden></div> </div>

Custom Date Format

Add data-format to the container to override the default DD/MM/YYYY. Tokens: YYYY, YY, MM, M, DD, D. Any other character passes through literally. Applies to both Gregorian and Hijri, and both endpoints of a range. Token presence also drives the picker UI — omit the day tokens (MM/YYYY) for a month-only picker, use only year tokens (YYYY) for a year-only picker.

<div class="nds-form-container nds-date-picker" data-format="YYYY-MM-DD"> <div class="nds-form-header"> <label for="date-picker-iso"> <span class="nds-label">ISO format</span> </label> </div> <div class="nds-form-control"> <div class="nds-form-action"> <button type="button" class="nds-btn nds-subtle nds-md date-picker-toggle" aria-label="Calendar Toggler"> <i class="nds-icon nds-hgi-calendar-03" aria-hidden="true"></i> </button> </div> <input type="text" id="date-picker-iso" class="nds-input nds-date-input" placeholder="YYYY-MM-DD"> </div> <div class="nds-form-footer" data-feedback-target hidden></div> </div>

Date Bounds (Min / Max)

Add data-min-date and/or data-max-date to the input — values parsed with the picker's own data-format. Out-of-range day cells, month cells, and years render disabled; prev/next arrows and the Today button also disable at the boundary. Coexists with data-year-before / data-year-after — the tighter side wins. Hand-typed values are validated too: a badly formatted, out-of-range, or reversed-range value shows a localized field error on commit and blocks form submit through the standard forms validation (setCustomValidity), so the bounds can't be bypassed by editing the input directly.

<!-- No future dates --> <div class="nds-form-container nds-date-picker"> <div class="nds-form-header"> <label for="date-picker-no-future"> <span class="nds-label">Birth date</span> </label> </div> <div class="nds-form-control"> <div class="nds-form-action"> <button type="button" class="nds-btn nds-subtle nds-md date-picker-toggle" aria-label="Calendar Toggler"> <i class="nds-icon nds-hgi-calendar-03" aria-hidden="true"></i> </button> </div> <input type="text" id="date-picker-no-future" class="nds-input nds-date-input" placeholder="DD/MM/YYYY" data-max-date="31/12/2025"> </div> <div class="nds-form-footer" data-feedback-target hidden></div> </div>

Built-in Features

What you get out of the box with zero configuration

Auto-initialization

Loaded from nds-extras.min.js and registered as NDS.DatePicker by the loader. Scans for .nds-date-input inside .nds-form-control. Calendar dropdown is created lazily on first click. For dynamic content, call NDS.DatePicker.reinit().

Dual Calendar System

Supports both Gregorian and Hijri (Islamic lunar) calendars. Add the nds-hijri class to the container to switch. Conversion uses an accurate API reference with browser Intl and mathematical fallbacks.

Date Range Selection

Add the dateRange class to enable start/end date selection. Visual indicators highlight the range with connected cells between start and end dates.

Flexible Year Range

Control the year dropdown range with data-year-before and data-year-after attributes on the input. Defaults work for most use cases.

Bilingual Support

Month names, weekday labels, and button text render in Arabic or English based on the page language. Add data-lang="ar" on the input to override. Supports RTL and LTR layouts with correct dropdown positioning.

Smart Positioning

Calendar dropdown automatically flips above the input when there is not enough space below. On mobile, the dropdown centers horizontally for better visibility.

Usage Guidelines

When and how to use the date picker effectively

When to Use

  • Date selection in forms where the user needs a calendar view to pick a date
  • Booking, scheduling, and event planning interfaces
  • Use date range mode for report filters, travel dates, or any start/end date pair
  • Use Hijri mode for government forms and services that require Islamic calendar dates
  • For simple known dates (birth date, ID expiry), a plain text input with a date mask may be simpler
  • Pre-populate the input with a value in DD/MM/YYYY format to set an initial date

Best Practices

  • Always pair the date input with a visible label using <label for> so the field is accessible
  • Set data-year-before and data-year-after to meaningful ranges for the context (a birth date picker needs a wide past range, a booking picker needs a wider future range)
  • Use data-year-after="0" on input fields where future dates are not allowed: the year dropdown will stop at the current year
  • Listen on the change event of the input to react to selection and clear actions, both fire a native bubbling change event
  • For server-rendered forms that may be re-inserted into the DOM after a route change, call NDS.DatePicker.reinit() to wire new inputs
  • To remove a calendar from a specific input (for example in a dynamic list row), call instance.destroy() on the value returned by NDS.DatePicker.create()
  • Do not nest a date picker inside another dropmenu or portal: the calendar dropdown uses the dropmenu positioning system and expects to anchor to its own .nds-form-control parent

Keyboard Navigation

The calendar grid follows the WAI-ARIA Date Picker Dialog pattern with roving tabindex. Tab moves into the grid and lands on the selected day, today, or the first day of the month.

KeyAction
Arrow keysMove focus one day at a time within the calendar grid. Wraps to the adjacent month when crossing a boundary
HomeMove focus to the first day of the current week (Sunday)
EndMove focus to the last day of the current week (Saturday)
PageUpNavigate to the previous month and focus the first day of that month
PageDownNavigate to the next month and focus the first day of that month
Shift + PageUpNavigate back one year (12 months) and focus the first day
Shift + PageDownNavigate forward one year (12 months) and focus the first day
Enter / SpaceSelect the focused day
EscapeClose the calendar dropdown (handled by the dropmenu system)

Data Attributes

AttributeElementDescription
data-year-before.nds-date-inputNumber of years before today to include in the year dropdown. Default: 5
data-year-after.nds-date-inputNumber of years after today to include in the year dropdown. Default: 0 — omitted (or set to 0), the year list caps at the current year, preventing future year selection
data-lang.nds-date-inputOverride the calendar language. Values: ar, en. Defaults to the <html lang> attribute
data-format.nds-form-container.nds-date-pickerCustom date format. Tokens: YYYY, YY, MM, M, DD, D. Any other character passes through literally. Default: DD/MM/YYYY. Applies to both Gregorian and Hijri; both endpoints of a range use the same format. Token presence also selects the picker UI — omit day tokens for a month picker (day defaults to 1), use only year tokens for a year picker (day+month default to 1)
data-min-date.nds-date-inputEarliest selectable date. Parsed with the picker's data-format. Coexists with data-year-before — the tighter side wins. Typed values before it fail form validation
data-max-date.nds-date-inputLatest selectable date. Parsed with the picker's data-format. Coexists with data-year-after — the tighter side wins. Typed values after it fail form validation
data-clearable.nds-form-container.nds-date-pickerShows a Clear button in the footer that wipes the input value + state and closes the picker. Auto-enabled in range mode. Boolean (presence-only)

Events

EventTargetWhen
change.nds-date-inputFires on every day selection (bubbling, native). Also fires when the user clicks Clear, setting the input value to an empty string

CSS Custom Properties

Set on .nds-date-picker-dropdown to control the calendar panel dimensions.

PropertyDefaultDescription
--dropmenu-width100%Calendar panel width relative to the form control
--dropmenu-min-width350pxMinimum width of the calendar panel
--dropmenu-max-width500pxMaximum width of the calendar panel
--menu-padding0Padding override for the dropmenu container. Internal calendar sections supply their own padding
--btn-size40px (32px mobile)Size of each day cell button in the calendar grid

JavaScript API

Exposed as window.NDS.DatePicker by nds-extras.min.js. Use NDS.DatePicker.create() to attach a calendar instance to an existing input, and call instance.destroy() to tear it down cleanly.

// Auto-initialized by nds-loader.js (NDS.DatePicker namespace, nds-extras.min.js bundle). // No manual init needed. For dynamic content: NDS.DatePicker.reinit(); // Attach a calendar to a specific input and its .nds-form-control parent. // Returns the DatePickerCalendar instance (or the existing one if already wired). var instance = NDS.DatePicker.create(input, formControl); // Tear down a specific calendar instance (removes listeners, DOM, dropmenu). instance.destroy(); // Listen for date selection and clear events on the input. input.addEventListener('change', function (e) { console.log('Selected value:', e.target.value); // 'DD/MM/YYYY' or '' }); // Format a Gregorian date as DD/MM/YYYY NDS.DatePicker.CalendarConfig.gregorian.formatDate(new Date()); // Convert between Gregorian and Hijri NDS.DatePicker.CalendarConfig.hijri.gregorianToHijri(new Date()); // Returns: { day, month, year } NDS.DatePicker.CalendarConfig.hijri.hijriToGregorian(1447, 9, 1); // Returns: Date object // Create a Hijri date object NDS.DatePicker.createHijriDate(1, 9, 1447); // Read the converted date (opposite calendar) from the input var input = document.querySelector('.nds-date-input'); var converted = input.dataset.convertedDate; // Disable or require the date picker programmatically NDS.Forms.setState(input, 'disabled', true); NDS.Forms.setState(input, 'required', true);
Last Modified Date: 15/07/2026 - 05:38 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks