Pular para o conteúdo

Pickers (date + time)

components specs/components/pickers.kmd

Compound controls for selecting a date, time, date range, or date-time. Material parity (`/components/date-pickers` and `/components/time-pickers`). Covers docked vs modal date pickers, dial vs input time pickers, date ranges, locale rules, and keyboard navigation.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Pickers (date + time)

Facet Visual of Koder Design. Material parity: https://m3.material.io/components/date-pickers and https://m3.material.io/components/time-pickers.

Variant matrix

PickerModesUse
Date — modalCalendar grid, dialogDefault for date selection
Date — modal inputText input within dialogPower-user keyboard entry
Date — dockedCalendar attached to anchor inputContinuous form context
Date range — modalTwo-month calendar with range selectionTrip / report range
Time — dialAnalog clock faceDefault mobile entry
Time — inputTwo numeric fields HH:MMDesktop / keyboard preference

R1 — Date picker — modal (calendar)

Anatomy:

┌──────────────────────────────────────┐
│ Select date           ⌄  ⌃ Year      │
│ ────────────────────────────────────  │
│ ◂  May 2026                    ▸     │
│                                       │
│  S  M  T  W  T  F  S                 │
│                  1  2                 │
│  3  4  5  6  7  8  9                 │
│ 10 11 12 13 14 15 16                  │
│ 17 18 19 20 21 22 23                  │
│ 24 25 26 27 28 29 30                  │
│ 31                                    │
│                                       │
│                [Cancel]  [OK]         │
└──────────────────────────────────────┘
  • Container: dialog, 360 dp wide (mobile portrait) / 328 dp (desktop)
  • Header: shows current selection in headline-small
  • Month navigation: arrows + month name; tap month opens year picker
  • Day grid: 7 columns, 6 rows max; current day with circle outline; selected day with filled circle (accent color)
  • Footer: Cancel + OK text buttons
  • Today indicator: 1 px circle outline on today's date
  • Selected: filled circle, primary bg, on-primary text

R2 — Date picker — docked

Calendar floats below an anchor text field (no modal scrim). Used in forms with multiple date fields, where modal context-switch is heavy.

  • Anchor: text field with calendar icon trailing
  • On focus / icon tap: calendar appears below (above if no room)
  • Closes when user picks a date OR clicks outside
  • No scrim — page stays interactive

R3 — Date range picker

Two-month side-by-side calendar:

┌──────────────────────────────────────────────────────┐
│  Start date  →  End date                              │
│  Mar 12      →  Mar 28                                │
│ ──────────────────────────────────────────────────── │
│ ◂  March 2026         April 2026                ▸    │
│                                                       │
│  S  M  T  W  T  F  S    S  M  T  W  T  F  S          │
│  ...                     ...                          │
│                                                       │
│                       [Cancel]  [Save]                │
└──────────────────────────────────────────────────────┘
  • Two months visible; tap-and-drag OR two-tap to define range
  • Selected range: tonal bg (secondary-container) for days in range; filled circle on start + end
  • Mobile (Compact): one month with scroll, range still applies

R4 — Time picker — dial

Anatomy:

┌───────────────────────────────┐
│        Select time             │
│ ─────────────────────────────  │
│         ┌─ 10 : 30 ─┐  AM  PM │
│         └───────────┘          │
│                                │
│            ╭─────╮             │
│         11 │  ● 12             │
│       10  ╱│       ╲ 1         │
│         9  │   ●   │ 2         │
│           ╲│       │            │
│         8  └─────┘  3          │
│           7  6  5  4            │
│                                │
│            [Cancel]  [OK]      │
└───────────────────────────────┘
  • Display: HH : MM in large text; tap each segment to edit
  • Dial: hour ring (12 positions) or minute ring (60 positions, shown as 12 multiples of 5)
  • AM / PM segmented button (12-hour locale only)
  • Switch to keyboard: small icon toggles to Input variant

R5 — Time picker — input

Two text fields for HH and MM with : separator, plus AM/PM segmented button (12-hour locale only).

  • Each field: numeric keyboard on mobile; type-to-edit on desktop
  • Auto-advance: typing 2 digits in HH jumps to MM field
  • Validation: HH ∈ [0, 23] or [1, 12]; MM ∈ [0, 59]
  • Smaller dialog than dial variant (no clock face)

