{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "status-component-group",
  "title": "Status Component Group",
  "description": "Collapsible group wrapper for status components",
  "registryDependencies": [
    "https://openstatus.dev/r/status-component.json",
    "https://openstatus.dev/r/status-types.json",
    "collapsible"
  ],
  "files": [
    {
      "path": "src/components/blocks/status-component-group.tsx",
      "content": "\"use client\";\n\nimport {\n  StatusComponentIcon,\n  StatusComponentStatus,\n} from \"@/components/blocks/status-component\";\nimport type { StatusType } from \"@/components/blocks/status.types\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\nimport { useEffect, useState } from \"react\";\n\n/**\n * StatusComponentGroup - Collapsible group for organizing related monitors\n *\n * A collapsible container component for grouping related StatusComponent items,\n * displaying an aggregate status for the group. The component shows:\n * - Group title\n * - Aggregate status label (e.g., \"Operational\", \"Degraded\")\n * - Status icon with appropriate color\n * - Expandable/collapsible content area for grouped monitors\n *\n * **Key Features**:\n * - **Collapsible**: Click to expand/collapse grouped monitors\n * - **Hydration-Aware Animations**: Prevents layout shift on initial render by delaying\n *   animations until after mount (avoids animation flash when defaultOpen=true)\n * - **Aggregate Status**: Shows overall status for the entire group\n * - **Keyboard Accessible**: Full keyboard support via Radix UI Collapsible\n * - **Hover Effects**: Subtle border and background changes on hover/open\n *\n * The component uses a hydration-aware animation pattern: animations are disabled\n * on the server and first client render, then enabled after mount. This prevents\n * layout shifts when `defaultOpen={true}` is used.\n *\n * @param title - The group name/title\n * @param status - The aggregate status type for the group (controls icon color and status label)\n * @param defaultOpen - Whether the group starts expanded (default: false)\n * @param children - StatusComponent items or other content to display when expanded\n *\n * @example\n * // Basic collapsible group with multiple monitors\n * ```tsx\n * <StatusComponentGroup\n *   title=\"API Services\"\n *   status=\"success\"\n *   defaultOpen={false}\n * >\n *   <StatusComponent variant=\"success\">\n *     <StatusComponentHeader>\n *       <StatusComponentHeaderLeft>\n *         <StatusComponentIcon />\n *         <StatusComponentTitle>REST API</StatusComponentTitle>\n *       </StatusComponentHeaderLeft>\n *     </StatusComponentHeader>\n *   </StatusComponent>\n *   <StatusComponent variant=\"success\">\n *     <StatusComponentHeader>\n *       <StatusComponentHeaderLeft>\n *         <StatusComponentIcon />\n *         <StatusComponentTitle>GraphQL API</StatusComponentTitle>\n *       </StatusComponentHeaderLeft>\n *     </StatusComponentHeader>\n *   </StatusComponent>\n * </StatusComponentGroup>\n * ```\n *\n * @example\n * // Degraded group with mixed statuses\n * ```tsx\n * <StatusComponentGroup\n *   title=\"Database Cluster\"\n *   status=\"degraded\"\n *   defaultOpen={true}\n * >\n *   <StatusComponent variant=\"success\">\n *     <StatusComponentHeader>\n *       <StatusComponentHeaderLeft>\n *         <StatusComponentIcon />\n *         <StatusComponentTitle>Primary DB</StatusComponentTitle>\n *       </StatusComponentHeaderLeft>\n *     </StatusComponentHeader>\n *   </StatusComponent>\n *   <StatusComponent variant=\"degraded\">\n *     <StatusComponentHeader>\n *       <StatusComponentHeaderLeft>\n *         <StatusComponentIcon />\n *         <StatusComponentTitle>Replica DB</StatusComponentTitle>\n *       </StatusComponentHeaderLeft>\n *     </StatusComponentHeader>\n *   </StatusComponent>\n * </StatusComponentGroup>\n * ```\n *\n * @example\n * // Multiple groups for different service categories\n * ```tsx\n * <StatusContent>\n *   <StatusComponentGroup title=\"Core Services\" status=\"success\">\n *     // Core service monitors...\n *   </StatusComponentGroup>\n *   <StatusComponentGroup title=\"Third-Party APIs\" status=\"degraded\" defaultOpen>\n *     // Third-party monitors...\n *   </StatusComponentGroup>\n *   <StatusComponentGroup title=\"Internal Tools\" status=\"success\">\n *     // Internal tool monitors...\n *   </StatusComponentGroup>\n * </StatusContent>\n * ```\n *\n * @see StatusComponent - For individual monitor displays within the group\n * @see StatusComponentIcon - For the status icon displayed in the header\n * @see StatusComponentStatus - For the status label displayed in the header\n */\nexport function StatusComponentGroup({\n  children,\n  title,\n  status,\n  className,\n  defaultOpen = false,\n  ...props\n}: React.ComponentProps<\"div\"> & {\n  title: string;\n  status?: Exclude<StatusType, \"empty\">;\n  children?: React.ReactNode;\n  defaultOpen?: boolean;\n}) {\n  const [mounted, setMounted] = useState(false);\n\n  useEffect(() => {\n    setMounted(true);\n  }, []);\n\n  return (\n    <div {...props}>\n      <Collapsible\n        defaultOpen={defaultOpen}\n        data-slot=\"status-component-group\"\n        className={cn(\n          \"-mx-3\",\n          \"bg-muted/50 hover:border-border/50 data-[state=open]:border-border/50 data-[state=open]:bg-muted/50 rounded-lg border border-transparent\",\n          className,\n        )}\n      >\n        <CollapsibleTrigger\n          data-slot=\"status-component-group-trigger\"\n          className={cn(\n            \"group/component flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 font-mono font-medium\",\n            \"cursor-pointer\",\n            className,\n          )}\n          data-variant={status}\n          aria-label={`Toggle ${title} status details`}\n        >\n          {title}\n          <div className=\"flex items-center gap-2\">\n            <StatusComponentStatus className=\"text-sm\" />\n            <StatusComponentIcon />\n          </div>\n        </CollapsibleTrigger>\n        <CollapsibleContent\n          data-slot=\"status-component-group-content\"\n          data-animate={mounted}\n          className={cn(\n            \"border-border/50 flex flex-col gap-3 border-t px-3 py-2\",\n            \"overflow-hidden\",\n            // REMINDER: otherwise, if defaultOpen is true, the animation will be triggered and we have a layout shift\n            \"data-[animate=true]:data-[state=closed]:animate-collapsible-up data-[animate=true]:data-[state=open]:animate-collapsible-down\",\n          )}\n        >\n          {children}\n        </CollapsibleContent>\n      </Collapsible>\n    </div>\n  );\n}\nStatusComponentGroup.displayName = \"StatusComponentGroup\";\n",
      "type": "registry:ui",
      "target": "components/blocks/status-component-group.tsx"
    }
  ],
  "type": "registry:block"
}