shadcn.io is not affiliated with official shadcn/ui
Date Range Form Block for Svelte
Two date inputs and a month that stay one range: booked nights drawn struck through and named when a block runs over one, an end before the start refused on the end field, and a two-night minimum.
Installation
Overview
Block a run of nights with this date range form for Svelte with Ark UI. A compact header sits over a hairline frame with a plus mark on each corner, in two cells. The first holds two Date Inputs, Start and End, and a summary ("5 nights, Fri 6 Nov to Wed 11 Nov"); the second is a month to pick from, drawn as a grid of buttons with a plus mark where it meets the first cell. The inputs and the month are one range: typing a date moves the highlight, and picking two days fills the inputs. Four nights are booked and drawn struck through; a range can't start on one, and one that runs over one says "Includes 14 Nov, which is booked" under the End field. The End is the morning the place opens again, so an End before the Start is refused on the End, and a block is at least two nights. It's built from Date Input, Button, Shine Button and Guides, with a CSS entrance only. For holiday lets, room blocks, leave and any form that takes a start and an end with rules between them.
FAQ
How do I change the booked nights, the minimum and the months?
Edit the constants at the top: BOOKED (ISO days), MIN_NIGHTS, MONTH_IDS (the months the grid can show) and AS_OF (the day the block treats as now, which closes the nights before it). startProblem and endProblem are the rules and return one sentence each; the fields, the summary and the Block dates check all read them, so a new rule is one more line there.
Why is the End a morning and not a night?
A booking is nights, and the last night is the one before the day you leave. So Fri 6 Nov to Wed 11 Nov is five nights (6, 7, 8, 9 and 10), and a booked night on the 11th does not block it. The month names this in words for a screen reader ("first night" on the Start, "the morning it opens again" on the End), and the check that finds a booked night looks at the nights only.
How do the inputs and the month stay in step?
There is one range, kept as two ISO days. The inputs report a date once all three segments are filled; a day picked on the month is written back into them through a small child component inside each input (DateBridge). The first pick starts a range, the second ends it, and picking a day on or before the Start starts again. The month is a grid of buttons and takes the arrow keys, one tab stop, and Enter or Space to pick.
When does it check, and where do the messages go?
When focus leaves the two fields, when you pick on the month and when you press Block dates, which also moves focus to the first field with a problem. A Start problem is under the Start, and everything about the End (before the Start, too short, over a booked night) is under the End, so each message sits next to the field you fix.
What stays local, and how do I connect it for real?
Nothing is blocked: Block dates says "5 nights blocked here only. Nothing was sent." To make it real, send the two ISO days from the submit handler, check the booked nights on your server too, and show its answer in the same status line. Feed BOOKED from your calendar rather than a constant.