datetime_slots
Tappable availability, grouped by day.
Times you can actually have. datetime_slots renders up to 24 availability slots as chips, grouped by calendar day whenever the model supplies timestamps.
Grouping is not decoration. A flat run of "09:00 11:30 09:30 13:00" spanning two dates is a booking mistake waiting to happen, so the block refuses to render one.
Re-rendered in the browser from the SDK’s own scales. Not a screenshot.
Rendered natively by the Flutter SDK and the Web SDK, both since 0.1.0.
When not to use it
Do not use it to ask for a date months out, because twenty-four chips will not cover it. A form with a date field is the right shape when availability is not the constraint.
Do not use it to confirm the booking either. Once a slot is chosen, the summary of what was booked is booking_card.
Props
Every block also carries type and a required fallback_text of 1 to 300 characters.
| Prop | Type | Required | Constraints |
|---|---|---|---|
title | string | No | Up to 120 characters. |
slots | array | Yes | 1 to 24 entries. |
slots[].id | string | Yes | 1 to 64 characters. Used to mark the chosen slot. |
slots[].label | string | Yes | 1 to 60 characters. Usually a clock time. |
slots[].starts_at | string | No | ISO 8601 in UTC (...Z); a numeric offset fails validation. Supply it and the slots group by day, in the device's local timezone. |
slots[].action | action | No | { kind: "reply", text } or { kind: "open_url", url }. See Actions. Omit it and the slot is shown but not tappable. |
On the wire
{
"id": "blk_12",
"type": "datetime_slots",
"fallback_text": "Five fitting slots across 2 and 3 September.",
"props": {
"title": "Fitting at Neon Kicks Amsterdam",
"slots": [
{
"id": "s1",
"label": "10:00",
"starts_at": "2026-09-02T10:00:00Z",
"action": {
"kind": "reply",
"text": "Book the 10:00 fitting on 2 September"
}
},
{
"id": "s2",
"label": "11:30",
"starts_at": "2026-09-02T11:30:00Z",
"action": {
"kind": "reply",
"text": "Book the 11:30 fitting on 2 September"
}
},
{
"id": "s4",
"label": "09:30",
"starts_at": "2026-09-03T09:30:00Z",
"action": {
"kind": "reply",
"text": "Book the 09:30 fitting on 3 September"
}
}
]
}
}Interaction
A tap fires the slot's action. The slot is marked as chosen once the send has actually gone out, so scrolling back through the thread shows which time was picked; a tap dropped because the previous turn was still open leaves the row unchanged rather than claiming a choice that was never sent. Legal kinds are reply and open_url. Both execute: open_url opens the page in an in-app browser, or goes to your RendelConfig.onOpenUrl when you set one. https only.
Labels render with tabular figures, so a row of clock times does not re-flow between renders.
States
| State | What the SDK draws |
|---|---|
| Chosen | The tapped chip fills with the accent and keeps a near-black label. The fill transitions rather than snapping. |
| No timestamps | The slots render as one flat group with no day heading. The block does not invent a grouping it was not given. |
| Empty | An empty slots array renders fallback_text inside the plate. |
| Loading | A title bar and four pill placeholders at 44pt. |
Accessibility
Day headings are read before the chips beneath them, so a screen-reader user hears "Wed 2 Sep, 10:00" in order rather than a bare time. A chosen chip announces "10:00, selected".
fallback_text should say how many slots there are and which days they span.