Skip to main content

Calendar Component for Rails

Calendar component for Rails. A date picker calendar with single and range selection, month and year views, and disabled-date handling.

Usage

<%= render "components/calendar" %>

With Selected Date

<%= render "components/calendar", selected: Date.today %>

Examples

Single Selection

<%= render "components/calendar",
      mode: :single,
      selected: Date.today %>

Range Selection

<%= render "components/calendar",
      mode: :range,
      selected: Date.today,
      selected_end: Date.today + 5 %>

With Date Constraints

<%= render "components/calendar",
      min_date: Date.today,
      max_date: Date.today + 14 %>

Week Starting Monday

<%= render "components/calendar",
      week_starts_on: :monday %>

Form Integration

<%= form_with model: @event do |f| %>
  <%= render "components/calendar",
        selected: @event.date,
        input_name: "event[date]" %>
<% end %>

Range Form Integration

<%= render "components/calendar",
      mode: :range,
      input_name: "booking[check_in]",
      input_name_end: "booking[check_out]" %>

API Reference

Calendar

Parameter Type Default Description
selected Date, String nil Selected start date; also sets the displayed month
selected_end Date, String nil Selected end date (range mode)
month Integer nil Display month (1-12); defaults to the selected or current month
year Integer nil Display year; defaults to the selected or current year
mode Symbol :single :single or :range
min_date Date, String nil Minimum selectable date; also disables the previous-month button
max_date Date, String nil Maximum selectable date; also disables the next-month button
disabled_dates Array [] Dates (Date or ISO string) to disable; kept when navigating months
show_outside_days Boolean true Show days from adjacent months; when false their cells stay empty, kept when navigating months
week_starts_on Symbol :sunday :sunday or :monday
cell_size String nil CSS length written to --cell-size (default 2rem); combined with any style: you pass
input_name String nil Renders a hidden input for the start date
input_name_end String nil Renders a hidden input for the end date; range mode only
css_classes String "" Additional CSS classes
html_options Hash {} Additional HTML attributes; data merges with the component's, style: is joined with cell_size

Month navigation rebuilds the grid in the browser. The partial passes data-calendar-disabled-dates-value (ISO date array) and data-calendar-show-outside-days-value to the controller so every month renders with the same rules as the first one.

Calendar Header

Rendered by the calendar; holds the previous/next buttons and the caption.

Parameter Type Default Description
month Integer required Display month
year Integer required Display year
month_name String required Caption text
css_classes String "" Additional CSS classes
html_options Hash {} Additional HTML attributes

Calendar Week

Rendered by the calendar, one per grid row.

Parameter Type Default Description
days Array required Seven Date objects
display_month Integer required Month being shown; other days get data-outside
selected_date Date nil Selected start date
selected_end_date Date nil Selected end date
mode Symbol :single :single or :range
min_date Date nil Minimum selectable date
max_date Date nil Maximum selectable date
disabled_dates Array [] Date objects to disable
show_outside_days Boolean true Render days outside display_month; when false an empty data-calendar-part="outside-day" cell holds the column
css_classes String "" Additional CSS classes
html_options Hash {} Additional HTML attributes

Day States

Attribute Description
data-today Today's date
data-outside Day from an adjacent month
data-state="selected" Selected day (single mode)
data-state="range-start" First day of a range
data-state="range-middle" Day inside a range
data-state="range-end" Last day of a range
disabled Outside min_date/max_date or in disabled_dates

Events and programmatic methods are listed under Stimulus Controller below.

Helper Methods

Method Description
calendar_to_date(value) Date from a Date, Time, DateTime or ISO string; nil when blank or unparseable
calendar_month_data(date, week_starts_on = :sunday) Hash with month, year, first_of_month, last_of_month, weeks, week_starts_on
calendar_month_name(date, format = :long) Localized "%B %Y", or "%b %Y" with :short
calendar_date_in_range?(date, start_date, end_date) True when date is between both ends, inclusive
calendar_weekday_names(week_starts_on = :sunday, format = :short) Weekday names; :short, :narrow or :long
calendar_data_attrs(mode: :single, selected: nil, selected_end: nil, month: nil, year: nil) data: hash for a hand-built calendar element

Stimulus Controller

calendar

Attached to the calendar root (data-controller="calendar"). The partial renders every value from its locals.

Value Type Default Description
month Number 0 Displayed month (1-12), from the month local or the selected/current month
year Number 0 Displayed year
selected String "" Selected start date, ISO 8601
selectedEnd String "" Selected end date, ISO 8601 (range mode)
minDate String "" Minimum selectable date, ISO 8601; also disables the previous-month button
maxDate String "" Maximum selectable date, ISO 8601; also disables the next-month button
mode String "single" single or range
weekStartsOn String "sunday" sunday or monday
disabledDates Array [] ISO dates to disable, applied to every month the controller builds
showOutsideDays Boolean true Render days from adjacent months when rebuilding the grid
Target Element
day Each day button (rendered by calendar/week, and by the controller when it rebuilds the grid)
input Hidden input for the start date, present when input_name is set
inputEnd Hidden input for the end date, present when input_name_end is set
prevButton Previous-month button in calendar/header
nextButton Next-month button in calendar/header
grid Declared but not rendered; the controller finds the grid by data-calendar-part="grid"
caption Declared but not rendered; the controller finds the caption by data-calendar-part="caption"
Action Description
previousMonth / nextMonth Bound on the header buttons; rebuild the grid for the new month and dispatch calendar:navigate
selectDay Bound on each day (click). Single mode toggles the day; range mode sets the start, then the end (a date before the start swaps them, the start again clears), and a third click starts a new range
handleKeydown Bound on each day (keydown). Arrow keys move by a day or a week, Home and End jump to the first and last day of the month; moving past the month navigates to the next or previous one. Disabled days are not focused
Event Detail Description
calendar:change mode, selected, selectedEnd A day was selected or cleared; dates are ISO strings or null. The hidden inputs are already updated
calendar:navigate month, year, selected, selectedEnd The visible month changed

Both events bubble and fire once per change.

For programmatic use the controller also exposes getValue() (returns { selected, selectedEnd }), select(date) (a Date or ISO string; follows the range rules in range mode) and clear(). select and clear dispatch calendar:change.