Used as default on desktop AND as toggle from dial when user prefers keyboard.

R6 — Locale rules

Pickers ALWAYS respect locale (per i18n/contract.kmd):

Locale aspectDriven by
First day of weekLocale (Sun / Mon / Sat)
Month / weekday namesLocale
Date format in headerLocale
12 / 24-hourLocale (en-US 12h; pt-BR 24h)
Number systemLocale (Latin / Arabic-Indic / etc.)

Override via prop only if domain requires (e.g., 24-hour for medical schedules in en-US). Document why.

R7 — Constraints

Pickers support:

  • min / max dates → out-of-range days disabled (38% opacity, not selectable)
  • disabledDates array → specific dates blocked (holidays, booked slots)
  • disabledRanges for date range picker

Disabled dates are still navigable via keyboard but cannot be selected; screen reader announces "Disabled".

R8 — Keyboard

KeyDate pickerTime picker
TabEnters → cycles through controlsSame
Arrow Up/DownPrevious/next weekIncrement by 1
Arrow Left/RightPrevious/next daySwitch HH ↔ MM
Page Up/DownPrevious/next monthIncrement by 5 (minute) / 1 (hour)
Home / EndStart/end of weekn/a
EnterSelects date / timeSelects
EscCancelsCancels

R9 — Accessibility

  • Dialog wrapper: role="dialog" + aria-modal="true" + aria-labelledby (pointing to "Select date")
  • Calendar grid: role="grid" + aria-label="Date picker"; each cell role="gridcell" with aria-selected on current
  • Out-of-range / disabled cells: aria-disabled="true"
  • Today cell: aria-current="date"
  • Time dial: role="slider" per ring (hour / minute) with aria-valuenow / valuemin / valuemax
  • Time input fields: native <input type="number"> semantics; labels read "Hour" / "Minute"
  • Screen reader announces selection: "Selected: Monday, May 11, 2026"

R10 — Animation

  • Modal open: scale-in 0.95 → 1 + fade (motion-medium)
  • Month change: slide horizontal (motion-medium)
  • Year picker: vertical scroll list (in-place, no slide)
  • Dial click: hand rotates to target position (motion-emphasized-decelerate)
  • Range drag: tonal fill grows in real-time
  • Reduced motion: instant transitions; no rotation animation (snap dial)

R11 — Per-preset variation

PresetDate visualTime visual
material3Tonal selection, rounded buttonsDial first, input toggle
material2Solid accent selectionDial first, no input toggle
ios_cupertinoWheel pickers stacked (year/month/day)Wheel pickers (HH/MM)
gnomeAdwaita calendar w/ accent todaySpin buttons for HH/MM
windows_11Combo button revealing flyoutCombo button revealing flyout
brutalistSharp grid, no animationSharp dial, no rotation
terminal_classicText prompt YYYY-MM-DD>Text prompt HH:MM>

R12 — Density

DensityCell sizeFooter height
Compact36 px48 px
Default40 px52 px
Comfortable48 px64 px

R13 — Forbidden patterns

  • ❌ Date picker without min / max for time-bounded contexts (birthdate, expiry, etc.)
  • ❌ Time picker dial < 240 dp diameter (touch targets too small)
  • ❌ Ignoring locale first-day-of-week
  • ❌ Picker that requires server roundtrip per month change (latency)
  • ❌ Picker without keyboard fallback (Input variant always available for accessibility)
  • ❌ Calendar grid that scrolls vertically through years (use year picker overlay instead)
  • ❌ Disabled dates without explanation (provide tooltip or description)
  • ❌ Range picker that allows end < start without auto-swap
  • i18n/contract.kmd — locale-aware formatting
  • themes/color-roles.kmdprimary for selected, secondary-container for range
  • themes/typography.kmdheadline-small for header, body-large for cells
  • components/text-fields.kmd — anchor for docked variant
  • components/dialogs.kmd — modal wrapper pattern
  • interaction/states.kmd — disabled / selected layers
  • foundations/elements.kmd — Control + Container families

Referências