Calendar
Always-visible calendar grid for single dates, multiple dates, or ranges, at day, month, or year granularity.
Basic
With label and help text
Pick the day you would like to come in.
Pre-selected value
Multiple selection
Add multiple to select more than one date. Each pick renders its own hidden input, so name should end in [].
Range selection
Use calendar_range to pick a start and end date. The endpoints render with a connecting band across the days in between.
Min and max bounds
Disabled dates
disabled_dates takes a mixed list of specific dates and recurring patterns: :weekends, {:weekday, n}, {:month_day, m, d}, and Date.Range values.
Required selection
allow_deselect={false} keeps at least one date selected; clicking the active day no longer clears it.
Month granularity
Year granularity
Extended navigation
Select navigation
navigation="select" swaps the header arrows for month and year dropdowns, so jumping across many months takes one click.
Localized
Static
static renders a read-only grid with no header, no hidden inputs, and no JS hook. Selected dates stay highlighted and every cell is unfocusable.
See you on the highlighted date.
Form integration with validation
Pass a Phoenix.HTML.FormField via field to derive name, value, and errors automatically. Server-side validation rules surface as inline errors below the calendar.
Changes: %{}
Server-driven updates
Update value from the server and the calendar re-syncs its selection without a full re-render. The grid uses phx-update="ignore"; the hidden input value bridges patches into the JS hook.
Dynamic constraints
Push new min and max bounds from the server. The calendar's mutation observer picks up the change and updates which days are selectable and which navigation arrows are enabled.
Server-fetched event markers
Fetch event markers from the server every time the user navigates to a new month. A small hook bridges the calendar's navigate event into a LiveView handler, a backdrop overlay covers the calendar while the request is in flight, and a dot is painted under each returned date.
Birth date picker
Combine navigation="select" with max={Date.utc_today()} to jump across years quickly while blocking any future date.
Time off request
A date range constrained to upcoming weekdays via min and disabled_dates={[:weekends]}, with navigation="extended" adding year arrows to the header.
Working days only.