Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Monthly View Calendar Block for React

A month as a table with event pills in each day, a panel listing the chosen day's events, paging between September and December and a Today button, all worked out from a fixed 14 October 2026.

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 household or a small team one month to plan from, with this monthly calendar for React with Base UI. A hairline frame with a plus mark on each corner holds a table of seven columns, Monday first, whose large cells carry up to two event pills each: a small mark in the category's shape and the event's title, then "+2 more" when there are more. Choosing a day, with a click or the arrow keys, Home, End, Page Up and Page Down, lists its events in the panel at the end of the frame with their time, place, mark and category word, and a polite status line says the same ("Thu 15 Oct: 3 events"). Previous and next Buttons page between September and December 2026, and Today returns to 14 October with a ring on the day number. A day with nothing on shows an Empty state at the same height, with a link to the next day that has something. Categories are never colors: each is a shape (a dot, a ring, a diamond, a bar, a hatched square) with its word in a legend, and the Badge marks the day that is today. The bands are ruled by Guides. Below the small breakpoint the cells keep marks only and the day panel sits under the month. It's built from Button, Empty, Badge and Guides, with a CSS entrance only. For planners, team calendars and any app that needs a month with events in it.

FAQ

How do I fill it with my events?

Edit EVENTS. Each has an ISO date, a wall-clock start such as 09:30 (empty for an all-day event), a title, a place and a mark of solid, ring, diamond, bar or hatch; KINDS gives each mark its word. List events in time order within a day. The counts, the pills and the day panel are all worked out from that array. Change FIRST_MONTH and LAST_MONTH to set how far the arrows can page.

Why is today always 14 October?

Nothing in the block reads the clock. AS_OF is the one moment the block treats as now, and the Today ring, the Today button and the badge all come from it, so the block looks the same on any day and in a screenshot. To follow the real date, set AS_OF from your own clock or server and keep the rest as it is.

How do I move around with the keyboard?

The month is one tab stop. The arrow keys move a day or a week, Home and End go to the start and end of the week, Page Up and Page Down turn to the previous or next month, and Enter or Space chooses the day. Each day is a button named with its full date, whether it is today and how many events it has ("Thursday 15 October, 3 events"), and the grid keeps its left-to-right order in right-to-left languages.

Why are the categories shapes and not colors?

A color alone can't be told apart by everyone, and it can't print or survive a grayscale screenshot. Each category here has its own shape and pattern, and the legend always shows the shape next to the word. The day panel repeats the word for every event.

What stays local, and how do I wire it up?

Everything. Choosing days and paging only change state in the page, and nothing is saved or sent. To make it real, load events for the visible month from your own API when month changes, and keep the rest of the component as it is; the cells and the panel read from whatever array you give them.

How does it look on a phone?

Each cell shrinks to a day number and up to three marks, with the exact event count in the button's name. The legend and the day panel stack under the month, and the panel keeps the same height whether the day has events or not.