Time Picker

Use @schedulespark/time-picker for framework-free analog and digital time inputs.

Time Picker

@schedulespark/time-picker provides framework-free analog and digital time picker modes for ScheduleSpark forms.

Related terms: npm, ScheduleSpark, @schedulespark/time-picker, time picker, timepicker, time input, analog time picker, digital time picker, scheduling, shift scheduling, 12-hour time, 24-hour time, minute step, min time, max time, keyboard input, CSS variables, forms, vanilla JavaScript, framework-free, TypeScript.

Install

npm install @schedulespark/time-picker

Import the stylesheet once wherever your app loads global CSS:

import "@schedulespark/time-picker/styles.css";

The package is framework-free and has no runtime dependencies.

Basic Usage

import { createTimePicker } from "@schedulespark/time-picker";
import "@schedulespark/time-picker/styles.css";

const host = document.querySelector("#time-picker");

if (!(host instanceof HTMLElement)) {
  throw new Error("Missing #time-picker host");
}

const picker = createTimePicker({
  label: "Start time",
  value: "09:00",
  minTime: "06:00",
  maxTime: "18:00",
  minuteStep: 15,
  mode: "analog",
  onChange: (value) => {
    console.log(value);
  }
});

picker.mount(host);

onChange always receives normalized HH:mm, regardless of whether the picker displays 12-hour or 24-hour labels.

Analog And Digital Modes

ModeBest forNotes
analogQuick selection with a compact visual clock.Pointer movement snaps to minuteStep; hour/minute controls respect minTime and maxTime.
digitalDense, predictable lists and keyboard-heavy forms.Renders step-based options; out-of-range options are disabled.

You can switch modes by recreating the picker with a different mode value. Values remain HH:mm.

API Reference

type TimePickerMode = "analog" | "digital";
type TimeFormat = "12h" | "24h";

interface TimePickerOptions {
  disabled?: boolean;
  id?: string;
  label?: string;
  maxTime?: string;
  minTime?: string;
  minuteStep?: number;
  mode?: TimePickerMode;
  name?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  required?: boolean;
  timeFormat?: TimeFormat;
  value?: string;
}
OptionTypeDefaultNotes
valuestring""Current time as HH:mm.
onChange(value: string) => voidundefinedReceives normalized HH:mm.
mode"analog" | "digital""analog"Picker UI mode.
timeFormat"24h" | "12h""24h"Display format only. Values remain HH:mm.
minuteStepnumber15Digital option interval and analog snap step.
minTimestringundefinedInclusive lower bound as HH:mm.
maxTimestringundefinedInclusive upper bound as HH:mm.
labelstringundefinedOptional field label.
idstringgeneratedInput id.
namestringundefinedInput name for native form submission.
placeholderstringundefinedInput placeholder.
requiredbooleanfalseNative required attribute.
disabledbooleanfalseDisables input and picker controls.

Instance Methods

MethodNotes
mount(host)Renders into an HTMLElement.
setValue(value)Updates the selected value.
setDisabled(disabled)Toggles disabled state.
destroy()Removes the picker DOM.

Range Rules

  • Values must be valid day times from 00:00 through 23:59.
  • minTime and maxTime are inclusive.
  • Typed values are normalized to HH:mm.
  • timeFormat affects display labels only.
  • Use maxTime: "11:59" for 11:59 AM and maxTime: "23:59" for 11:59 PM.
  • Digital values outside the range remain visible but disabled.

12-Hour Display

createTimePicker({
  label: "Close time",
  value: "17:30",
  timeFormat: "12h",
  minTime: "09:00",
  maxTime: "23:00",
  onChange(value) {
    // value is still "HH:mm", for example "17:45"
  }
});

Theming

Override CSS custom properties on .ssp-time-picker:

VariableDefaultAffects
--ssp-time-picker-text#18211fRoot text and button text.
--ssp-time-picker-label-text#33413dField label.
--ssp-time-picker-border#c7d1cc / #d8e0dcInput, button, popover, and clock borders.
--ssp-time-picker-bg#fffButton, popover, and clock backgrounds.
--ssp-time-picker-accent#11735fFocus ring, selected border, and clock center.
--ssp-time-picker-accent-bg#dff4ebActive and selected backgrounds.
--ssp-time-picker-accent-text#0a4f42Active and selected text.
--ssp-time-picker-disabled-bg#eef2f0Disabled button background.
--ssp-time-picker-disabled-text#8a9692Disabled button text.
--ssp-time-picker-radius0.5remPopover radius.
--ssp-time-picker-popover-shadowpackage defaultPopover shadow.
--ssp-time-picker-z-index20Popover stacking order.
--ssp-time-picker-popover-min-width16remPopover minimum width.
--ssp-time-picker-popover-max-widthmin(94vw, 22rem)Popover maximum width.
--ssp-time-picker-clock-sizemin(17rem, 78vw)Analog clock size.
.dark-form .ssp-time-picker {
  --ssp-time-picker-text: #e7f1ee;
  --ssp-time-picker-label-text: #b7c4bf;
  --ssp-time-picker-border: #33413d;
  --ssp-time-picker-bg: #17211e;
  --ssp-time-picker-accent: #4fd1a5;
  --ssp-time-picker-accent-bg: #163a2f;
  --ssp-time-picker-accent-text: #8ff0c7;
}

Framework Integration

Mount once after the host element exists and destroy on unmount. In React, store the picker instance in a ref and call setValue or setDisabled from effects when props change.

Troubleshooting

SymptomCheck
Value is AM/PM textThe API expects and emits HH:mm; timeFormat only changes display labels.
Options are disabledConfirm minTime, maxTime, and minuteStep produce selectable values.
Popover appears behind another layerRaise --ssp-time-picker-z-index.
Styles are missingImport @schedulespark/time-picker/styles.css.