universal-datetime-picker

Getting started

This guide gets a working picker on screen. After that, pick the entry point and props that match your app.

What this package does

universal-datetime-picker renders an accessible calendar for date, time, datetime, or date-range selection. React gets native components. Other stacks use vanilla factories or Web Components from the same package.

Who should use it

  • You need a calendar UI, not only date parsing.
  • You want one CSS file and shared behavior across frameworks.
  • You are fine with dayjs as a runtime dependency for formatting and locales.

Features at a glance

  • Modes: date, time, datetime
  • Inline calendar, centered overlay, or anchored popover
  • Built-in input trigger (DateTimeInput)
  • Date range start/end selection
  • Light/dark theme and CSS variables
  • dayjs locales plus overrideable UI labels

Prerequisites

  • Node.js and a package manager, or a plain HTML page for CDN.
  • For React only: react and react-dom ≥ 18. Those peers are optional if you use vanilla, Web Components, or CDN.
  • dayjs is installed automatically as a runtime dependency of this package.

Install

npm install universal-datetime-picker

Yarn and pnpm work the same way.

yarn add universal-datetime-picker
pnpm add universal-datetime-picker

Always import the stylesheet

Without CSS, the calendar has almost no layout. Import once near your app root:

import "universal-datetime-picker/style.css";

CDN equivalent (pin a version in production):

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/universal-datetime-picker@2.1.2/dist/style.css"
/>

Verify it worked

  1. Install completes without peer errors for your stack.
  2. The stylesheet loads (network tab or a visible green primary color).
  3. A picker appears. For non-inline React DateTime, the overlay opens by default unless you set defaultOpen={false}.
  4. Selecting a date (and OK for datetime/time) updates your state or logs a value.

Minimal React example

import { useState } from "react";
import DateTime, { DateTimeInput } from "universal-datetime-picker";
import "universal-datetime-picker/style.css";

export function App() {
  const [value, setValue] = useState<Date | null>(null);

  return (
    <>
      <DateTimeInput
        mode="date"
        asString={false}
        value={value}
        onChange={(next) => setValue(next instanceof Date ? next : null)}
      />
      <DateTime
        inline
        mode="date"
        asString={false}
        value={value}
        onChange={(next) => setValue(next instanceof Date ? next : null)}
      />
    </>
  );
}

Next.js App Router: put this in a Client Component ("use client"). See Next.js.

Minimal vanilla example

import { createDateTimePicker } from "universal-datetime-picker/vanilla";
import "universal-datetime-picker/style.css";

const mount = document.querySelector("#picker");
if (!mount) throw new Error("#picker missing");

const picker = createDateTimePicker(mount, {
  mode: "date",
  inline: true,
  asString: false,
  onChange: (value) => console.log(value),
});

// Later: picker.destroy();

Minimal CDN example

<!doctype html>
<html lang="en">
  <head>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/universal-datetime-picker@2.1.2/dist/style.css"
    />
  </head>
  <body>
    <datetime-picker mode="date" inline></datetime-picker>
    <script src="https://cdn.jsdelivr.net/npm/universal-datetime-picker@2.1.2/dist/cdn/universal-datetime-picker.iife.js"></script>
    <script>
      UniversalDateTimePicker.defineCustomElements();
      document
        .querySelector("datetime-picker")
        .addEventListener("change", (e) => console.log(e.detail));
    </script>
  </body>
</html>

Default open behavior

For non-inline DateTime and DateTimeRange, defaultOpen is true. The overlay appears as soon as the component mounts. Pass defaultOpen={false} (or control open) when you open from a button. DateTimeInput defaults to closed because it owns its trigger. Details: Overlay and triggers.

Next steps