Single date selection
Default mode — one date per picker. Set selectType: 'single' or omit the option.
new RollDate('#date', { theme: 'main' });
Documentation
Everything in one place — installation, configuration, API, and examples.
RollDate supports single date selection, range selection, multiple dates, and time picking in one lightweight scrolling picker. Try live widgets on the demo page or generate code in the playground.
weekDaysNames must be Sunday-first (['Sun','Mon',…]). When startWeekFromMonday is true, RollDate rotates the header automatically.
const picker = new RollDate(selector, options);
RollDate Events extends the RollDate ecosystem with Month, Week, Day and Agenda views. Events · Events docs
Install from npm, use a CDN, or download the standalone ZIP.
npm install @rolldate/core
import '@rolldate/core/css/min'; import RollDate from '@rolldate/core';
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@rolldate/core/dist/css/rolldate.min.css"> <script src="https://cdn.jsdelivr.net/npm/@rolldate/core/dist/js/rolldate.min.js"></script>
Offline bundle with built dist/ files and a short README — no npm required.
Attach RollDate to an input or container element.
<input id="date" type="text" placeholder="Pick a date" /> new RollDate('#date', { theme: 'main' });
Create a picker by pointing RollDate at a target element and passing an optional configuration object.
new RollDate('#date'); new RollDate(['#start', '#end'], { selectType: 'range' });
| Argument | Type | Required | Description |
|---|---|---|---|
selector |
string | yes | CSS selector for one input or inline container (div, span, section). |
selector |
[string, string] | yes | Two inputs for range mode: start field and end field. |
options |
object | no | Configuration object (see tables below). |
Hook into selection and lifecycle events. All default to a no-op except selectDate.
| Callback | Default | Arguments / payload | When fired |
|---|---|---|---|
selectDate |
console.log |
SINGLEDate | nullRANGE Date[] (0–2 items)MULTI Date[]
|
After the selection changes. |
onOpen |
noop | { period, selectedDates } |
Popup opened. |
onClose |
noop | { period, selectedDates } |
Popup closed. |
onViewChange |
noop | { from, to, current: { year, month, decade } } |
Switching day / month / year view. |
onHoverDate |
noop | (date, meta) — date is Date | null |
Hovering a day (or leaving the calendar). |
Call these on the instance returned by the constructor.
| Name | Signature | Returns | Description |
|---|---|---|---|
open() | () | void | Open popup (popup mode). |
close() | ({ restoreFocus?: boolean }?) | void | Close popup. Pass { restoreFocus: true } to return focus to the opener. |
selectToday() | () | void | Select today; applies current time if enableTime. |
clearSelection() | () | void | Clear all selected dates. |
goToDate(date) | (Date|string) | boolean | Navigate to a date without changing selection. |
getValue() | () | Date | Date[] | null | Current selection. |
setValue(value) | (Date|string|array|null) | boolean | Set selection programmatically; null clears. |
getViewMonth() | () | { year, month } | Month visible on screen (updates while scrolling). |
getViewDate() | () | Date | First day of the visible month. |
setDisabledDates(dates) | (DateRule[]) | void | Replace the full disabledDates rule list. |
setEnabledDates(dates?) | (DateRule[] \| undefined) | void | Replace the allowlist without recreating the picker. Pass undefined to turn it off; [] blocks every date. Non-array values are ignored and keep the current allowlist. Dates that become unavailable are removed from the selection and selectDate runs. |
disableDate(date) | (Date|string) | void | Disable one exact date. |
enableDate(date) | (Date|string) | void | Remove one exact denylist entry only. Kept for compatibility; it cannot override weekly, monthly, range, or callback disabledDates rules. |
isDateDisabled(date) | (Date|string) | boolean | True if the date cannot be selected (minDate/maxDate, enabledDates, disabledDates). |
setHighlightDates(dates) | (array) | void | Replace day dot markers. |
highlightDate(date, color?) | (Date|string, string?) | void | Add a dot marker (appends). |
unhighlightDate(date, color?) | (Date|string, string?) | void | Remove dot marker(s). |
getHighlightColors(date) | (Date|string) | (string|null)[] | Dot colors for a day. |
destroy() | () | void | Remove DOM nodes and detach listeners. |
selectedDates | getter | Date[] | Currently selected dates (read-only). |
period | getter | 'day' | 'month' | 'year' | Active calendar view. |
RollDate picks its mode from the type of the target element.
| Mode | Trigger | Behaviour |
|---|---|---|
| Popup | input or triggerSelector |
Calendar is appended to document.body, shown on focus/click. |
| Inline | div, span, section |
Calendar is rendered inside the element, always visible. |
A live inline instance. More interactive demos on the demo page or playground.
Popup vs inline is chosen by the element type: input → popup, div/section → inline.
Common patterns below. Every option is listed in the options reference.
Default mode — one date per picker. Set selectType: 'single' or omit the option.
new RollDate('#date', { theme: 'main' });
Single field with start and end in one value — ideal for filters and travel forms.
new RollDate('#trip', {
selectType: 'range',
closeOnSelect: false
});
Separate start and end fields. Pass an array of two selectors — RollDate wires both inputs.
new RollDate(['#check-in', '#check-out'], {
selectType: 'range'
});
Select many non-contiguous dates — useful for availability or multi-day bookings.
new RollDate('#dates', {
selectType: 'multi',
closeOnSelect: false
});
Keep the popup open until the user confirms time. Use closeOnSelect: false when time is enabled.
new RollDate('#appointment', {
theme: 'main',
enableTime: true,
use12Hour: true,
timePosition: 'right',
timeStep: 15,
closeOnSelect: false
});
Limit selectable dates with minDate / maxDate and block specific days.
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
new RollDate('#booking', {
minDate: new Date(),
maxDate: new Date(Date.now() + 90 * 864e5),
disabledDates: [tomorrow]
// strings work too: ['2026-07-22'] or ['22.07.2026'] with dateFormat
});
enabledDates is an allowlist: once you pass the option, every other date is blocked. enabledDates: [] blocks all dates. disabledDates is a denylist and always wins, so you can allow weekends and then close a holiday. Priority is minDate/maxDate → allowlist → denylist. Weekdays use Date#getDay() (0 = Sunday). Monthly rules use occurrence 1–5 or -1 (last). Use setEnabledDates to change the allowlist at runtime. enableDate only removes an exact denylist entry.
new RollDate('#weekends', {
startDate: '2026-12-20',
enabledDates: [
{ repeat: 'weekly', weekdays: [0, 6] }
],
disabledDates: [
'2026-12-26',
{ from: '2027-01-01', to: '2027-01-10' }
]
});
// Runtime: undefined turns the allowlist off, [] blocks every date
picker.setEnabledDates([{ repeat: 'weekly', weekdays: [0, 6] }]);
picker.setEnabledDates([]);
picker.setEnabledDates(undefined);
// Block the third Thursday of each month:
// disabledDates: [{ repeat: 'monthly', weekday: 4, occurrence: 3 }]
The optional presets plugin ships 28 ready ranges with English and Ukrainian labels. It is a separate file — the core stays small when you do not use it.
import RollDate from '@rolldate/core';
import { presets, lastN } from '@rolldate/core/presets';
// or <script src="rolldate-presets.min.js"> → window.RollDatePresets
new RollDate('#report', {
selectType: 'range',
closeOnSelect: false,
presetsLabel: 'Quick select',
rangePresets: [
...presets(['today', 'thisWeek', 'last7', 'last30', 'thisMonth', 'lastQuarter'], { locale: 'en' }),
lastN(6, 'month')
]
});
Preset ids: today, yesterday, tomorrow, thisWeek, lastWeek, nextWeek, weekToDate, weekend, last7, last14, last30, last90, next7, next14, next30, thisMonth, lastMonth, nextMonth, monthToDate, thisQuarter, lastQuarter, nextQuarter, quarterToDate, thisYear, lastYear, nextYear, yearToDate, last12Months. Options: locale, labels (override by id), startWeekFromMonday (defaults to the picker's), now. Custom windows: lastN(n, 'day' | 'week' | 'month'), nextN(…).
Built-in themes keep the presets bar below the calendar. Other placements are part of a licensed theme.
new RollDate('#report', {
selectType: 'range',
closeOnSelect: false,
rangePresets: [
{
label: '7 days',
getRange(picker) {
const start = picker.selectedDates[0] ?? picker.getViewDate();
const end = new Date(start);
end.setDate(end.getDate() + 6);
return [start, end];
}
},
{
label: 'This month',
getRange(picker) {
const { year, month } = picker.getViewMonth();
return [
new Date(year, month, 1),
new Date(year, month + 1, 0)
];
}
}
]
});
Mark days with colored dots — useful for bookings or event previews. Multiple colors per day via colors.
new RollDate('#calendar', {
highlightDates: [
{ date: '15.08.2026', color: '#22c55e' },
{ date: '20.08.2026', colors: ['#ef4444', '#a855f7'] }
]
});
picker.highlightDate('25.08.2026', '#eab308');
Override month and weekday labels. weekDaysNames stays Sunday-first; set startWeekFromMonday to rotate the header.
new RollDate('#date-de', {
locale: 'de-DE',
startWeekFromMonday: true,
monthsNames: ['Januar', 'Februar', /* … */],
monthsShortNames: ['Jan', 'Feb', /* … */],
weekDaysNames: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
});
Built-in main, dark, and light themes. Pass theme in the constructor or change at runtime with setTheme().
Theme colors live on .RollDate__container as --rd-* custom properties. Override the ones you need — no forked CSS. Full color list, defaults, and roles: CSS variables.
new RollDate('#date', { theme: 'dark' });
picker.setTheme('light');
.RollDate__container {
--rd-accent: #10b981;
--rd-accent-strong: #059669;
--rd-on-accent: #042f2e;
}
Prevent keyboard entry on mobile; open the picker from a button or icon.
<input id="date" type="text" readonly placeholder="Pick a date" /> <button type="button" id="open-date">Open</button>
new RollDate('#date', {
triggerSelector: '#open-date'
});
Any text and handler. Built-in actions today, clear, close; styles primary, secondary, link; position: 'left' groups a button at the start of the footer.
new RollDate('#date', {
selectType: 'range',
closeOnSelect: false,
footerButtons: [
{ text: 'Clear', action: 'clear', variant: 'link', position: 'left' },
{ text: 'Cancel', action: 'close', variant: 'secondary' },
{
text: 'Apply range',
variant: 'primary',
onClick(picker) {
save(picker.selectedDates);
picker.close();
}
}
]
});
RollDate uses semantic buttons and keyboard-friendly scrolling columns. Pair popup mode with a visible trigger and keep inputs readonly on touch devices so the native keyboard does not cover the calendar.
The infinite vertical scroll replaces month grids — fewer taps to reach distant dates. Tune wheel and touch with scrollSpeed (1 is the default; 0 keeps arrows and keyboard only). Use triggerSelector for icon buttons, and test with timePosition: 'bottom' when horizontal space is tight.
More interactive scenarios live on /demo; generate copy-paste snippets in the playground.
Yes. Zero runtime dependencies — no React, Vue, jQuery, Moment.js, Day.js, or CSS frameworks. Just JavaScript plus the bundled CSS.
Yes. Set selectType: 'range' on one input or pass two selectors for separate start/end fields. Range presets add quick-select buttons.
Yes. Set scrollSpeed — 1 is the built-in speed, 0.7 is slower, 1.5 is faster. 0 disables wheel and touch scrolling; month arrows and keyboard still work.
Yes. RollDate is built for touch scrolling and optional haptic feedback. On narrow viewports the time panel moves below the calendar automatically.
Yes — that is the default. Attach RollDate to any input or container with plain JavaScript. It also works inside React, Vue, Svelte, and other frameworks when mounted on the client.
Yes. Enable enableTime: true for scrollable hour and minute columns, with optional 12-hour mode and configurable timeStep.
Yes. RollDate is plain JavaScript. Mount it in useEffect / onMounted (or equivalent) and call destroy() on unmount. No official framework wrapper is required.
No. Zero runtime dependencies — only the browser Date object.
Call picker.destroy() before removing the host element from the DOM, or when your SPA route unmounts. This detaches listeners and removes injected popup nodes.
Yes. Create one RollDate instance per input or container. Each instance is independent — store references if you need to call methods later.
For popup mode on mobile, readonly is recommended so the native keyboard does not cover the calendar. Desktop users can still open the picker on focus/click.
Yes. disabledDates is a denylist (exact dates, ranges, weekly/monthly repeats, or a callback). enabledDates is an allowlist: once you pass it, every other date is blocked. enabledDates: [] blocks all dates. Change the allowlist later with setEnabledDates (undefined turns it off). disabledDates always wins. enableDate only removes an exact denylist entry — it cannot override a weekly or monthly rule. Combine with minDate / maxDate for booking windows.
Set theme to main, dark, or light, or override the color tokens on .RollDate__container. Every color variable is listed on the CSS variables page.
Yes. Override monthsNames, monthsShortNames, weekDaysNames, and optionally locale / dateFormat.
Attach to an input for popup. Pass a container element (div, section, …) for inline. Use triggerSelector for an external open button.
Yes. @rolldate/core ships with rolldate.d.ts — options, methods, and callbacks are typed out of the box.