Modern time picker library built with TypeScript. Works with any framework or vanilla JavaScript.
Live Demo • Documentation • Changelog
Upgrading from v2? Check the upgrade guide below.
This project is actively maintained. Some areas planned for improvement:
any types remain in the codebaseContributions welcome! Feel free to open an issue or PR.
npm install timepicker-ui
Your app needs this global CSS rule for correct styling:
*,
*::before,
*::after {
box-sizing: border-box;
}
Most projects include this by default.
<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);
picker.create();
const picker = new TimepickerUI(input, {
theme: "dark",
clockType: "24h",
animation: true,
backdrop: true,
onConfirm: (data) => {
console.log("Selected time:", data);
},
});
picker.create();
import { useEffect, useRef } from "react";
import { TimepickerUI } from "timepicker-ui";
import "timepicker-ui/main.css";
function TimePickerComponent() {
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (inputRef.current) {
const picker = new TimepickerUI(inputRef.current, {
onConfirm: (data) => {
console.log("Time selected:", data);
},
});
picker.create();
return () => picker.destroy();
}
}, []);
return <input ref={inputRef} type="text" />;
}
Full documentation available at timepicker-ui.vercel.app/docs
| Option | Type | Default | Description |
|---|---|---|---|
clockType |
12h / 24h |
12h |
Clock format |
theme |
string | basic |
UI theme (9 themes available) |
animation |
boolean | true |
Enable animations |
backdrop |
boolean | true |
Show backdrop overlay |
editable |
boolean | false |
Allow manual input editing |
mobile |
boolean | false |
Force mobile version |
disabledTime |
object | undefined |
Disable specific hours/minutes |
incrementHours |
number | 1 |
Hour increment step |
incrementMinutes |
number | 1 |
Minute increment step |
switchToMinutesAfterSelectHour |
boolean | true |
Auto-switch to minutes after hour |
okLabel |
string | OK |
OK button text |
cancelLabel |
string | CANCEL |
Cancel button text |
onConfirm |
function | undefined |
Callback when time is confirmed |
onCancel |
function | undefined |
Callback when cancelled |
onOpen |
function | undefined |
Callback when picker opens |
onUpdate |
function | undefined |
Callback when time is updated |
onSelectHour |
function | undefined |
Callback when hour is selected |
onSelectMinute |
function | undefined |
Callback when minute is selected |
onSelectAM |
function | undefined |
Callback when AM is selected |
onSelectPM |
function | undefined |
Callback when PM is selected |
onError |
function | undefined |
Callback when error occurs |
Available themes: basic, crane-straight, crane-radius, m3, dark, glassmorphic, pastel, ai, cyberpunk
import "timepicker-ui/main.css"; // Required base styles
import "timepicker-ui/theme-dark.css"; // Specific theme
const picker = new TimepickerUI(input, {
theme: "dark",
});
const picker = new TimepickerUI(input, {
disabledTime: {
hours: [1, 3, 5, 8],
minutes: [15, 30, 45],
interval: "10:00 AM - 2:00 PM",
},
});
const picker = new TimepickerUI(input, {
inline: {
enabled: true,
containerId: "timepicker-container",
showButtons: false,
autoUpdate: true,
},
});
const picker = new TimepickerUI(input, options);
picker.create(); // Initialize
picker.open(); // Open programmatically
picker.close(); // Close
picker.destroy(); // Clean up
picker.getValue(); // Get current time
picker.setValue("14:30"); // Set time
picker.update({ options }); // Update configuration
TimepickerUI.getById("my-id"); // Get instance by ID
TimepickerUI.getAllInstances(); // Get all instances
TimepickerUI.destroyAll(); // Destroy all instances
Listen to timepicker events using the new EventEmitter API (recommended) or the legacy DOM events (deprecated, will be removed in v4):
const picker = new TimepickerUI(input);
picker.create();
picker.on("confirm", (data) => {
console.log("Time confirmed:", data);
});
picker.on("cancel", (data) => {
console.log("Cancelled:", data);
});
picker.on("open", () => {
console.log("Picker opened");
});
picker.on("update", (data) => {
console.log("Time updated:", data);
});
picker.on("select:hour", (data) => {
console.log("Hour selected:", data.hour);
});
picker.on("select:minute", (data) => {
console.log("Minute selected:", data.minutes);
});
picker.on("select:am", (data) => {
console.log("AM selected");
});
picker.on("select:pm", (data) => {
console.log("PM selected");
});
picker.on("error", (data) => {
console.log("Error:", data.error);
});
picker.once("confirm", (data) => {
console.log("This runs only once");
});
picker.off("confirm", handler);
Note: DOM events (e.g., timepicker:confirm) are deprecated and will be removed in v4. Please migrate to the new EventEmitter API shown above.
input.addEventListener("timepicker:confirm", (e) => {
console.log("Time:", e.detail);
});
input.addEventListener("timepicker:cancel", (e) => {
console.log("Cancelled");
});
Available legacy events: timepicker:open, timepicker:cancel, timepicker:confirm, timepicker:update, timepicker:select-hour, timepicker:select-minute, timepicker:select-am, timepicker:select-pm, timepicker:error
1. CSS must be imported manually
// v3 - Required
import "timepicker-ui/main.css";
2. Event names changed
// v2
input.addEventListener("show", ...);
input.addEventListener("accept", ...);
// v3
input.addEventListener("timepicker:open", ...);
input.addEventListener("timepicker:confirm", ...);
3. Use callbacks instead of events
// v3 - Recommended
const picker = new TimepickerUI(input, {
onConfirm: (data) => console.log(data),
onCancel: (data) => console.log("Cancelled"),
});
4. destroy() behavior
// v2 - Removed input from DOM
picker.destroy();
// v3 - Only destroys picker, keeps input
picker.destroy();
getById, destroyAll)getValue() and setValue() methodson, off, once)Starting in v3.x, we recommend using the new EventEmitter API instead of DOM events:
// Old way (deprecated, will be removed in v4)
input.addEventListener("timepicker:confirm", (e) => {
console.log(e.detail);
});
// New way (recommended)
picker.on("confirm", (data) => {
console.log(data);
});
Benefits:
once() for one-time listenersimport { useEffect, useRef } from "react";
import { TimepickerUI } from "timepicker-ui";
import "timepicker-ui/main.css";
function App() {
const inputRef = useRef(null);
useEffect(() => {
if (!inputRef.current) return;
const picker = new TimepickerUI(inputRef.current);
picker.create();
return () => picker.destroy();
}, []);
return <input ref={inputRef} placeholder="Select time" />;
}
<template>
<input ref="pickerInput" placeholder="Select time" />
</template>
<script setup>
import { onMounted, ref } from "vue";
import { TimepickerUI } from "timepicker-ui";
import "timepicker-ui/main.css";
const pickerInput = ref(null);
onMounted(() => {
if (!pickerInput.value) return;
const picker = new TimepickerUI(pickerInput.value);
picker.create();
});
</script>
import { Component, ElementRef, ViewChild, AfterViewInit } from "@angular/core";
import { TimepickerUI } from "timepicker-ui";
@Component({
selector: "app-root",
template: `<input #timepickerInput placeholder="Select time" />`,
})
export class App implements AfterViewInit {
@ViewChild("timepickerInput") inputRef!: ElementRef<HTMLInputElement>;
ngAfterViewInit() {
const picker = new TimepickerUI(this.inputRef.nativeElement);
picker.create();
}
}
Add to angular.json styles:
"styles": ["src/styles.css", "timepicker-ui/main.css"]
Development tooling is in the app/ directory. See app/README.md for details.
MIT © Piotr Glejzer
Contributions welcome! Check the issues page.
Chrome 60+, Firefox 55+, Safari 12+, Edge 79+, iOS Safari 12+, Chrome Android 60+