Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Meeting Schedule Dashboard Block for React

A day on a time axis from 08:00 to 18:00 with nine meetings placed by start and length, overlaps side by side marked Conflict, a now line, and a meeting-length select that marks and lists the free slots.

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

See where a day's meetings collide and where there is room, with this meeting schedule panel for React with Base UI. A hairline frame with a plus mark on each corner draws Monday 19 Oct 2026 on Agendawell as a vertical axis from 08:00 to 18:00. Nine meetings sit at their start and length; those that overlap stand side by side in columns and say "Conflict" with how many are in the clash, and a line marks now at a typed 11:15. A Native Select in the header sets the meeting length to 15, 30 or 60 minutes, and the free slots from now to the end of the day are marked on the axis with dashed boxes and listed in the side cell. Pressing a meeting opens it in the side cell with its time, place and who is invited as Avatar initials, and a Button to join that does nothing in this demo and says so. It's built from Native Select, Button, Avatar, Badge and Guides. For calendars and scheduling tools.

FAQ

How do I fill it with my calendar?

Edit MEETINGS: each is made with meeting(id, title, start, length, place, attendees), where the start is minutes after midnight (at(9, 30) is 09:30) and the length is in minutes. OPEN, CLOSE and NOW set the working day and the now line, and HOUR is the height of an hour on the axis. The columns, the conflicts, the free slots and the header sentence are all worked out from the meetings.

How are conflicts found?

Two meetings conflict when one starts before the other ends. Meetings that overlap in a run are laid out in columns, each in the first column that is free when it starts, and each one shows how many meetings are in its clash. The header counts the runs with more than one meeting.

How are the free slots worked out?

Meetings are merged into busy runs, a meeting that ends as another starts counting as one run, and the gaps between them within the working day are the free time. A gap is clipped to start no earlier than now and kept only if it holds at least the length you chose, so switching from 30 to 60 minutes leaves fewer slots.

What does Join do?

Nothing in this demo: it says so in the status line. In your app, open the meeting's call link from the handler, or render the button as a link.

What stays local, and how do I wire it for real?

Everything: the day is typed, the now line is fixed at 11:15 and no calendar is read. To make it real, load the day's events from your calendar, set NOW from the clock after mount, and keep times in the viewer's time zone.

How does it look on a phone?

The axis stays vertical at the same height, the columns of a clash get narrower and the side cell stacks under the axis. Each meeting is a button named with its title, time and number of conflicts, so a narrow title is still readable in the side cell.