PhiaUi.Components.MultiSelectCalendar (phia_ui v0.1.17)

Copy Markdown View Source

A full-month calendar grid where multiple individual (non-contiguous) dates can be toggled on/off.

Selected dates are rendered as individual filled rounded rectangles using bg-primary/20 text-primary font-semibold. This is distinct from RangeCalendar, which selects a contiguous band of dates.

The grid is SUN-first (Sun Mon Tue Wed Thu Fri Sat). Adjacent-month days are rendered faded (opacity-40) to fill the first and last rows.

Month and year navigation is provided through navigation buttons (on_prev, on_next) and/or <select> dropdowns (on_month_change, on_year_change). State (current month/year, selected dates) lives entirely in the parent LiveView.

Example

<.multi_select_calendar
  year={@year}
  month={@month}
  selected_dates={@selected_dates}
  on_select="toggle_date"
  on_prev="prev_month"
  on_next="next_month"
  on_month_change="month_changed"
  on_year_change="year_changed"
/>

LiveView event handlers

def handle_event("toggle_date", %{"date" => iso}, socket) do
  date = Date.from_iso8601!(iso)
  selected =
    if date in socket.assigns.selected_dates do
      List.delete(socket.assigns.selected_dates, date)
    else
      [date | socket.assigns.selected_dates]
    end
  {:noreply, assign(socket, selected_dates: selected)}
end

def handle_event("prev_month", _params, socket) do
  {y, m} = prev_ym(socket.assigns.year, socket.assigns.month)
  {:noreply, assign(socket, year: y, month: m)}
end

def handle_event("next_month", _params, socket) do
  {y, m} = next_ym(socket.assigns.year, socket.assigns.month)
  {:noreply, assign(socket, year: y, month: m)}
end

def handle_event("month_changed", %{"month" => m}, socket) do
  {:noreply, assign(socket, month: String.to_integer(m))}
end

def handle_event("year_changed", %{"year" => y}, socket) do
  {:noreply, assign(socket, year: String.to_integer(y))}
end

Zero JavaScript

This component is entirely server-rendered. No JS hook is required.

Summary

Functions

Renders a single-month calendar grid supporting multiple individual date selections.

Functions

multi_select_calendar(assigns)

Renders a single-month calendar grid supporting multiple individual date selections.

All geometry (leading/trailing days, per-cell selection state) is computed server-side before the template renders.

Attributes

  • year (:integer) (required) - 4-digit year of the displayed month.

  • month (:integer) (required) - Month number (1–12).

  • selected_dates (:list) - List of Date.t() values that are currently selected. Defaults to [].

  • on_select (:string) - phx-click event name fired when any current-month day is clicked. The LiveView receives %{"date" => "YYYY-MM-DD"}. Clicking a selected date again is intended to deselect it — the toggle logic lives in the parent.

    Defaults to nil.

  • on_prev (:string) - phx-click event name for the previous-month navigation button. Defaults to nil.

  • on_next (:string) - phx-click event name for the next-month navigation button. Defaults to nil.

  • on_month_change (:string) - phx-change event name for the month <select> dropdown. Defaults to nil.

  • on_year_change (:string) - phx-change event name for the year <select> dropdown. Defaults to nil.

  • min_year (:integer) - Earliest year shown in the year <select> dropdown. Defaults to 2000.

  • max_year (:integer) - Latest year shown in the year <select> dropdown. Defaults to 2040.

  • class (:string) - Additional CSS classes merged onto the root element. Defaults to nil.

  • Global attributes are accepted. HTML attributes forwarded to the root <div>.