SutraUI.Calendar (Sutra UI v0.4.0)

View Source

A monthly calendar grid for date selection.

Renders a single month with prev/next navigation. Designed to be composed into date pickers or used standalone. Date state stays in the parent LiveView; the component emits plain LiveView events.

Examples

# Static calendar (current month)
<.calendar />

# Interactive — emit events on date click and month navigation
<.calendar
  year={@year}
  month={@month}
  selected={@selected}
  select_event="select_date"
  nav_event="nav_month"
/>

# Range selection
<.calendar
  mode="range"
  selected={@range_start}
  range_end={@range_end}
  select_event="select_range"
  nav_event="nav_month"
/>

# Monday-start week, with disabled dates
<.calendar
  week_start={1}
  disabled_dates={@holidays}
  selected={@selected}
  select_event="select_date"
/>

Attributes

  • year - Displayed year. Defaults to the selected date's year, then current year.
  • month - Displayed month (1-12). Defaults to the selected date's month, then current month.
  • selected - Selected Date struct or ISO string.
  • range_end - Range end date (only used in mode="range").
  • mode - Selection mode: single or range. Defaults to single.
  • disabled_dates - List of Date structs or ISO strings to disable.
  • week_start - First weekday, where 0 is Sunday and 6 is Saturday. Defaults to 0.
  • select_event - LiveView event emitted on date click with phx-value-date.
  • nav_event - LiveView event emitted on prev/next with phx-value-year and phx-value-month.
  • class - Additional CSS classes.

Event Handling

The calendar emits two distinct events:

# Date selection — fires with the clicked date
def handle_event("select_date", %{"date" => date}, socket) do
  d = Date.from_iso8601!(date)
  {:noreply, assign(socket, selected: d, year: d.year, month: d.month)}
end

# Month navigation — fires with the new year/month
def handle_event("nav_month", %{"year" => year, "month" => month}, socket) do
  {:noreply, assign(socket, year: String.to_integer(year), month: String.to_integer(month))}
end

Accessibility

  • Uses role="grid" with role="row" and role="gridcell" for the calendar grid.
  • Each day is a <button> — natively keyboard-focusable and operable.
  • aria-selected marks the selected date.
  • aria-current="date" marks today.
  • Disabled dates use the native disabled attribute.
  • Navigation buttons have descriptive aria-labels.

Summary

Functions

calendar(assigns)

Attributes

  • year (:integer) - Displayed year. Defaults to selected year, then current year. Defaults to nil.
  • month (:integer) - Displayed month (1-12). Defaults to selected month, then current month. Defaults to nil.
  • selected (:any) - Selected Date struct or ISO string. Defaults to nil.
  • range_end (:any) - Range end Date struct or ISO string. Defaults to nil.
  • mode (:string) - Selection mode. Defaults to "single". Must be one of "single", or "range".
  • disabled_dates (:list) - List of disabled Date structs or ISO strings. Defaults to [].
  • week_start (:integer) - First weekday: 0 = Sunday, 1 = Monday, ... 6 = Saturday. Defaults to 0. Must be one of 0, 1, 2, 3, 4, 5, or 6.
  • select_event (:string) - LiveView event emitted on date click with phx-value-date. Defaults to nil.
  • nav_event (:string) - LiveView event emitted on prev/next with phx-value-year and phx-value-month. Falls back to select_event. Defaults to nil.
  • class (:any) - Additional CSS classes. Defaults to nil.
  • id (:string) - DOM id for the calendar root. Defaults to nil.
  • Global attributes are accepted. Additional HTML attributes. Supports all globals plus: ["aria-label"].