Next.js Date Picker
A Next.js date picker for the App Router with Vanilla Calendar Pro: a client component for an inline calendar, and in AdminKit PRO a date and time input.
Use VanillaCalendar to show a calendar on a page, or to let people pick a date without typing it. It wraps Vanilla Calendar Pro 3 in AdminKit for Next.js. The free version draws an inline calendar, as on the Analytics dashboard. AdminKit PRO adds a date picker on a Bootstrap input, and a time picker.
VanillaCalendar is a client component, a file that starts with "use client", because the calendar is drawn in the browser. The HTML that Next.js renders on the server only has the empty <div>, or the empty input. Once the browser has taken over that HTML (hydration), a useEffect imports Vanilla Calendar Pro with a dynamic import() and draws the calendar. So the library never runs on the server.
The calendar follows the light or dark color mode. AdminKit passes selectedTheme: "system" and themeAttrDetect: "html[data-bs-theme]" before your options.
Example
This calendar selects today's date. It is a client component, so it works out that date in the browser, as the dashboard's calendar does:
"use client";
import { useState } from "react";
import { VanillaCalendar } from "@/components/plugins/vanilla-calendar";
export function TodayCalendar() {
const [today] = useState(() => new Date());
return (
<VanillaCalendar
options={{
selectedDates: [today],
enableJumpToSelectedDate: true,
firstWeekday: 0,
}}
/>
);
}A server component page could pass options={{ selectedDates: [new Date()] }} itself. With a static export, though, that code runs when the site is built, so the calendar would show the build date. Compute dates that depend on "now" in a client component, as above.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
options | VanillaCalendarOptions | Vanilla Calendar Pro's options; read once, when the calendar is created | |
input | boolean | false | PRO: render a read-only <input> that opens the calendar as a popup (inputMode) |
time | boolean | false | PRO: add the time picker extension |
Other props, such as className, id, placeholder and name, go to the <div>, or to the <input> with input. Later changes to options are ignored. Give the component a new key to create the calendar again. Options with callbacks, such as onChangeToInput, are functions. A server component cannot pass functions to the browser, so the component that defines them needs "use client". VanillaCalendar itself is in src/components/plugins/vanilla-calendar.tsx.
Date picker
This feature is only available in AdminKit PRO. Learn more.
When a form needs a date field, add input. It renders <input type="text" readOnly>, which opens the calendar as a popup. Write the input text yourself in onChangeToInput, as the demo's Datepickers client component does:
"use client";
import {
VanillaCalendar,
type VanillaCalendarOptions,
} from "@/components/plugins/vanilla-calendar";
const dueDate: VanillaCalendarOptions = {
firstWeekday: 0,
onChangeToInput(self) {
if (self.context.inputElement) {
self.context.inputElement.value = self.context.selectedDates[0] ?? "";
self.hide();
}
},
};
export function DueDateField() {
return (
<>
<label className="form-label" htmlFor="datepickerDue">Due date</label>
<VanillaCalendar
input
id="datepickerDue"
name="due"
className="form-control"
placeholder="Select date.."
options={dueDate}
/>
</>
);
}selectedDates holds "YYYY-MM-DD" strings. With a name, the text is part of the form's FormData. Send it to your API with fetch, because a static export has no Server Actions.
Ranges, multiple dates and time
This feature is only available in AdminKit PRO. Learn more.
For a range, several dates or a time, start from the same pattern. These are the other pickers of the Advanced Inputs demo:
| Picker | Props and options |
|---|---|
| Date and time | time, selectionTimeMode: 24; write `${date} ${self.context.selectedTime}` |
| Several dates | selectionDatesMode: "multiple"; write selectedDates.join(", ") |
| Date range | selectionDatesMode: "multiple-ranged"; write the first and last of selectedDates |
| Time only | time, selectionTimeMode: 24, selectionDatesMode: false, layouts: { default: "<#ControlTime />" }; write selectedTime |
A time picker:
const meetingTime: VanillaCalendarOptions = {
selectionTimeMode: 24,
selectionDatesMode: false,
layouts: { default: "<#ControlTime />" },
onChangeToInput(self) {
if (self.context.inputElement) {
self.context.inputElement.value = self.context.selectedTime;
}
},
};
<VanillaCalendar input time className="form-control" placeholder="Select time.." options={meetingTime} />Accessibility
- Pass an
idtoVanillaCalendarand point a<label htmlFor>at it. - The input is
readOnly: dates are picked in the calendar. The browser skips constraint validation on read-only inputs, sorequireddoes nothing there. Check the value before you submit. - Tell users the format the input shows, in the placeholder or in help text.
Related
- React Bootstrap datepicker: the same component in AdminKit for React (Vite)
- Bootstrap 5 datepicker: the date picker of the HTML version
- Calendar: the FullCalendar event calendar
- Form controls: inputs and submitting a form
- Advanced Inputs demo
Last updated on
Input maskPro
A Next.js input mask for the App Router in AdminKit PRO: a client component that loads Inputmask in the browser and masks dates, amounts and IP addresses.
Validation
Next.js Bootstrap form validation: the browser's own checks with Bootstrap feedback in a client component, and errors from your API shown with is-invalid.