Highly customizable time picker UI library for JavaScript and modern frameworks (React, Vue, Angular), with clock and wheel modes, zero dependencies, and full SSR support.
Live Demo • Documentation • Changelog • React Wrapper
| timepicker-ui | Typical UI lib | |
|---|---|---|
| Dependencies | 0 | 1-10+ |
| UI modes | Clock + Wheel + Compact | Clock only |
| Plugin system | Yes (range, timezone, wheel) | No |
| Framework lock-in | None - works everywhere | Often React-only |
| SSR safe | Yes, out of the box | Often requires workarounds |
| Tree-shakeable | Yes - plugins excluded if unused | Varies |
Full guide: Installation docs
npm install timepicker-ui
Full guide: Quick Start docs
<input id="timepicker" type="text" />
import { TimepickerUI } from "timepicker-ui";
import "timepicker-ui/main.css";
const input = document.querySelector("#timepicker");
const picker = new TimepickerUI(input, {
clock: { type: "24h" },
ui: { theme: "dark" },
callbacks: {
onConfirm: (data) => console.log("Selected:", data),
},
});
picker.create();
Note - Requires global
box-sizing: border-box(included by default in most frameworks) .
Full reference: Methods · Events · TypeScript
picker.create(); // Initialize
picker.open(); // Open programmatically
picker.close(); // Close
picker.destroy(); // Clean up
picker.getValue(); // Get current time string
picker.setValue("14:30"); // Set time
picker.update({ ... }); // Update options at runtime
// Events
picker.on("confirm", (data) => {});
picker.on("cancel", (data) => {});
picker.on("open", () => {});
picker.on("update", (data) => {});
picker.on("clear", (data) => {});
picker.on("error", (data) => {});
picker.once("confirm", handler);
picker.off("confirm", handler);
// Static
TimepickerUI.getById("my-id");
TimepickerUI.getAllInstances();
TimepickerUI.destroyAll();
Options are grouped into logical namespaces. Full reference: Options docs · Configuration guide
new TimepickerUI(input, {
clock: {
type: "12h" | "24h", // default: "12h"
incrementHours: 1,
incrementMinutes: 1,
disabledTime: { hours: [], minutes: [], interval: "" },
currentTime: boolean | object,
},
ui: {
theme: "basic" | "dark" | "m3-green" | "crane" | ..., // 10 themes
mode: "clock" | "wheel" | "compact-wheel", // default: "clock"
animation: true,
backdrop: true,
mobile: false,
editable: false,
inline: { enabled: false, containerId: "", showButtons: true, autoUpdate: false },
clearButton: false,
cssClass: "",
},
labels: { am, pm, ok, cancel, time, mobileTime, mobileHour, mobileMinute, clear },
behavior: { focusTrap: true, focusInputAfterClose: false, delayHandler: 300, id: "" },
callbacks: { onConfirm, onCancel, onOpen, onUpdate, onSelectHour, onSelectMinute, onSelectAM, onSelectPM, onError, onClear },
wheel: { placement: "auto" | "top" | "bottom", hideFooter: false, commitOnScroll: false, hideDisabled: false, ignoreOutsideClick: false },
});
Browse all themes: Theme docs · Live examples · Custom styling
Available: basic, crane, crane-straight, m3-green, m2, dark, glassmorphic, pastel, ai, cyberpunk
import "timepicker-ui/main.css"; // always required
import "timepicker-ui/theme-dark.css"; // theme-specific stylesheet
new TimepickerUI(input, { ui: { theme: "dark" } });
Docs: Plugins overview · Examples: Range · Timezone · Wheel
import { TimepickerUI, PluginRegistry } from "timepicker-ui";
import { RangePlugin } from "timepicker-ui/plugins/range";
import { TimezonePlugin } from "timepicker-ui/plugins/timezone";
import { WheelPlugin } from "timepicker-ui/plugins/wheel";
// Register once at app startup
PluginRegistry.register(RangePlugin);
PluginRegistry.register(TimezonePlugin);
PluginRegistry.register(WheelPlugin);
new TimepickerUI(input, { range: { enabled: true } });
Full examples: React · Vue / Angular / Svelte
React (quick example)
import { useEffect, useRef } from "react";
import { TimepickerUI } from "timepicker-ui";
import "timepicker-ui/main.css";
function TimePicker() {
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
if (!ref.current) return;
const picker = new TimepickerUI(ref.current);
picker.create();
return () => picker.destroy();
}, []);
return <input ref={ref} />;
}
There is also a dedicated React wrapper package.
See app/README.md for local development setup.
Contributions welcome! Open an issue or PR.
MIT © Piotr Glejzer