Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Booking Slot Grid Table Block for React Aria

A court booking grid in a fixed window, Monday to Friday by nine hourly slots: free slots are named Book buttons, one booking at a time shows as Yours, and the foot band cancels it.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let people book one slot, with this booking slot grid for React with React Aria. A fixed-height window holds a top bar with the club and the court, and a native table of hairline cells: Monday to Friday of one week across, nine hourly slots from 08:00 down. A free slot is a "Book" Button named for its day and time ("Book Tue 10:00"); a booked slot says "Booked" in text and a closed one is dashed and read as "Unavailable", and neither can take focus, so Tab visits only the open slots. You hold one booking at a time: pressing another slot moves it, the cell reads "Yours" in solid foreground, and the foot band names it ("You have Tue 10:00, Court 2") beside a Cancel that frees the slot and puts focus back on it, over a four-item legend. Below the medium breakpoint a ToggleGroup chooses the day and the table shows one day beside the time column. For courts, meeting rooms, appointments and anything that is booked from a grid.

FAQ

How do I change the days, the hours and who has booked what?

Edit DAYS and HOURS. Each day carries a string with one letter per slot: o for open, b for booked by someone else, x for closed. The cell state is worked out by cellOf from that string and from your own booking, so "Yours" is never stored twice. The free count in the top bar and the legend come from the same helpers. To change the number of slots, change HOURS and make each day's string that long.

What stays local, and how do I wire it to a real booking system?

The booking is one useState value and nothing is reserved or paid for; the status line says so. To make it real, send the day and slot to your API in book, mark the cell pending while it runs, and treat a rejection (someone else got there first) by setting that slot to booked and saying so in the status line. Cancel is the same in reverse. Because the grid is read from one string per day, a fresh response from the server can replace it without touching the markup.

Why only one booking at a time?

It keeps the interaction honest and the foot band simple: the booking you hold is always named in one place, and booking a second slot moves the first instead of silently holding two. If your product allows several, keep a list instead of one value, show each in the foot band or a list, and let Cancel act on the focused one. The grid code does not change.

Is a grid of buttons accessible?

Yes. It is a native table with a caption, column heads that read the full day name ("Tuesday 13") and row heads for the hours. Only open slots are buttons, each with a name that includes the day and time, so a screen reader hears "Book Tue 10:00" and the keyboard visits exactly the choices there are. Your slot is read as "Yours, Tue 10:00, Court 2". One polite status line reports every booking and cancellation, and focus moves to your slot when you book and back to the freed slot when you cancel.

How does it look on a phone?

The table shows the time column and one day. Five day buttons above it choose which one, in the same solid-foreground style as a pressed button elsewhere, and a booking made on one day is still in the foot band when you switch to another. The window keeps its height, the rows scroll inside it if they do not fit, and the foot stays in view.

Does the window change size when I book or cancel?

No. A cell holds a button, a word or a dashed box of the same height, the rows are fixed, and the foot band reserves two lines for its sentence. The window has a set height on every screen and the grid scrolls inside it if a different theme makes it taller.