chronova_picker

A premium, highly customizable Date & Time Picker system for Flutter, built around a single shared selection engine reused across every picker mode and presentation surface.

Status: MVP (v1.0.2). See Whats included below for exact scope.

Screenshots

screenshot 1 screenshot 2 screenshot 3
screenshot 4 screenshot 5 screenshot 6
screenshot 7 screenshot 8

Features

  • Single date picker (calendar + wheel styles)
  • Date range picker (calendar style, tap-tap range selection)
  • Time picker (analog clock + wheel styles, 12-hour display)
  • Dialog, bottom sheet, inline, and adaptive presentation
  • Light / dark / seed-based (ColorScheme.fromSeed) theming
  • Constraint engine: minimum/maximum date, disabled dates, custom selectable-date callback, minimum/maximum range duration
  • Simple static API for common cases, full parameter set for advanced ones
  • Zero third-party runtime dependencies
  • Calendar, range, and time logic are pure Dart and unit tested independent of any widget harness

Installation

Point at the local path while developing, or publish to pub.dev and use the usual version constraint:

dependencies:
  chronova_picker:
    path: ../chronova_picker # or a pub.dev version once published

Then:

import "package:chronova_picker/chronova_picker.dart";

Basic usage

final date = await ChronovaPicker.pickDate(context: context);
final range = await ChronovaPicker.pickDateRange(context: context);
final time = await ChronovaPicker.pickTime(context: context);

Each method returns null if the user cancels.

Advanced usage

final result = await ChronovaPicker.pickDateRange(
  context: context,
  initialStart: DateTime.now(),
  minimumDate: DateTime.now(),
  maximumDate: DateTime(2030),
  minimumDuration: const Duration(days: 1),
  maximumDuration: const Duration(days: 30),
  presentation: ChronovaPresentation.adaptive,
  theme: ChronovaThemeData.fromSeed(seedColor: Colors.blue),
);

Date picker styles

ChronovaPicker.pickDate(
  context: context,
  style: ChronovaDatePickerStyle.wheel, // or .calendar
);

Time picker styles

ChronovaPicker.pickTime(
  context: context,
  style: ChronovaTimePickerStyle.wheel, // or .clock
  minuteInterval: 15,
);

Presentation modes

ChronovaPresentation.dialog       // modal dialog
ChronovaPresentation.bottomSheet  // modal bottom sheet
ChronovaPresentation.adaptive     // bottom sheet on narrow screens, dialog on wide screens
ChronovaPresentation.inline       // no modal surface — embed the widget directly, see below

popover currently falls back to dialog (true desktop popover positioning is planned post-MVP — see Known limitations).

Inline (embedded) usage

For inline presentation, embed the picker widget directly instead of calling the async pickX methods:

ChronovaTheme(
  data: ChronovaThemeData.fromSeed(seedColor: Colors.blue),
  child: ChronovaDatePicker(
    showActions: false,
    onChanged: (ChronovaDateResult result) {
      // handle result.date
    },
  ),
)

Themes

ChronovaThemeData.light();
ChronovaThemeData.dark();
ChronovaThemeData.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark);

Theming is grouped by concern rather than exposed as a flat list of properties: colors, typography, calendar, time, button.

final theme = ChronovaThemeData.fromSeed(seedColor: Colors.teal).copyWith(
  calendar: const ChronovaCalendarThemeData(dayCellSize: 44),
);

Constraints

ChronovaPicker.pickDate(
  context: context,
  minimumDate: DateTime.now(),
  maximumDate: DateTime(2030),
  disabledDate: (date) => date.weekday == DateTime.saturday || date.weekday == DateTime.sunday,
);

Every constraint check flows through ChronovaConstraintValidator, which returns a structured ChronovaValidationResult (not just a boolean) so UI can explain why a date was rejected.

Accessibility

  • Every day cell, clock face, wheel item, and button carries an explicit Semantics label.
  • Minimum tap target sizing on interactive calendar cells.
  • Selected/disabled/today states are exposed as semantic properties, not just color.

Keyboard navigation (arrow keys, tab order, escape-to-close) and full reduced-motion support are on the roadmap — see below.

Platform support

Built entirely on Flutter/Material primitives (CustomPainter, ListWheelScrollView, Overlay-free dialogs/sheets) — no platform channels, so it should run anywhere Flutter does: Android, iOS, Web, macOS, Windows, Linux. Desktop-specific polish (hover states, two-month layouts, true popover positioning) is still on the roadmap.

Whats included in this MVP

  • Picker modes: date, dateRange, time
  • dateTime, dateTimeRange, and timeRange models exist (ChronovaDateTimeResult, etc.) but do not yet have dedicated composed picker widgets
  • Presentations: dialog, bottomSheet, inline, adaptive (popover falls back to dialog)
  • Date styles: calendar, wheel (compact not yet implemented)
  • Time styles: clock, wheel (digital not yet implemented)
  • English only; localization abstraction is not yet built
  • No haptics, no ChronovaPickerController, no built-in presets yet

Known limitations

  • No ChronovaPickerController yet — pickers are used directly via onChanged/onConfirm callbacks
  • No preset system yet (Today / Last 7 Days / etc.)
  • No true desktop popover positioning (falls back to dialog)
  • No RTL verification pass yet, though Row/Padding usage avoids most hardcoded directional assumptions
  • No keyboard navigation yet
  • Golden/visual regression tests not yet set up

Contributing

This is an early-stage package built incrementally. Please open an issue before large PRs so the architecture (core -> engine -> theme -> widgets -> pickers -> presentation -> public API, one-directional) stays consistent. In particular: code under lib/src/engine/ must never import Flutter UI classes.

License

MIT — see LICENSE.

Libraries

chronova_picker
chronova_picker: a premium, highly customizable date & time picker system for Flutter.
main