Skip to content
Devix Open Source

Customize

Styling and theming

import '@devix-labs/time-picker/styles.css';        // plain
import '@devix-labs/time-picker/styles.layer.css';  // the same, inside @layer devix

The layered stylesheet loses every specificity fight with your own CSS, which is what you want when the picker is dropped into a design system that already has opinions.

The input itself is left alone — it keeps whatever your form styles give it. The only rule applied to it is room at the end for the clock button.

Variables

.dxtp {
  --dxtp-radius: 10px;
  --dxtp-font-size: 13px;
  --dxtp-panel-width: 168px;
  --dxtp-panel-height: 264px;
  --dxtp-option-height: 32px;
  --dxtp-gap: 4px;

  --dxtp-bg: #fff;
  --dxtp-text: #18181b;
  --dxtp-muted: #71717a;
  --dxtp-border: #e4e4e7;
  --dxtp-shadow: 0 14px 40px rgb(17 17 28 / 0.16);
  --dxtp-accent: #ea4b71;          /* the chosen time, focus rings */
  --dxtp-active: #f4f4f5;          /* the row the keyboard is on */
  --dxtp-selected: color-mix(in srgb, var(--dxtp-accent) 12%, transparent);
  --dxtp-danger: #dc2626;
}

A wider panel with roomier rows is two lines:

.dxtp { --dxtp-panel-width: 220px; --dxtp-option-height: 40px; }

Dark

theme: 'auto' reads the page — Tailwind's .dark, data-theme, Bootstrap's data-bs-theme, or simply the background behind the widget — and re-reads it when a theme toggle flips. Override the dark palette by redefining the same variables under [data-theme='dark'].

Your classes

createTimePicker(input, {
  classNames: {
    panel: 'rounded-2xl shadow-xl',
    option: 'px-3 rounded-lg',
    note: 'text-emerald-600',
    footer: 'border-zinc-100',
  },
});

Parts: root, input, toggle, panel, list, option, note, columns, column, columnLabel, cell, footer, button, zones, zone, duration, error.

State

Selector When
.dxtp--open The panel is showing.
.dxtp--invalid What was typed is not a time, or not an available one.
.dxtp-option.is-selected The chosen time.
.dxtp-option.is-active The row the keyboard is on.
.dxtp-option.is-disabled Not available.
.dxtp-panel--sheet Showing as a bottom sheet.
.dxtp-panel--inline Rendered always-open.

Each slot's own className lands on its row, so a premium hour can look premium.

Three recipes

shadcn/ui

.dxtp {
  --dxtp-bg: hsl(var(--popover));
  --dxtp-text: hsl(var(--popover-foreground));
  --dxtp-muted: hsl(var(--muted-foreground));
  --dxtp-border: hsl(var(--border));
  --dxtp-accent: hsl(var(--primary));
  --dxtp-active: hsl(var(--accent));
  --dxtp-radius: var(--radius);
}

Bootstrap 5 — its variables, dark mode included, which data-bs-theme already drives:

.dxtp {
  --dxtp-bg: var(--bs-body-bg);
  --dxtp-text: var(--bs-body-color);
  --dxtp-muted: var(--bs-secondary-color);
  --dxtp-border: var(--bs-border-color);
  --dxtp-accent: var(--bs-primary);
  --dxtp-radius: var(--bs-border-radius);
}

Material 3

.dxtp {
  --dxtp-bg: var(--md-sys-color-surface-container);
  --dxtp-text: var(--md-sys-color-on-surface);
  --dxtp-muted: var(--md-sys-color-on-surface-variant);
  --dxtp-border: var(--md-sys-color-outline-variant);
  --dxtp-accent: var(--md-sys-color-primary);
  --dxtp-radius: 16px;
  --dxtp-option-height: 44px;
}

Icons

createTimePicker(input, {
  icons: {
    clock: '<i class="fa-regular fa-clock"></i>',
    check: '<svg viewBox="0 0 16 16">…</svg>',
  },
});
Updated 15 Sep 2026