Language

NepaliDatePicker

A text input with a calendar popover for choosing a Bikram Sambat date.

function NepaliDatePicker(props: NepaliDatePickerProps): JSX.Element

A YYYY-MM-DD text input, an optional clear button, and a button that opens a NepaliCalendar in a popover. Typing and picking both produce a BSDate; clearing produces undefined.

import { useState } from "react";
import { NepaliDatePicker, type BSDate } from "bikram-sambat-react";
 
const [date, setDate] = useState<BSDate>();
 
<label htmlFor="dob">Date of birth</label>
<NepaliDatePicker id="dob" value={date} onChange={setDate} clearable />
Live demobikram-sambat-react@0.1.0
value = undefined

Props

Every prop is optional.

Value

PropTypeDefaultDescription
valueBSDate | undefined(uncontrolled)The selected date, controlled. Passing the prop at all, even as undefined, makes the picker controlled; undefined means empty.
defaultValueBSDateThe initial date, when uncontrolled.
onChange(date: BSDate | undefined) => voidCalled when the date changes: picked in the calendar, typed as a complete valid date, or cleared.

Calendar

These are passed on to the calendar in the popover, and apply to typed input too.

PropTypeDefaultDescription
minDateBSDateBS 1979-01-01The first selectable (and typeable) date, inclusive.
maxDateBSDateBS 2100-12-31The last selectable date, inclusive.
isDateDisabled(date: BSDate) => booleanReturn true to disable a day, in the calendar and when typed.
locale"en" | "ne""en"Language of the calendar and every label.
numerals"latin" | "devanagari"from localeDigits in the input text and the calendar.
todayBSDatethe device's dateThe day the calendar highlights as today.
showGregorianDatebooleanfalseShow AD dates in the calendar.
dayShape"circle" | "rounded" | "square""circle"Shape of the calendar's day buttons.

Input

PropTypeDefaultDescription
iconPosition"end" | "start" | "none""end"Where the calendar button goes. See icon position.
clearablebooleanfalseShow a button that clears the date.
placeholderstring"YYYY-MM-DD" / "वर्ष-महिना-गते"The input's placeholder, per locale.
disabledbooleanfalseDisable the whole picker.
readOnlybooleanfalseShow the value without allowing changes: the calendar button is disabled, the clear button hidden.
requiredbooleanMark the input as required, for native form validation.
namestringRender a hidden input with this name for native forms. See forms.
idstringid of the text input, for a <label htmlFor>.
aria-label, aria-labelledby, aria-describedbystringAccessible name and description of the input, when there's no <label>.

Styling

PropTypeDefaultDescription
classNamesPartial<DatePickerClassNames>A class for each part: root, field, input, clear, trigger, popover, icon, plus calendar for the calendar's own parts.
componentsPartial<DatePickerComponents>Replace the calendar's parts, and the TriggerIcon and ClearIcon.
unstyledbooleanfalseLeave out the default nc-* classes, on the picker and its calendar.
classNamestringExtra class for the root element.

See styling & customization.

Typing a date

The input accepts YYYY-MM-DD, zero-padded, in Latin or Devanagari digits: 2083-06-15 and २०८३-०६-१५ both work, whatever numerals is set to.

  • A date is committed only when it's complete, valid and selectable. While you type 2083-06-1, nothing happens; the moment the text becomes 2083-06-15, onChange is called. Partial or invalid text never produces a date.
  • Invalid text isn't flagged while you type. It's marked aria-invalid (and shown with a red border by the default styles) when the input loses focus or you press Enter. 2083-02-32, for example, is invalid because Jestha 2083 has 31 days.
  • Dates outside minDate/maxDate, or rejected by isDateDisabled, count as invalid.
  • Clearing the text calls onChange(undefined).
  • The text follows value. When value changes from outside, or a date is picked in the calendar, the text is rewritten as YYYY-MM-DD in the current numeral system. If a controlled parent rejects a typed date (doesn't update value), the text goes back to the current value.

The popover

  • Opening: click the calendar button, or press Alt+↓ in the input. Focus moves into the calendar, onto the selected date or else today.
  • Picking: click a day or press Enter/Space on it. The popover closes and focus returns to the calendar button.
  • Closing without picking: press Escape (focus returns to the button), click outside, or Tab out of it. Focus is never trapped.
  • Placement: the popover opens below the field, or above it when there isn't room below, and lines up with the field's right edge when it would overflow the viewport on the right.

Escape inside the picker is handled there and doesn't reach your own handlers, so a picker inside a modal dialog closes only itself.

Icon position

iconPosition puts the calendar button after the input (the default), before it, or nowhere:

<NepaliDatePicker iconPosition="end" />
<NepaliDatePicker iconPosition="start" />
<NepaliDatePicker iconPosition="none" />
Live demobikram-sambat-react@0.1.0

With "none", the input itself opens the calendar:

  • clicking the input opens it without moving focus, so you can keep typing;
  • ↓ in the input moves into the calendar (and opens it first if it's closed);
  • after a pick or Escape, focus returns to the input.

The input then has role="combobox" with aria-haspopup="dialog", aria-expanded and aria-controls, the WAI-ARIA combobox date picker pattern.

Clearing

clearable adds a clear button after the input while there's a date. It clears the value (onChange(undefined)) and moves focus to the input. It's hidden when the picker is disabled or readOnly.

Forms

NepaliDatePicker works with plain value/onChange, so it fits any form library. For a native <form>, give it a name: it renders a hidden input holding the date as ASCII YYYY-MM-DD (empty when there's no date), whatever the numeral system shown to the user.

<form action="/save">
  <NepaliDatePicker name="dob" locale="ne" defaultValue={{ year: 2083, month: 6, day: 15 }} />
  <button type="submit">Save</button>
</form>
// The input shows "२०८३-०६-१५"; the form submits dob=2083-06-15.

On the server, parseBsDate from bikram-sambat-ts turns the submitted text back into a BSDate.

ⓘ

Note: the text input itself has no name, so only the hidden YYYY-MM-DD value is submitted. required applies to the visible input, so the browser blocks submitting an empty picker.

Labels

Give the input an accessible name, like any form field: a <label htmlFor> pointing at id, or aria-label / aria-labelledby. The calendar button is labelled "Choose date", or "Choose date, 2083-06-15" once a date is set ("मिति छान्नुहोस्" in Nepali), and the popover is a dialog with the same label.

Disabled and read-only

disabled disables the input and both buttons. readOnly keeps the value visible and selectable as text, but the calendar button is disabled and the clear button is hidden.