Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Calendar App Sidebar Block for React

A calendar app in a fixed-height window: a Day, Week, Month and Year toggle, five calendars with checkboxes and pattern swatches that hide their events, four filtering tags and a New event button.

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

Give a calendar app its whole shell with this calendar app sidebar for React with Base UI. A window framed by a hairline with a plus mark on each corner holds the Sidebar: the product's mark, a View Toggle Group (Day, Week, Month and Year), five calendars (Personal, Work, Holidays, Birthdays and Reminders), each with a Checkbox and a swatch told apart by pattern (solid, hatched, dotted, outlined and double) rather than by color, four tags, and the signed-in person at the foot. Beside it, a top bar names what the grid shows and holds New event, a Shine Button and the only colored control. Untick a calendar and its events leave the grid at once; pick a view and the grid redraws as a day's list, a week of seven columns, a month of cells or a year of twelve; Previous, Next and Today move through time from a fixed date, and a tag filters what's shown. Hiding every calendar or filtering to nothing shows an Empty state with a way back, and the status line says the result. The rail collapses to the checkboxes and tag icons with tooltips, and below the medium breakpoint it becomes a sheet. It's built from Sidebar, Toggle Group, Checkbox, Empty, Avatar, Button, Shine Button and Guides, with a CSS entrance only. For calendars, planners, booking tools and any app whose sidebar chooses what the page shows.

FAQ

Why are the calendars told apart by pattern and not by color?

So they stay readable on every theme, in grayscale and for people who can't tell hues apart. Each calendar has a look (solid, hatched, dotted, outlined or double) drawn in CSS from the theme's foreground, and its name is always written beside the swatch and spoken after each event's title. If you want hues, change the swatchClass function and keep the name; the grid never relies on the swatch alone.

How does unticking a calendar work?

The checkboxes hold a list of hidden calendars in the block's state. Every grid, count and status line is worked out from the typed EVENTS list minus the hidden calendars and the chosen tag, so the numbers beside each calendar, the count above the grid and the sentence in the status line always agree. Untick all five and the grid shows an Empty state with a Show all calendars button. In your app, keep the same shape: one list of events, one list of visible calendars, and derive everything else.

What stays in the page, and how do I connect it?

Everything. The events are typed at the top of the file, the "now" every date is measured from is a constant (14 October 2026, so the demo looks the same whenever it loads), and New event adds an untitled event to Personal on the open day in the block's own state. Nothing is saved, synced or sent, and reloading starts over. Replace the handlers with your API and read the events for the visible range from your server. The tags are links to # whose handler toggles the filter. They're SidebarMenuButtons with render set to an a element.

How does it work on a phone?

Below the medium breakpoint the sidebar becomes a sheet that the menu button in the top bar opens from the start edge, the right in a right-to-left layout. Escape closes it and focus goes back to the menu button. The calendars and the view live in the sheet, so the status line at the foot of the window states the live result ("Week of 12 Oct: 14 events, 5 of 5 calendars."). The week and the month keep their seven columns inside a scrollable region you can reach with Tab, so the page never scrolls sideways.

What happens when the sidebar collapses?

The menu button or the rail along the sidebar's edge folds it to icons. The View toggle gives way, because it has no folded form, while each calendar keeps its checkbox, named for screen readers, and each tag keeps its icon with a tooltip. The provider is set with persist={false} and shortcut={false}, so the block writes no cookie and leaves Ctrl and Command with B to the page it sits on.

Is it accessible?

The sidebar is a navigation landmark named after the product, with each group named by its label. Every checkbox is named by its calendar, the toggle group is named View, and a tag that is on is marked as current and says so in its name. The grids are lists of days with lists of events, in a labelled scrollable region reachable with Tab, and each event's calendar is spoken after its title. One polite status line reports each change, and times and dates are isolated so they read right in a right-to-left layout.