A full-month calendar grid with range selection visualised as a continuous band.
Range visualisation:
- range_start: blue filled circle on the number + right-half band background connecting to the middle days.
- range_middle: full-width band background.
- range_end: blue filled circle on the number + left-half band background connecting from the middle days.
- single (start == end): blue filled circle only — no band.
State (current month, range boundaries) lives entirely in the parent
LiveView. Day clicks and month navigation fire phx-click events.
Example
<.range_calendar
year={@year}
month={@month}
range_start={@from}
range_end={@to}
on_select="pick_date"
on_prev="prev_month"
on_next="next_month"
/>LiveView event handlers
def handle_event("pick_date", %{"date" => iso}, socket) do
date = Date.from_iso8601!(iso)
# two-click range protocol
socket =
cond do
is_nil(socket.assigns.from) ->
assign(socket, from: date, to: nil)
is_nil(socket.assigns.to) and Date.compare(date, socket.assigns.from) != :lt ->
assign(socket, to: date)
true ->
assign(socket, from: date, to: nil)
end
{:noreply, socket}
end
def handle_event("prev_month", _params, socket) do
{:noreply, assign(socket, month: prev_month(socket.assigns.month, socket.assigns.year))}
endZero JavaScript
This component is entirely server-rendered. No JS hook is required.
Summary
Functions
Renders a single-month calendar grid with range-selection band visualisation.
Functions
Renders a single-month calendar grid with range-selection band visualisation.
All geometry (leading/trailing days, per-cell range state) is computed server-side before the template renders. The HEEx template is purely declarative — no inline logic.
Attributes
year(:integer) (required) - 4-digit year of the displayed month.month(:integer) (required) - Month number (1–12).range_start(:any) - Range selection startDate.t()(ornilfor no selection). Defaults tonil.range_end(:any) - Range selection endDate.t()(ornilfor open range). Defaults tonil.on_select(:string) -phx-clickevent name fired when a current-month day is clicked. The LiveView receives%{"date" => "YYYY-MM-DD"}.Defaults to
nil.on_prev(:string) -phx-clickevent name for the previous-month navigation button. Defaults tonil.on_next(:string) -phx-clickevent name for the next-month navigation button. Defaults tonil.class(:string) - Additional CSS classes merged onto the root element. Defaults tonil.Global attributes are accepted. HTML attributes forwarded to the root
<div>.