Centrim Design System — a token-first, accessible React component system.
Date, time & calendar
One calendar surface powers every date control. Each trigger keeps the V2 field chrome, exactly one right-side icon, and the standard FormField label / helper / error hierarchy.
Family rules
Applies to Date, Date & time, Time, Month, Week and Range pickers alike.
What is this?
A single date & time family — DatePicker, DateTimePicker, TimePicker, MonthPicker, WeekPicker, DateRangePicker and the shared Calendar — composed from the existing V2 Button, Select, Popover, FormField and Feedback components.
When to use it
- Capturing a service date, resident birth date or maintenance schedule in a form
- Booking an appointment time or a recurring job slot
- Filtering a list or report by a date range
How to use it
- Exactly one supporting icon per trigger, always right-aligned: Calendar for dates, Clock for time
- All calendars render the shared Calendar component — never a bespoke grid
- Deferred pickers (date & time, presets, ranges) commit only on Apply
- Validation uses the existing FieldMessage error treatment
- Overlays use the V2 Popover: aligned to trigger, collision-padded, viewport-safe
What to avoid
- A custom icon alongside a native browser picker icon
- Communicating today, selected, range or disabled state through colour alone
- New overlay, focus or spacing treatments specific to calendars
One icon, on the right
Date picker
The default single-date control.
DatePicker
Pick one calendar date. A field-shaped trigger opens the shared Calendar in a V2 popover.
import { DatePicker } from "@/design-system";
When to use
- A single date such as a service date or resident birth date
- Dates where a calendar helps the user orient by weekday or month
- Forms already using FormField label and helper conventions
When not to use
- A date plus a time — use DateTimePicker
- A start and end date — use DateRangePicker
- Whole months or weeks — use MonthPicker or WeekPicker
Service date, with today and month navigation
The date the service is delivered.
Month and year are selectable for distant dates.
Disabled dates, required, error and read-only
Past dates cannot be scheduled.
Please choose a service date.
Set by the recurrence rule.
Do
- Keep the calendar icon as the only trigger icon
- Disable dates that are genuinely unavailable rather than validating after the fact
Don't
- Show a native picker icon next to the V2 icon
- Style today and selected identically
Date & time picker
Date and time in one deferred overlay.
DateTimePicker
Pick a date and a time together. The calendar and the hour / minute / AM-PM segments live in one popover and commit on Apply.
import { DateTimePicker } from "@/design-system";
When to use
- Appointments and visits
- Recurring job start moments
- Anything where the time of day changes meaning
When not to use
- Date-only values — use DatePicker
- Time-only values — use TimePicker
Appointment time
Confirm the date and the arrival time.
Validation and read-only
Choose a date and time.
Managed by the schedule.
Do
- Default the time to a sensible working hour
- Commit only when the user applies
Don't
- Show both a calendar and a clock icon on the trigger
- Close the overlay before the time is chosen
Time picker
Hour, minute and AM / PM.
TimePicker
Pick a time of day, either by segment selects or from a list of slots.
import { TimePicker } from "@/design-system";
When to use
- Service times and appointment slots
- Shift start and end times
When not to use
- Durations — use a NumberInput with a unit addon
- Date plus time — use DateTimePicker
Service time, 12-hour and 24-hour
Visits are scheduled in 15-minute slots.
24-hour clock, 30-minute slots.
Validation and disabled
Please choose a time.
Do
- Match the step to how the business actually books time
Don't
- Offer minute-level precision where 15-minute slots are the reality
Month & week pickers
Coarser periods, same chrome.
MonthPicker
Pick a whole month, with year navigation and a 12-cell grid.
import { MonthPicker } from "@/design-system";
When to use
- Reporting periods
- Billing months
When not to use
- Specific dates — use DatePicker
Reporting month
Reports are generated per calendar month.
Future months are not billable yet.
WeekPicker
Pick a whole week. Clicking any day selects that week and shows it as a connected range.
import { WeekPicker } from "@/design-system";
When to use
- Rota and roster periods
- Weekly maintenance schedules
When not to use
- A free-form range — use DateRangePicker
Rota week
Weeks run Monday to Sunday.
Date strip
A horizontal day selector with prev / next stepping.
DateStrip
Select a single day from a compact horizontal strip; the arrows step the visible window without changing the selection.
import { DateStrip } from "@/design-system";
When to use
- Booking and appointment day bars
- Roster or schedule day navigation
When not to use
- Picking a far-off date — use DatePicker
- A date range — use DateRangePicker
- A whole week as one value — use WeekPicker
Booking day, with month label and event dots
September 2026
Selected: Friday 25 September
Disabled
September 2026
Date range picker
Start, range and end — plus optional presets.
DateRangePicker
Pick a start and end date. Optional quick presets and an explicit Clear / Cancel / Apply footer keep reporting filters predictable.
import { DateRangePicker, DATE_RANGE_PRESETS } from "@/design-system";
When to use
- Date range filters on lists and reports
- Booking or availability windows
When not to use
- A single date — use DatePicker
- A calendar week — use WeekPicker
Filter with presets and Apply
Filters the maintenance list by completion date.
Immediate selection, and validation
Closes as soon as both ends are chosen.
Please choose a start and end date.
Do
- Add presets only where a relative range is genuinely useful
- Keep the label visible so the range is never ambiguous
Don't
- Force presets into every range picker
- Rely on the range fill alone to convey start and end
Date range filter
A compact preset dropdown for toolbar and table filters.
DateRangeFilter
A single compact trigger that opens a preset list — All time, Today, Yesterday, Last 7 / 30 days, This / Last month, Last 6 months — with an optional Custom range… entry that swaps to the shared range calendar. Presets commit immediately; a custom range commits on Apply.
import { DateRangeFilter, DATE_RANGE_FILTER_PRESETS } from "@/design-system";
When to use
- Date filters in table filter bars, dashboards and report toolbars
- Anywhere a quick relative period matters more than exact dates
When not to use
- Capturing a deliberate start and end date in a form — use DateRangePicker
- A single date — use DatePicker
Toolbar filter with presets and custom range
Compact size, and without custom range
Do
- Keep All time as the neutral default
- Use the resolved DateRange from onValueChange to filter the data
Don't
- Duplicate these presets inside DateRangePicker
- Hide the active period behind an icon-only trigger
Calendar
The shared surface, usable on its own.
Calendar
The one calendar surface of the system: month grid, header navigation, day states and an optional Today shortcut.
import { Calendar } from "@/design-system";
When to use
- Inline scheduling views
- Building a new date interaction that still needs the standard grid
When not to use
- Anywhere a picker already exists — compose the picker instead
Inline calendar with month / year selection and Today
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Disabled dates and outside-month days
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
Do
- Keep cells light — only today, selected and range carry weight
Don't
- Give every cell a border or shadow
- Re-style react-day-picker outside this component
Event calendar
A month grid of scheduled activities, with a toolbar, colour key and per-day events.
EventCalendar
Reviewing a schedule: month navigation, a tone-coded colour key, weekday headers and six week rows of day cells carrying their events.
import { EventCalendar } from "@/design-system";
When to use
- Activity, booking and appointment calendars
- Any month overview where events belong to days rather than to rows
When not to use
- Picking a date in a form — use DatePicker
- A list of events with no month context — use List or DataTable
Month view with a colour key and view controls
- Note
- Call
- Meeting
- Task
- Site tour
Do
- Keep the grid quiet — meaning comes from the event chips, not from cell chrome
- Always pass a legend when more than one tone is in play
Don't
- Show more than a few events per cell — use maxEventsPerDay and a day view
- Encode a category with colour alone