A split booking dashboard: a left panel with a top nav, functional tab bar, a Manage menu, a bento of revenue/occupancy/metric tiles and an image, toggleable active-booking cards, and a room-availability timeline; a right rail with a real month calendar (selectable days, booked-day dots) and a time-slotted day agenda.
A full-height booking dashboard for appointment and room-scheduling apps, split into a working left panel and a right rail. The left side pairs a bento of revenue, occupancy, and metric tiles with toggleable booking cards and a room-availability schedule timeline; the right rail carries a real month calendar with booked-day dots and a time-slotted day agenda. It is a drop-in appointment scheduling UI for any Next.js / React scheduling dashboard, built on shadcn/ui.
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/dashboard5?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/dashboard5?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/dashboard5.tsx, the two composed Beste components schedule-timeline and notifications-menu to components/beste/component/, and the shadcn/ui dependencies they need (button, badge, avatar, switch, calendar, dropdown-menu, command, dialog).
The installed file exports dashboard5Demo alongside the block: the exact props behind the preview above. Spread it to get the full workspace in one line. The block is full-height (h-screen), so render it as the page's main surface rather than inside a constrained container.
import { Dashboard5, dashboard5Demo } from "@/components/beste/block/dashboard5";
export default function Page() {
return <Dashboard5 {...dashboard5Demo} />;
}Every prop is optional. Omit any and the block falls back to its built-in demo data, so <Dashboard5 /> renders a complete, populated booking workspace out of the box. Pass just the props you want to override.
| Prop | Type | Default | Description |
|---|---|---|---|
brandName | string | "Atrium" | Wordmark shown next to the hexagon logo in the top-left header |
heading | string | "Main dashboard" | The left-panel page heading |
manager | DashboardManager | demo manager | Identity shown at the top of the right rail (name, role, avatar) |
commandGroups | CommandPaletteGroup[] | demo groups | Grouped entries in the ⌘K command palette |
notifications | NotificationItem[] | demo items | Entries behind the right-rail notifications bell |
metrics | Metric[] | demo stats | The three-up metric strip in the bento |
bookings | Booking[] | demo cards | The "Active bookings" cards |
schedule | TimelineRow[] | demo rows | Room rows feeding the room-availability schedule timeline |
agenda | AgendaSlot[] | demo slots | The right-rail day agenda slots |
bookedDays | Date[] | demo dates | Days that draw booked-day dots on the calendar |
revenue | string | "$3,240" | Pre-formatted value in the "Today's revenue" bento tile |
revenueDelta | string | "+8.2% today" | Trend line under the revenue value |
occupancy | string | "82%" | Pre-formatted value in the "Occupancy" bento tile |
occupancyCaption | string | "28 of 34 rooms" | Caption under the occupancy value |
heroImage | string | demo Unsplash URL | Image URL for the tall bento tile, rendered with a plain <img> |
The block-local data types:
type Booking = {
id: string;
title: string;
time: string; // pre-formatted range, e.g. "12:30 — 15:45"
room: string;
tags: string[];
avatars: string[]; // image URLs, rendered with plain <img>
extra: number; // "+N" overflow count after the avatar stack
enabled: boolean; // initial state of the card's Switch
};
type AgendaSlot = {
time: string; // e.g. "09:00"
event?: {
title: string;
range: string; // e.g. "09:00 — 10:00"
tone: "emerald" | "amber" | "rose";
};
};
type Metric = {
label: string;
value: string; // pre-formatted, e.g. "$2.1M"
delta: string; // e.g. "+4.2%"
icon: LucideIcon;
};
type DashboardManager = {
name: string;
role: string;
avatar: string; // image URL, rendered with a plain <img>
};
// block-local
type CommandPaletteGroup = {
heading: string;
items: { id: string; label: string; icon?: LucideIcon }[];
};The remaining props reuse the interfaces exported by the composed Beste components:
// from notifications-menu
type NotificationItem = {
id: string;
title: string;
description?: string;
time: string;
icon?: LucideIcon;
unread?: boolean;
};
// from schedule-timeline
type TimelineRow = {
id: string;
label: string;
sublabel?: string;
events: {
id: string;
label: string;
start: number; // hour, e.g. 9 or 15.5
end: number;
tone?: "primary" | "emerald" | "amber" | "sky" | "rose" | "violet";
}[];
};A few structural and cosmetic bits stay as constants in the installed file — edit them in place:
tabs — the labels for the left-panel tab bar (Booking, Amenities, Rooms, Locations).agendaTone — the border/background classes mapping each agenda tone (emerald, amber, rose).revenue, occupancy, and heroImage props above.This block composes two standalone Beste UI components, installed alongside it:
/component/schedule-timeline./component/notifications-menu.⌘K (or Ctrl+K) anywhere toggles the command palette; the header search button opens it too, and selecting any item closes it. A global keydown listener is registered on mount and cleaned up on unmount.Switch with independent local state, seeded from the booking's enabled value.bookedDays render a small dot beneath the date.overflow-x-auto, min-w-[560px] container).lg breakpoint; the left panel fills the width on smaller screens, and the header nav / search width collapse responsively."use client") because it uses local state, a keyboard listener, and interactive shadcn/ui primitives, so it composes into any App Router page.<section> is h-screen with its own internal scroll regions. Give it the full viewport rather than nesting it inside a padded layout.<img>, so no next.config images.remotePatterns setup is needed for the remote (Unsplash) hosts.dashboard4
A project-management dashboard: sidebar + search topbar, a four-up project stats row with one highlighted card, a weekly project-analytics bar chart, a reminder card with a start-meeting action, a team-collaboration list, a project-progress radial gauge, and a focus time-tracker card.
dashboard7
A web-analytics console: sidebar + search topbar, a live realtime strip, an hourly sessions area chart, a daily-goal radial gauge, a channel-audience radar chart, a new-vs-returning line chart, and a sortable top-pages table.
dashboard11
A health dashboard with a top navigation bar (no sidebar): three activity-ring radial gauges, a steps area chart and a heart-rate line chart, and a recent-workouts list. A Today/Week/Month segmented control live-swaps the chart data and totals.
dashboard3
An e-commerce analytics dashboard: sidebar + search topbar, a four-up KPI row with period deltas, a net-profit area chart, a repeat-rate radial gauge, a busiest-weekday bar chart, and a best-selling products data table.
dashboard6
A project detail dashboard for staffing: sidebar + action topbar with a project actions menu, a project header with status pills, a five-up stat strip with project meta, functional pipeline sub-tabs, a search / recently-active toggle / filters-menu toolbar that live-filters the grid, and a responsive grid of nine talent cards with wishlist and invite toggles.
dashboard12
An observability console with an icon rail and a live status ribbon: a service-health grid with status dots and latency/uptime, a latency line chart, a request-volume area chart, a 30-day uptime bar strip, and a recent-events feed. A 1h/24h/7d tab control live-swaps the chart data.