TimeSlotGrid component — a responsive grid of time-slot buttons for appointment booking.
Displays time slots as pill buttons arranged in a configurable column grid (2, 3, or 4 columns). Each slot may be in one of four states: default (available), selected, disabled (individual slot), or fully disabled (entire grid).
Zero JavaScript — state is managed by the LiveView.
States
| State | Description |
|---|---|
| available (default) | White bg, border, hover highlight |
| selected | Blue border (2 px), blue text, semibold |
| slot disabled | Muted bg, opacity-50, cursor-not-allowed |
| grid disabled | All slots muted, opacity-50, cursor-not-allowed |
Slot formats accepted
- Plain string:
"9:00 AM"— value and label both equal the string - Map with value only:
%{value: "9:00 AM"}— label defaults to value - Map with value + label:
%{value: "9:00AM", label: "9:00 AM"} - Full map:
%{value: "9:00AM", label: "9:00 AM", disabled: true}
Examples
<%!-- Basic usage --%>
<.time_slot_grid slots={~w(9:00AM 9:30AM 10:00AM)} />
<%!-- With selected slot and LiveView handler --%>
<.time_slot_grid
slots={@available_slots}
selected={@selected_time}
on_select="pick_slot"
/>
<%!-- 4-column grid, grid-level disabled --%>
<.time_slot_grid slots={@slots} cols={4} disabled={@loading} />
Summary
Functions
Renders a grid of time-slot pill buttons.
Functions
Renders a grid of time-slot pill buttons.
Examples
<.time_slot_grid slots={~w(3:00PM 3:30PM 4:00PM)} selected="3:30PM" on_select="pick" />Attributes
slots(:list) (required) - List of time slot strings or maps (%{value:, label:, disabled:}).selected(:string) - Value of the currently selected slot. Defaults tonil.on_select(:string) - phx-click event name fired when a slot is clicked. Defaults tonil.cols(:integer) - Number of grid columns — 2, 3, or 4 (defaults to 3). Defaults to3.disabled(:boolean) - Disables the entire grid — all slots become non-interactive. Defaults tofalse.class(:string) - Additional CSS classes merged via cn/1. Defaults tonil.- Global attributes are accepted. HTML attributes forwarded to the root wrapper element.