Calendar
Calendar component (Phlex) A date picker calendar with support for single, range, and multiple selection
Examples
Default
A date picker calendar built with date-fns and Stimulus.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar" %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new %>
</div>With Selected Date
Calendar with a pre-selected date.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", selected: Date.today %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(selected: Date.today) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(selected: Date.today) %>
</div>Date Range
Select a start and end date.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", mode: :range, selected: Date.today..(Date.today + 7) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(mode: :range, selected: Date.today..(Date.today + 7)) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(mode: :range, selected: Date.today..(Date.today + 7)) %>
</div>Multiple Months
Display 2 months side by side.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", number_of_months: 2 %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(number_of_months: 2) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(number_of_months: 2) %>
</div>Multiple Months with Range
Date range selection with 2 months displayed (hover to preview range).
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", mode: :range, number_of_months: 2 %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(mode: :range, number_of_months: 2) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(mode: :range, number_of_months: 2) %>
</div>With Dropdowns (Native)
Month/Year dropdown navigation using native HTML selects.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", show_dropdowns: true %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(show_dropdowns: true) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(show_dropdowns: true) %>
</div>With Dropdowns (UI Select)
Month/Year dropdown navigation using our custom UI Select component.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", show_dropdowns: true, use_native_select: false %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(show_dropdowns: true, use_native_select: false) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(show_dropdowns: true, use_native_select: false) %>
</div>With Min/Max Dates
Restricted date range (next 30 days only).
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", min_date: Date.today, max_date: Date.today + 30.days %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(min_date: Date.today, max_date: Date.today + 30.days) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(min_date: Date.today, max_date: Date.today + 30.days) %>
</div>Range With Min/Max Days
Range selection constrained to 3-7 days (hover over dates to see preview).
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", mode: :range, min_range_days: 3, max_range_days: 7 %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(mode: :range, min_range_days: 3, max_range_days: 7) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(mode: :range, min_range_days: 3, max_range_days: 7) %>
</div>Range With Disabled Dates
Range cannot include disabled dates (weekends disabled).
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", mode: :range, exclude_disabled: true, disabled_dates: weekend_dates %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(mode: :range, exclude_disabled: true, disabled_dates: weekend_dates) %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(mode: :range, exclude_disabled: true, disabled_dates: weekend_dates) %>
</div>Week Starts Monday
European-style calendar starting on Monday.
| Mo | Tu | We | Th | Fr | Sa | Su |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", week_starts_on: 1 %>
</div>| Mo | Tu | We | Th | Fr | Sa | Su |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(week_starts_on: 1) %>
</div>| Mo | Tu | We | Th | Fr | Sa | Su |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(week_starts_on: 1) %>
</div>Localization (pt-BR)
Calendar with Portuguese (Brazil) locale for month and weekday names.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render "ui/calendar", locale: "pt-BR" %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::Calendar.new(locale: "pt-BR") %>
</div>| Su | Mo | Tu | We | Th | Fr | Sa |
|---|
<div class="rounded-md border">
<%= render UI::CalendarComponent.new(locale: "pt-BR") %>
</div>Features
- Keyboard navigation
- Form integration
- Disabled state support
- ARIA attributes for accessibility
- Keyboard navigation with arrow keys
- Click outside to close
- Animation support
API Reference
Calendar
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| mode | Symbol | :single | The mode |
| selected | String | nil | The selected |
| month | String | Date.today | The month |
| number_of_months | Integer | 1 | The number of months |
| week_starts_on | Integer | 0 | The week starts on |
| locale | String | en-US | The locale |
| min_date | String | nil | The min date |
| max_date | String | nil | The max date |
| disabled_dates | Array | [] | The disabled dates |
| show_outside_days | Boolean | true | The show outside days |
| fixed_weeks | Boolean | false | The fixed weeks |
| show_dropdowns | Boolean | false | The show dropdowns |
| year_range | Integer | 100 | The year range |
| min_range_days | Integer | 0 | The min range days |
| max_range_days | Integer | 0 | The max range days |
| exclude_disabled | Boolean | false | The exclude disabled |
| use_native_select | Boolean | true | The use native select |
| name | String | nil | Form field name |
Keyboard Shortcuts
| Key | Description |
|---|---|
| Enter | Activates the focused element |
| Space | Activates the focused element |
| ArrowDown | Moves focus to next item |
| ArrowUp | Moves focus to previous item |
| ArrowLeft | Moves focus left or decreases value |
| ArrowRight | Moves focus right or increases value |
| Home | Moves focus to first item |
| End | Moves focus to last item |
| PageUp | Moves focus up by page |
| PageDown | Moves focus down by page |
JavaScript
Stimulus Controller
ui--calendarValues
| Name | Type | Description |
|---|---|---|
| mode | String | The mode |
Actions
initializeLocalepreviousMonthnextMonthpreviousYearnextYeargoToMonthgoToYeargoToTodaydispatchMonthChangeannounceMonthChangeannounceSelectionselectDateselectRangehasDisabledDatesInRangetoggleDateisInRangePreviewisRangePreviewStartisRangePreviewEndanimateMonthTransitionisSelectedisDisabledisInRangeisRangeStartisRangeEndmoveFocusselectFocusedDaterestoreFocusnavigateAndFocusmoveToStartOfWeekmoveToEndOfWeek