Styling contract
Headless Datepicker styling is entirely slot and state driven. The controller gives you stable public attributes so you can style the same field, overlay, and calendar structure with plain CSS or utility classes. The current helper directives apply those public attrs for you, so most applications style the slots instead of mirroring attribute maps manually.
CSS contract table
| Selector | Purpose |
|---|---|
[data-slot="datepicker"] | Host root for shared field and popup theming. [tngDatepickerHost] applies this automatically. |
[data-slot="datepicker-field"] | Field wrapper containing the input shell and overlay anchor. |
[data-slot="datepicker-input-shell"] | Combined input and trigger chrome. |
[data-slot="datepicker-input"] | Editable text input surface. [tngDatepickerInput] applies the slot attr and input behavior. |
[data-slot="datepicker-trigger"] | Trigger button that toggles the calendar popup. [tngDatepickerTrigger] applies the slot and ARIA attrs. |
[data-slot="datepicker-overlay"] | Popup panel. [tngDatepickerOverlay] keeps this as the styling surface even after portaling. |
[data-slot="datepicker-header"] / [data-slot="datepicker-period-button"] | Header layout and month-year drill-down trigger. The nav/period directives add behavior without changing the styling hook. |
[data-slot="datepicker-cell"] | Day cell styling surface in the month grid. [tngDatepickerDayCell] applies item attrs and selection behavior. |
[data-slot="datepicker-month"] / [data-slot="datepicker-year"] | Month and year picker cells. [tngDatepickerMonthOption] and [tngDatepickerYearOption] apply the same public attrs. |
State selectors
| State | Applied on | Use case |
|---|---|---|
[data-open] | Host, trigger, input shell, overlay | Open-state emphasis and shell changes. |
[data-invalid] | Input shell | Manual input parse or bounds errors. |
[data-disabled] | Host, day/month/year cells | Disabled field or blocked date visuals. |
[data-selected] | Day/month/year cells | Committed selection state. |
[data-focus-visible] | Day/month/year cells | Keyboard focus treatment distinct from selection. |
[data-active] | Day/month/year cells | Current roving target when focus and selection differ. |
[data-in-month] | Day cells | Distinguishes spillover days from the current visible month. |
[data-hidden] | Day cells | Supports hidden placeholder cells when outside days are not shown. |
Common custom properties
| Token | Typical usage |
|---|---|
--tng-datepicker-radius | Field shell and overlay radius. |
--tng-datepicker-field-height | Combined input and trigger height. |
--tng-datepicker-overlay-gap | Distance between the field anchor and the popup. |
--tng-datepicker-overlay-padding | Popup panel padding. |
--tng-datepicker-grid-gap | Spacing between day, month, and year cells. |
--tng-datepicker-inline-gap / --tng-datepicker-nav-size | Trigger/nav spacing and wrapper-level control sizing. |
--tng-datepicker-day-cell-size | Base day-cell height. |
--tng-datepicker-picker-cell-size | Base month/year-cell height. |
--tng-datepicker-brand | Selected and focus-visible accent color. |
--tng-datepicker-border / --tng-datepicker-border-strong | Field chrome, panel edges, and stronger selected-state borders. |
--tng-datepicker-bg / --tng-datepicker-surface / --tng-datepicker-canvas | Field shell, control fills, and popup surface layers. |
--tng-datepicker-fg / --tng-datepicker-muted | Primary text, icon, weekday, and supporting copy colors. |
--tng-datepicker-focus / --tng-datepicker-focus-shadow | Focus ring color and the shared focus treatment used by the contract. |
--tng-datepicker-shadow / --tng-datepicker-ease | Popup elevation and contract transition timing. |
Scoped token overrides
css
.release-datepicker {
color-scheme: light;
--tng-datepicker-radius: 1rem;
--tng-datepicker-field-height: 2.9rem;
--tng-datepicker-overlay-gap: 0.56rem;
--tng-datepicker-overlay-padding: 0.72rem;
--tng-datepicker-grid-gap: clamp(0.14rem, 1.15%, 0.28rem);
--tng-datepicker-inline-gap: 0.36rem;
--tng-datepicker-day-cell-size: 2.2rem;
--tng-datepicker-picker-cell-size: 2.3rem;
--tng-datepicker-nav-size: 1.95rem;
--tng-datepicker-bg: #ffffff;
--tng-datepicker-surface: #f8fafc;
--tng-datepicker-canvas: #ffffff;
--tng-datepicker-fg: #0f172a;
--tng-datepicker-muted: #64748b;
--tng-datepicker-brand: #2563eb;
--tng-datepicker-border: #cbd5e1;
--tng-datepicker-border-strong: #94a3b8;
--tng-datepicker-focus: #2563eb;
--tng-datepicker-focus-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
--tng-datepicker-shadow:
0 22px 38px rgba(15, 23, 42, 0.12),
0 10px 20px rgba(15, 23, 42, 0.08);
}