"use client"; import { StatusComponentIcon, StatusComponentStatus, } from "@openstatus/ui/components/blocks/status-component"; import type { StatusType } from "@openstatus/ui/components/blocks/status.types"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@openstatus/ui/components/ui/collapsible"; import { cn } from "@openstatus/ui/lib/utils"; import { useEffect, useState } from "react"; /** * StatusComponentGroup - Collapsible group for organizing related monitors * * A collapsible container component for grouping related StatusComponent items, * displaying an aggregate status for the group. The component shows: * - Group title * - Aggregate status label (e.g., "Operational", "Degraded") * - Status icon with appropriate color * - Expandable/collapsible content area for grouped monitors * * **Key Features**: * - **Collapsible**: Click to expand/collapse grouped monitors * - **Hydration-Aware Animations**: Prevents layout shift on initial render by delaying * animations until after mount (avoids animation flash when defaultOpen=true) * - **Aggregate Status**: Shows overall status for the entire group * - **Keyboard Accessible**: Full keyboard support via Radix UI Collapsible * - **Hover Effects**: Subtle border and background changes on hover/open * * The component uses a hydration-aware animation pattern: animations are disabled * on the server and first client render, then enabled after mount. This prevents * layout shifts when `defaultOpen={true}` is used. * * @param title - The group name/title * @param status - The aggregate status type for the group (controls icon color and status label) * @param defaultOpen - Whether the group starts expanded (default: false) * @param children - StatusComponent items or other content to display when expanded * * @example * // Basic collapsible group with multiple monitors * ```tsx * * * * * * REST API * * * * * * * * GraphQL API * * * * * ``` * * @example * // Degraded group with mixed statuses * ```tsx * * * * * * Primary DB * * * * * * * * Replica DB * * * * * ``` * * @example * // Multiple groups for different service categories * ```tsx * * * // Core service monitors... * * * // Third-party monitors... * * * // Internal tool monitors... * * * ``` * * @see StatusComponent - For individual monitor displays within the group * @see StatusComponentIcon - For the status icon displayed in the header * @see StatusComponentStatus - For the status label displayed in the header */ export function StatusComponentGroup({ children, title, status, className, defaultOpen = false, ...props }: React.ComponentProps<"div"> & { title: string; status?: Exclude; children?: React.ReactNode; defaultOpen?: boolean; }) { const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); }, []); return (
{title}
{children}
); } StatusComponentGroup.displayName = "StatusComponentGroup";