Meeting Scheduler
Day strip, slot grid and a time zone the visitor can change — because a slot list with no zone on it is how this pattern wastes an hour of everyone involved.
A month view where event chips truncate and overflow becomes "+n more", so a busy Tuesday never changes the height of the row it sits in.
components/calendar-month.tsxnpx hoverlab add calendar-month
Or over MCP, from your editor's agent — no account needed.
Free to read, copy and install, for personal and non-commercial projects. Shipping it in client work or a paid product needs Pro ($79 once). The source lands in your repo and stops being ours — no attribution, nothing to upgrade.
Start a page with this section — add more, order them, and leave with the page source.
Rendered live in your current theme — this is the same component whose source is below, not a screenshot of it.
/**
* <CalendarMonth> — a month grid for August 2026.
*
* A month view's job is density without noise. Event chips truncate to a
* single line and never wrap, so every week keeps the same row height;
* when a day holds more than the cell can carry, the overflow collapses
* to "+2 more" instead of stretching one row and knocking the whole
* month out of rhythm. Out-of-month days render muted but present —
* hiding them would break the weekday columns. Colour marks which
* calendar an event belongs to, and the legend above the grid states
* that mapping instead of leaving it to be guessed.
*/
import * as React from 'react'
import { ChevronLeft, ChevronRight } from 'lucide-react'
export type CalendarId = 'product' | 'design' | 'personal'
export interface CalendarEvent {
label: string
calendar: CalendarId
}
export interface CalendarMonthProps {
/** Events keyed by ISO date (YYYY-MM-DD). */
events?: Record<string, CalendarEvent[]>
className?: string
}
const CAL_STYLE: Record<CalendarId, { label: string; chip: string; dot: string }> = {
product: { label: 'Product', chip: 'bg-primary/15 text-primary', dot: 'bg-primary' },
design: { label: 'Design', chip: 'bg-sky-500/15 text-sky-500', dot: 'bg-sky-500' },
personal: { label: 'Personal', chip: 'bg-emerald-500/15 text-emerald-500', dot: 'bg-emerald-500' },
}
const DEFAULT_EVENTS: Record<string, CalendarEvent[]> = {
'2026-08-03': [{ label: 'Sprint 42 kickoff', calendar: 'product' }],
'2026-08-06': [{ label: 'Design crit', calendar: 'design' }],
'2026-08-13': [{ label: 'v3.1 release', calendar: 'product' }],
'2026-08-17': [{ label: 'Flight to Lisbon', calendar: 'personal' }],
'2026-08-20': [
{ label: 'Roadmap review', calendar: 'product' },
{ label: 'Portfolio review', calendar: 'design' },
{ label: 'Dentist, 15:30', calendar: 'personal' },
{ label: '1:1 with Sam', calendar: 'product' },
],
'2026-08-27': [{ label: 'Q3 planning', calendar: 'product' }],
}
const WEEKDAYS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
const MONTHS = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December',
]
const TODAY_ISO = '2026-08-13'
/** Monday before Aug 1, 2026 (a Saturday) — the grid's first cell. */
const FIRST_CELL_UTC = Date.UTC(2026, 6, 27)
const MAX_CHIPS = 2
interface DayCell {
iso: string
day: number
monthName: string
inMonth: boolean
}
function buildWeeks(): DayCell[][] {
const cells: DayCell[] = Array.from({ length: 42 }, (_, i) => {
const date = new Date(FIRST_CELL_UTC + i * 86_400_000)
return {
iso: date.toISOString().slice(0, 10),
day: date.getUTCDate(),
monthName: MONTHS[date.getUTCMonth()],
inMonth: date.getUTCMonth() === 7,
}
})
return Array.from({ length: 6 }, (_, w) => cells.slice(w * 7, w * 7 + 7))
}
const WEEKS = buildWeeks()
export function CalendarMonth({ events = DEFAULT_EVENTS, className = '' }: CalendarMonthProps) {
return (
<section className={`w-full ${className}`}>
<div className="mb-4 flex flex-wrap items-center gap-3">
<h2 className="text-lg font-bold tracking-tight">August 2026</h2>
<ul className="flex items-center gap-3 text-xs text-muted-foreground sm:ms-4">
{(Object.keys(CAL_STYLE) as CalendarId[]).map((id) => (
<li key={id} className="flex items-center gap-1.5">
<span aria-hidden className={`h-2 w-2 rounded-full border border-transparent ${CAL_STYLE[id].dot}`} />
{CAL_STYLE[id].label}
</li>
))}
</ul>
<div className="ms-auto flex items-center gap-1">
<button
type="button"
aria-label="Previous month"
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border/60 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
<ChevronLeft aria-hidden className="h-4 w-4 rtl:rotate-180" />
</button>
<button
type="button"
aria-label="Next month"
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border/60 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
<ChevronRight aria-hidden className="h-4 w-4 rtl:rotate-180" />
</button>
<button
type="button"
className="ms-1 rounded-lg border border-border/60 px-3 py-1.5 text-sm font-medium transition-colors hover:bg-muted"
>
Today
</button>
</div>
</div>
<div
role="grid"
aria-label="August 2026"
className="overflow-hidden rounded-xl border border-border/60"
>
<div role="row" className="grid grid-cols-7 gap-px bg-border/60">
{WEEKDAYS.map((weekday) => (
<span
key={weekday}
role="columnheader"
className="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground"
>
{weekday}
</span>
))}
</div>
{WEEKS.map((week) => (
<div key={week[0].iso} role="row" className="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
{week.map((cell) => {
const dayEvents = events[cell.iso] ?? []
const overflow = dayEvents.length - MAX_CHIPS
const isToday = cell.iso === TODAY_ISO
return (
<div key={cell.iso} role="gridcell" className={cell.inMonth ? 'bg-card' : 'bg-muted/30'}>
<button
type="button"
aria-label={`${cell.day} ${cell.monthName} 2026${
dayEvents.length ? `, ${dayEvents.length} event${dayEvents.length > 1 ? 's' : ''}` : ''
}`}
aria-current={isToday ? 'date' : undefined}
className="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50"
>
<span
className={`inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs ${
isToday
? 'font-bold ring-2 ring-primary'
: cell.inMonth
? 'font-medium'
: 'text-muted-foreground/85'
}`}
>
{cell.day}
</span>
{dayEvents.slice(0, MAX_CHIPS).map((event) => (
<span
key={event.label}
className={`block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium ${CAL_STYLE[event.calendar].chip}`}
>
{event.label}
</span>
))}
{overflow > 0 ? (
<span className="px-1.5 text-[0.65rem] font-medium text-muted-foreground">
+{overflow} more
</span>
) : null}
</button>
</div>
)
})}
</div>
))}
</div>
</section>
)
}
bg-card, text-muted-foreground) — it inherits your theme instead of overriding it.Drop it at components/calendar-month.tsx and import it where you need the section:
import { CalendarMonth } from '@/components/calendar-month'Read out of the component’s own type and signature, so this cannot drift from the source below. Every prop has a default — the component renders standalone before you pass it anything.
| Prop | Type | Default |
|---|---|---|
eventsEvents keyed by ISO date (YYYY-MM-DD). | Record<string, CalendarEvent[]> | DEFAULT_EVENTS, className = '' |
className | string | — |
The same block rendered once to markup, wrapped as a file your framework compiles. Tailwind classes are framework-agnostic, so the design transfers intact — the behaviour does not.
<!--
Month Calendar Grid — markup from the Hoverlab catalog.
This is the block rendered once to HTML and wrapped as a component
file. It is not a port of the React source: the Tailwind classes carry
the design, which is the part that took the work, and they are the same
in every framework.
This block has no interactive behaviour, so nothing is missing.
-->
<section class="w-full ">
<div class="mb-4 flex flex-wrap items-center gap-3">
<h2 class="text-lg font-bold tracking-tight">August 2026</h2>
<ul class="flex items-center gap-3 text-xs text-muted-foreground sm:ms-4">
<li class="flex items-center gap-1.5"><span aria-hidden="true" class="h-2 w-2 rounded-full border border-transparent bg-primary"></span>Product</li>
<li class="flex items-center gap-1.5"><span aria-hidden="true" class="h-2 w-2 rounded-full border border-transparent bg-sky-500"></span>Design</li>
<li class="flex items-center gap-1.5"><span aria-hidden="true" class="h-2 w-2 rounded-full border border-transparent bg-emerald-500"></span>Personal</li>
</ul>
<div class="ms-auto flex items-center gap-1">
<button type="button" aria-label="Previous month" class="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border/60 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-left h-4 w-4 rtl:rotate-180" aria-hidden="true">
<path d="m15 18-6-6 6-6"></path>
</svg>
</button>
<button type="button" aria-label="Next month" class="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-border/60 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right h-4 w-4 rtl:rotate-180" aria-hidden="true">
<path d="m9 18 6-6-6-6"></path>
</svg>
</button>
<button type="button" class="ms-1 rounded-lg border border-border/60 px-3 py-1.5 text-sm font-medium transition-colors hover:bg-muted">Today</button>
</div>
</div>
<div role="grid" aria-label="August 2026" class="overflow-hidden rounded-xl border border-border/60">
<div role="row" class="grid grid-cols-7 gap-px bg-border/60">
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Mon</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Tue</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Wed</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Thu</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Fri</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Sat</span>
<span role="columnheader" class="min-w-0 truncate bg-muted/60 px-2 py-2 text-center text-xs font-semibold text-muted-foreground">Sun</span>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="27 July 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">27</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="28 July 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">28</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="29 July 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">29</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="30 July 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">30</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="31 July 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">31</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="1 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">1</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="2 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">2</span>
</button>
</div>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-card">
<button type="button" aria-label="3 August 2026, 1 event" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">3</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-primary/15 text-primary">Sprint 42 kickoff</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="4 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">4</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="5 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">5</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="6 August 2026, 1 event" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">6</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-sky-500/15 text-sky-500">Design crit</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="7 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">7</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="8 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">8</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="9 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">9</span>
</button>
</div>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-card">
<button type="button" aria-label="10 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">10</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="11 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">11</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="12 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">12</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="13 August 2026, 1 event" aria-current="date" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-bold ring-2 ring-primary">13</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-primary/15 text-primary">v3.1 release</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="14 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">14</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="15 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">15</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="16 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">16</span>
</button>
</div>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-card">
<button type="button" aria-label="17 August 2026, 1 event" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">17</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-emerald-500/15 text-emerald-500">Flight to Lisbon</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="18 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">18</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="19 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">19</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="20 August 2026, 4 events" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">20</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-primary/15 text-primary">Roadmap review</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-sky-500/15 text-sky-500">Portfolio review</span>
<span class="px-1.5 text-[0.65rem] font-medium text-muted-foreground">+2 more</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="21 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">21</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="22 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">22</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="23 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">23</span>
</button>
</div>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-card">
<button type="button" aria-label="24 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">24</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="25 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">25</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="26 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">26</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="27 August 2026, 1 event" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">27</span>
<span class="block truncate rounded px-1.5 py-0.5 text-[0.65rem] font-medium bg-primary/15 text-primary">Q3 planning</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="28 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">28</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="29 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">29</span>
</button>
</div>
<div role="gridcell" class="bg-card">
<button type="button" aria-label="30 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">30</span>
</button>
</div>
</div>
<div role="row" class="grid grid-cols-7 gap-px border-t border-border/60 bg-border/60">
<div role="gridcell" class="bg-card">
<button type="button" aria-label="31 August 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs font-medium">31</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="1 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">1</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="2 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">2</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="3 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">3</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="4 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">4</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="5 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">5</span>
</button>
</div>
<div role="gridcell" class="bg-muted/30">
<button type="button" aria-label="6 September 2026" class="flex min-h-[5.25rem] w-full flex-col items-stretch gap-1 p-1.5 text-start transition-colors hover:bg-muted/50">
<span class="inline-flex h-6 w-6 items-center justify-center self-start rounded-full text-xs text-muted-foreground/85">6</span>
</button>
</div>
</div>
</div>
</section>
What each framework gets across the whole catalog — effects convert properly; this rung is markup.
The component, its props, the design tokens it expects and the command that installs it — as one prompt. Paste it into Claude, Cursor, v0 or ChatGPT and what they build around it will match the rest of the catalog instead of inventing its own system.
Want the whole screen instead of this one section? Open a page and copy it entire.
All of them free to read, copy and install — no account, no locked tiles, no watermarked preview. The whole catalog is open, and so are the API and the CLI.
Browse Scheduling & CalendarCopying the code is free. Putting it in client work or a paid product is what Pro is for — the licence, not the access.
Day strip, slot grid and a time zone the visitor can change — because a slot list with no zone on it is how this pattern wastes an hour of everyone involved.
Time down the side, tracks across, breaks spanning the width — the one comparison a month view cannot make. Falls to a linear list on a phone, from the same array.