{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar-2",
  "title": "Weekly Agenda View",
  "description": "Weekly agenda calendar listing Monday to Sunday with time-slotted event rows, confirmed, tentative, and cancelled status colors, and week navigation.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "button",
    "popover",
    "separator"
  ],
  "files": [
    {
      "path": "registry/blocks/calendar/2/calendar-block.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n  Popover,\n  PopoverContent,\n  PopoverDescription,\n  PopoverHeader,\n  PopoverTitle,\n  PopoverTrigger,\n} from \"@/components/ui/popover\"\nimport { Separator } from \"@/components/ui/separator\"\nimport { cn } from \"@/lib/utils\"\nimport { IconPlaceholder } from \"@/components/icons/icon-placeholder\"\n\ntype EventStatus = \"confirmed\" | \"tentative\" | \"cancelled\"\n\ninterface CalEvent {\n  time: string\n  duration: string\n  title: string\n  location?: string\n  status: EventStatus\n}\n\ninterface AgendaDay {\n  label: string\n  date: number\n  isToday: boolean\n  events: CalEvent[]\n}\n\ninterface Week {\n  range: string\n  days: AgendaDay[]\n}\n\nconst STANDUP: CalEvent = {\n  time: \"09:00\",\n  duration: \"30 min\",\n  title: \"Daily standup\",\n  location: \"Zoom\",\n  status: \"confirmed\",\n}\n\nconst WEEKS: Week[] = [\n  {\n    range: \"Jun 9 – Jun 15, 2025\",\n    days: [\n      { label: \"Mon\", date: 9, isToday: false, events: [STANDUP] },\n      {\n        label: \"Tue\",\n        date: 10,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"13:00\",\n            duration: \"1 hr\",\n            title: \"Hiring panel: Backend\",\n            location: \"Conf room B\",\n            status: \"confirmed\",\n          },\n        ],\n      },\n      { label: \"Wed\", date: 11, isToday: false, events: [STANDUP] },\n      {\n        label: \"Thu\",\n        date: 12,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"15:00\",\n            duration: \"45 min\",\n            title: \"Budget planning\",\n            location: \"Finance suite\",\n            status: \"tentative\",\n          },\n        ],\n      },\n      { label: \"Fri\", date: 13, isToday: false, events: [STANDUP] },\n      { label: \"Sat\", date: 14, isToday: false, events: [] },\n      { label: \"Sun\", date: 15, isToday: false, events: [] },\n    ],\n  },\n  {\n    range: \"Jun 16 – Jun 22, 2025\",\n    days: [\n      {\n        label: \"Mon\",\n        date: 16,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"14:00\",\n            duration: \"1 hr\",\n            title: \"Product roadmap review\",\n            location: \"Conf room A\",\n            status: \"confirmed\",\n          },\n        ],\n      },\n      {\n        label: \"Tue\",\n        date: 17,\n        isToday: true,\n        events: [\n          STANDUP,\n          {\n            time: \"11:00\",\n            duration: \"2 hr\",\n            title: \"Design system workshop\",\n            location: \"Studio 2\",\n            status: \"confirmed\",\n          },\n          {\n            time: \"16:30\",\n            duration: \"30 min\",\n            title: \"1:1 with Jordan\",\n            status: \"tentative\",\n          },\n        ],\n      },\n      {\n        label: \"Wed\",\n        date: 18,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"13:00\",\n            duration: \"1 hr\",\n            title: \"Q2 retrospective\",\n            location: \"Main boardroom\",\n            status: \"confirmed\",\n          },\n        ],\n      },\n      {\n        label: \"Thu\",\n        date: 19,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"10:30\",\n            duration: \"45 min\",\n            title: \"Engineering sync\",\n            status: \"confirmed\",\n          },\n          {\n            time: \"15:00\",\n            duration: \"1 hr\",\n            title: \"Vendor call: Acme Payments\",\n            location: \"External\",\n            status: \"tentative\",\n          },\n        ],\n      },\n      {\n        label: \"Fri\",\n        date: 20,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"12:00\",\n            duration: \"30 min\",\n            title: \"Sprint planning kick-off\",\n            status: \"cancelled\",\n          },\n        ],\n      },\n      { label: \"Sat\", date: 21, isToday: false, events: [] },\n      {\n        label: \"Sun\",\n        date: 22,\n        isToday: false,\n        events: [\n          {\n            time: \"10:00\",\n            duration: \"1 hr\",\n            title: \"Team offsite prep call\",\n            status: \"tentative\",\n          },\n        ],\n      },\n    ],\n  },\n  {\n    range: \"Jun 23 – Jun 29, 2025\",\n    days: [\n      {\n        label: \"Mon\",\n        date: 23,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"11:00\",\n            duration: \"6 hr\",\n            title: \"Design sprint\",\n            location: \"Studio 2\",\n            status: \"confirmed\",\n          },\n        ],\n      },\n      { label: \"Tue\", date: 24, isToday: false, events: [STANDUP] },\n      {\n        label: \"Wed\",\n        date: 25,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"14:00\",\n            duration: \"1 hr\",\n            title: \"Customer advisory board\",\n            location: \"External\",\n            status: \"confirmed\",\n          },\n        ],\n      },\n      { label: \"Thu\", date: 26, isToday: false, events: [STANDUP] },\n      {\n        label: \"Fri\",\n        date: 27,\n        isToday: false,\n        events: [\n          STANDUP,\n          {\n            time: \"16:00\",\n            duration: \"1 hr\",\n            title: \"Team social\",\n            location: \"Rooftop\",\n            status: \"tentative\",\n          },\n        ],\n      },\n      { label: \"Sat\", date: 28, isToday: false, events: [] },\n      { label: \"Sun\", date: 29, isToday: false, events: [] },\n    ],\n  },\n]\n\nconst TODAY_WEEK = 1\n\nconst STATUS_ACCENT: Record<EventStatus, string> = {\n  confirmed: \"bg-primary\",\n  tentative: \"bg-muted-foreground\",\n  cancelled: \"bg-destructive\",\n}\n\nconst STATUS_LABEL: Record<EventStatus, string> = {\n  confirmed: \"Confirmed\",\n  tentative: \"Tentative\",\n  cancelled: \"Cancelled\",\n}\n\nexport default function CalendarBlock() {\n  const [weekIdx, setWeekIdx] = React.useState(TODAY_WEEK)\n  const week = WEEKS[weekIdx]\n  const totalEvents = week.days.reduce((n, d) => n + d.events.length, 0)\n\n  return (\n    <section className=\"flex w-full items-center justify-center bg-background px-6 py-12 text-foreground\">\n      <div className=\"w-full max-w-xl\">\n        <div className=\"overflow-hidden rounded-xl border border-border bg-card\">\n          <div className=\"flex items-center justify-between gap-4 px-4 py-3.5\">\n            <div className=\"flex items-center gap-3\">\n              <span className=\"flex size-9 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary\">\n                <IconPlaceholder\n                  lucide=\"Calendar\"\n                  tabler=\"IconCalendar\"\n                  hugeicons=\"CalendarIcon\"\n                  phosphor=\"Calendar\"\n                  remixicon=\"RiCalendarLine\"\n                  className=\"size-5\"\n                  aria-hidden=\"true\"\n                />\n              </span>\n              <div className=\"flex flex-col\">\n                <h1 className=\"font-heading text-sm font-semibold tracking-tight tabular-nums\">\n                  {week.range}\n                </h1>\n                <p className=\"text-xs text-muted-foreground tabular-nums\">\n                  {totalEvents} {totalEvents === 1 ? \"event\" : \"events\"} this\n                  week\n                </p>\n              </div>\n            </div>\n            <div className=\"flex items-center gap-1\">\n              <Button\n                variant=\"ghost\"\n                size=\"icon-sm\"\n                aria-label=\"Previous week\"\n                disabled={weekIdx === 0}\n                onClick={() => setWeekIdx((i) => Math.max(0, i - 1))}\n              >\n                <IconPlaceholder\n                  lucide=\"ChevronLeft\"\n                  tabler=\"IconChevronLeft\"\n                  hugeicons=\"ArrowLeft01Icon\"\n                  phosphor=\"CaretLeft\"\n                  remixicon=\"RiArrowLeftSLine\"\n                  aria-hidden=\"true\"\n                />\n              </Button>\n              <Button\n                variant=\"outline\"\n                size=\"sm\"\n                onClick={() => setWeekIdx(TODAY_WEEK)}\n              >\n                Today\n              </Button>\n              <Button\n                variant=\"ghost\"\n                size=\"icon-sm\"\n                aria-label=\"Next week\"\n                disabled={weekIdx === WEEKS.length - 1}\n                onClick={() =>\n                  setWeekIdx((i) => Math.min(WEEKS.length - 1, i + 1))\n                }\n              >\n                <IconPlaceholder\n                  lucide=\"ChevronRight\"\n                  tabler=\"IconChevronRight\"\n                  hugeicons=\"ArrowRight01Icon\"\n                  phosphor=\"CaretRight\"\n                  remixicon=\"RiArrowRightSLine\"\n                  aria-hidden=\"true\"\n                />\n              </Button>\n            </div>\n          </div>\n\n          <Separator />\n\n          <div>\n            {week.days.map((day, dayIdx) => (\n              <div key={day.date}>\n                <div\n                  className={cn(\n                    \"flex gap-4 px-4 py-3\",\n                    day.isToday && \"bg-primary/5\"\n                  )}\n                >\n                  <div className=\"flex w-11 shrink-0 flex-col items-center gap-1 pt-1\">\n                    <span\n                      className={cn(\n                        \"text-[10px] font-semibold tracking-widest uppercase\",\n                        day.isToday ? \"text-primary\" : \"text-muted-foreground\"\n                      )}\n                    >\n                      {day.label}\n                    </span>\n                    <span\n                      className={cn(\n                        \"flex size-8 items-center justify-center rounded-md text-sm font-semibold tabular-nums\",\n                        day.isToday\n                          ? \"bg-primary text-primary-foreground\"\n                          : \"text-foreground\"\n                      )}\n                    >\n                      {day.date}\n                    </span>\n                  </div>\n\n                  <div className=\"flex min-w-0 flex-1 flex-col justify-center gap-1\">\n                    {day.events.length === 0 ? (\n                      <p className=\"py-1.5 text-xs text-muted-foreground/70\">\n                        No events\n                      </p>\n                    ) : (\n                      day.events.map((event) => (\n                        <Popover key={`${event.time}-${event.title}`}>\n                          <PopoverTrigger\n                            render={\n                              <button\n                                type=\"button\"\n                                className=\"group flex w-full items-stretch gap-3 px-2 py-1.5 text-left transition-colors hover:bg-muted/60 focus-visible:bg-muted/60 focus-visible:outline-none\"\n                              />\n                            }\n                          >\n                            <span\n                              className={cn(\n                                \"w-1 shrink-0\",\n                                STATUS_ACCENT[event.status]\n                              )}\n                              aria-label={STATUS_LABEL[event.status]}\n                            />\n\n                            <div className=\"flex w-14 shrink-0 flex-col\">\n                              <span className=\"text-xs font-medium text-foreground tabular-nums\">\n                                {event.time}\n                              </span>\n                              <span className=\"text-[10px] text-muted-foreground\">\n                                {event.duration}\n                              </span>\n                            </div>\n\n                            <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n                              <span\n                                className={cn(\n                                  \"truncate text-sm leading-snug font-medium\",\n                                  event.status === \"cancelled\"\n                                    ? \"text-muted-foreground line-through\"\n                                    : \"text-foreground\"\n                                )}\n                              >\n                                {event.title}\n                              </span>\n                              {event.location && (\n                                <span className=\"flex items-center gap-1 text-[10px] text-muted-foreground\">\n                                  <IconPlaceholder\n                                    lucide=\"MapPin\"\n                                    tabler=\"IconMapPin\"\n                                    hugeicons=\"MapPinIcon\"\n                                    phosphor=\"MapPin\"\n                                    remixicon=\"RiMapPinLine\"\n                                    className=\"size-3 shrink-0\"\n                                    aria-hidden=\"true\"\n                                  />\n                                  {event.location}\n                                </span>\n                              )}\n                            </div>\n\n                            <IconPlaceholder\n                              lucide=\"ChevronRight\"\n                              tabler=\"IconChevronRight\"\n                              hugeicons=\"ArrowRight01Icon\"\n                              phosphor=\"CaretRight\"\n                              remixicon=\"RiArrowRightSLine\"\n                              className=\"size-4 shrink-0 self-center text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100\"\n                              aria-hidden=\"true\"\n                            />\n                          </PopoverTrigger>\n\n                          <PopoverContent align=\"start\" className=\"w-64\">\n                            <PopoverHeader>\n                              <PopoverTitle\n                                className={cn(\n                                  event.status === \"cancelled\" &&\n                                    \"text-muted-foreground line-through\"\n                                )}\n                              >\n                                {event.title}\n                              </PopoverTitle>\n                              <PopoverDescription>\n                                {day.label} {day.date}\n                              </PopoverDescription>\n                            </PopoverHeader>\n                            <Separator />\n                            <div className=\"flex flex-col gap-1.5 text-muted-foreground\">\n                              <span className=\"flex items-center gap-1.5\">\n                                <IconPlaceholder\n                                  lucide=\"Clock\"\n                                  tabler=\"IconClock\"\n                                  hugeicons=\"TimeIcon\"\n                                  phosphor=\"Clock\"\n                                  remixicon=\"RiTimeLine\"\n                                  className=\"size-3.5 shrink-0\"\n                                  aria-hidden=\"true\"\n                                />\n                                {event.time} ({event.duration})\n                              </span>\n                              {event.location && (\n                                <span className=\"flex items-center gap-1.5\">\n                                  <IconPlaceholder\n                                    lucide=\"MapPin\"\n                                    tabler=\"IconMapPin\"\n                                    hugeicons=\"MapPinIcon\"\n                                    phosphor=\"MapPin\"\n                                    remixicon=\"RiMapPinLine\"\n                                    className=\"size-3.5 shrink-0\"\n                                    aria-hidden=\"true\"\n                                  />\n                                  {event.location}\n                                </span>\n                              )}\n                              <span className=\"flex items-center gap-1.5\">\n                                <span\n                                  className={cn(\n                                    \"size-1.5 shrink-0\",\n                                    STATUS_ACCENT[event.status]\n                                  )}\n                                  aria-hidden=\"true\"\n                                />\n                                {STATUS_LABEL[event.status]}\n                              </span>\n                            </div>\n                          </PopoverContent>\n                        </Popover>\n                      ))\n                    )}\n                  </div>\n                </div>\n\n                {dayIdx < week.days.length - 1 && <Separator />}\n              </div>\n            ))}\n          </div>\n\n          <Separator />\n\n          <div className=\"flex items-center gap-4 px-4 py-3\">\n            {(\n              [\n                [\"confirmed\", \"Confirmed\"],\n                [\"tentative\", \"Tentative\"],\n                [\"cancelled\", \"Cancelled\"],\n              ] as [EventStatus, string][]\n            ).map(([status, label]) => (\n              <div key={status} className=\"flex items-center gap-1.5\">\n                <span\n                  className={cn(\"size-1.5\", STATUS_ACCENT[status])}\n                  aria-hidden=\"true\"\n                />\n                <span className=\"text-[10px] text-muted-foreground\">\n                  {label}\n                </span>\n              </div>\n            ))}\n          </div>\n        </div>\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "height": "1086px",
    "tier": "free"
  },
  "docs": "Requires a `base-*` style in components.json (the `shadcn init` default). Legacy `new-york`/`radix-*` styles install Radix primitives, which reject the `render` prop this block uses.",
  "categories": [
    "calendar"
  ],
  "type": "registry:block"
}