Date Picker
Use @schedulespark/date-picker for framework-free date input popovers.
Date Picker
@schedulespark/date-picker provides a framework-free month-grid date picker for ScheduleSpark forms.
Related terms: npm, ScheduleSpark, @schedulespark/date-picker, date picker, datepicker, date input, calendar input, calendar, scheduling, month grid, year picker, date range, disabled dates, keyboard navigation, CSS variables, forms, vanilla JavaScript, framework-free, TypeScript.
Install
npm install @schedulespark/date-pickerImport the stylesheet once wherever your app loads global CSS:
import "@schedulespark/date-picker/styles.css";This package has zero runtime dependencies. It is framework-free and does not require React or any other ScheduleSpark package.
Basic Usage
import { createDatePicker } from "@schedulespark/date-picker";
import "@schedulespark/date-picker/styles.css";
const host = document.querySelector("#date-picker");
if (!(host instanceof HTMLElement)) {
throw new Error("Missing #date-picker host");
}
const picker = createDatePicker({
label: "Start date",
value: "2026-07-04",
minDate: "2026-01-01",
maxDate: "2026-12-31",
weekStartsOn: 0,
onChange: (value) => {
console.log(value);
}
});
picker.mount(host);onChange always receives a normalized YYYY-MM-DD string. The picker stores only a date string, not a JavaScript Date, so it is safe for form fields and API payloads that expect calendar dates.
Dynamic Range Updates
picker.setRange("2026-07-01", "2026-07-31");
picker.setValue("2026-07-15");
picker.setDisabled(false);Use setRange when another field changes the allowed window, for example an end-date picker whose minDate follows the selected start date. The instance updates in place without rebuilding DOM.
API Reference
interface DatePickerOptions {
disabled?: boolean;
id?: string;
isDateDisabled?: (date: string) => boolean;
label?: string;
maxDate?: string;
minDate?: string;
name?: string;
onChange?: (value: string) => void;
placeholder?: string;
required?: boolean;
value?: string;
weekStartsOn?: number;
}| Option | Type | Default | Notes |
|---|---|---|---|
value | string | "" | Current date as YYYY-MM-DD. |
onChange | (value: string) => void | undefined | Receives normalized YYYY-MM-DD after a valid selection or typed value. |
minDate | string | undefined | Inclusive lower bound as YYYY-MM-DD. |
maxDate | string | undefined | Inclusive upper bound as YYYY-MM-DD. |
isDateDisabled | (date: string) => boolean | undefined | Custom disabled-date predicate for holidays, blackout dates, or closed days. |
weekStartsOn | number | 0 | First day of the week, 0 Sunday through 6 Saturday. |
label | string | undefined | Optional field label. |
id | string | generated | Input id. Pass a stable id when pairing with external labels. |
name | string | undefined | Input name for native form submission. |
placeholder | string | undefined | Input placeholder. |
required | boolean | false | Native required attribute. |
disabled | boolean | false | Disables the input and picker controls. |
Instance Methods
| Method | Notes |
|---|---|
mount(host) | Renders the labeled input and popover inside an HTMLElement. |
setValue(value) | Updates the selected value. Invalid input is rejected instead of clearing the field. |
setRange(minDate, maxDate) | Updates inclusive bounds in place. Pass undefined to clear either side. |
setDisabled(disabled) | Toggles disabled state. |
destroy() | Removes the picker DOM. |
Date Rules
- Values must use
YYYY-MM-DD. minDateandmaxDateare inclusive.- Out-of-range days stay visible but disabled.
isDateDisabledreceives normalizedYYYY-MM-DDstrings.- The package does not perform timezone conversion. Treat values as plain calendar dates.
Keyboard Navigation
| Key | Behavior |
|---|---|
| Arrow Left / Right | Move focus by one day. |
| Arrow Up / Down | Move focus by one week. |
| Home / End | Move focus to the start or end of the visible week. |
| Page Up / Down | Move focus by one month. |
| Shift + Page Up / Down | Move focus by one year. |
| Enter / Space | Select the focused day. |
| Escape | Close the popover without changing the value. |
Theming
Override CSS custom properties on .ssp-date-picker:
| Variable | Default | Affects |
|---|---|---|
--ssp-date-picker-text | #18211f | Root text and option text. |
--ssp-date-picker-label-text | #33413d | Field label and weekday header. |
--ssp-date-picker-border | #c7d1cc / #d8e0dc | Input, popover, and button borders. |
--ssp-date-picker-bg | #fff | Input, button, and popover backgrounds. |
--ssp-date-picker-accent | #11735f | Focus ring and today/focus indicators. |
--ssp-date-picker-accent-bg | #dff4eb | Selected option background. |
--ssp-date-picker-accent-text | #0a4f42 | Selected option text. |
--ssp-date-picker-disabled-bg | #eef2f0 | Disabled option background. |
--ssp-date-picker-disabled-text | #8a9692 | Disabled and outside-month text. |
--ssp-date-picker-radius | 0.5rem | Popover radius. |
--ssp-date-picker-popover-shadow | package default | Popover shadow. |
--ssp-date-picker-z-index | 20 | Popover stacking order. |
--ssp-date-picker-popover-min-width | 18rem | Popover minimum width. |
--ssp-date-picker-popover-max-width | min(94vw, 22rem) | Popover maximum width. |
--ssp-date-picker-day-size | 2.25rem | Day/month/year option size. |
.dark-form .ssp-date-picker {
--ssp-date-picker-text: #e7f1ee;
--ssp-date-picker-label-text: #b7c4bf;
--ssp-date-picker-border: #33413d;
--ssp-date-picker-bg: #17211e;
--ssp-date-picker-accent: #4fd1a5;
--ssp-date-picker-accent-bg: #163a2f;
--ssp-date-picker-accent-text: #8ff0c7;
}Framework Integration
Mount once after the host element exists and destroy on unmount. In React, keep the instance in a ref and call setValue, setRange, or setDisabled from effects instead of recreating it for every prop change.
Troubleshooting
| Symptom | Check |
|---|---|
| Popover is behind a modal | Raise --ssp-date-picker-z-index on .ssp-date-picker. |
| Date does not update | Confirm the value is YYYY-MM-DD and inside minDate / maxDate. |
| Custom disabled dates do not apply | Return true from isDateDisabled(date) for disabled dates. |
| Styles are missing | Import @schedulespark/date-picker/styles.css. |