"use client"; import { useStatusBlocksLabels } from "@openstatus/ui/components/blocks/status-i18n"; import { StatusIcon as UnifiedStatusIcon } from "@openstatus/ui/components/blocks/status-icon"; import type { StatusBarData, StatusType, } from "@openstatus/ui/components/blocks/status.types"; import { Skeleton } from "@openstatus/ui/components/ui/skeleton"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@openstatus/ui/components/ui/tooltip"; import { useMediaQuery } from "@openstatus/ui/hooks/use-media-query"; import { cn } from "@openstatus/ui/lib/utils"; import { formatDistanceToNowStrict, subDays } from "date-fns"; import { ArrowUpRight, InfoIcon } from "lucide-react"; import { useState } from "react"; // ============================================================================ // Layout Components // ============================================================================ interface StatusComponentProps extends React.ComponentProps<"div"> { variant: Exclude; } /** * StatusComponent - Root container for individual monitor/service status displays * * This component serves as the main container for displaying a single monitor or * service status. It establishes the status type context via data-variant attribute, * which child components (like StatusComponentIcon and StatusComponentStatus) use * to display the appropriate colors and icons. * * The component acts as a CSS group (/component) for advanced selector patterns, * enabling child components to style themselves based on the parent's variant. * * @param variant - The status type (success, degraded, error, or info) * * @example * ```tsx * * * * * API Server * Main API endpoint * * * 99.9% * * * * * * * * ``` * * @see StatusComponentHeader - For header layout * @see StatusComponentBody - For content area * @see StatusComponentIcon - For status indicator icon * @see StatusComponentStatus - For status label */ export function StatusComponent({ variant, className, children, ...props }: StatusComponentProps) { return (
{children}
); } StatusComponent.displayName = "StatusComponent"; // ============================================================================ // Header Components // ============================================================================ /** * StatusComponentHeader - Header container for monitor status information * * Provides a flex container with space-between alignment for the monitor header, * typically containing title/description on the left and status/uptime on the right. * * @example * ```tsx * * * * Database * * * 100% * * * ``` * * @see StatusComponentHeaderLeft - For left-aligned content * @see StatusComponentHeaderRight - For right-aligned content */ export function StatusComponentHeader({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentHeader.displayName = "StatusComponentHeader"; /** * StatusComponentHeaderLeft - Left-aligned header content container * * Provides a flex container with gap-2 spacing for left-aligned header elements, * typically containing the status icon, title, and optional description icon. * * @example * ```tsx * * * API Gateway * * Handles all incoming requests * * * ``` * * @see StatusComponentIcon - For status indicator * @see StatusComponentTitle - For service name * @see StatusComponentDescription - For info tooltip */ export function StatusComponentHeaderLeft({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentHeaderLeft.displayName = "StatusComponentHeaderLeft"; /** * StatusComponentHeaderRight - Right-aligned header content container * * Provides a flex container with gap-3 spacing for right-aligned header elements, * typically containing uptime percentage and status label. * * @example * ```tsx * * 99.95% * * * ``` * * @see StatusComponentUptime - For uptime percentage display * @see StatusComponentStatus - For status label */ export function StatusComponentHeaderRight({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentHeaderRight.displayName = "StatusComponentHeaderRight"; // ============================================================================ // Content Components // ============================================================================ /** * StatusComponentBody - Main content area for monitor visualizations * * Provides vertical spacing (space-y-2) for stacking content like status bars, * charts, or other status visualizations within the component. * * @example * ```tsx * * * * * ``` * * @see StatusBar - For uptime visualization bars * @see StatusComponentFooter - For footer with date range */ export function StatusComponentBody({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentBody.displayName = "StatusComponentBody"; // ============================================================================ // Display Components // ============================================================================ /** * StatusComponentTitle - Monitor or service name display * * Displays the monitor/service name in monospace font with truncation for long names. * The text is medium weight and uses a base font size. * * @example * ```tsx * Production API * ``` * * @example * ```tsx * * {monitor.name} * * ``` */ export function StatusComponentTitle({ children, className, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentTitle.displayName = "StatusComponentTitle"; /** * StatusComponentDescription - Info icon with tooltip for additional details * * Displays an info icon that shows a tooltip on hover (or tap on touch devices) * with additional description text. Returns null if no children are provided, * allowing for conditional rendering. * * Touch device support is built-in, toggling the tooltip on tap instead of * requiring hover. * * @param children - The description text to show in the tooltip * * @example * ```tsx * * This service handles user authentication and authorization * * ``` * * @example * ```tsx * // Conditionally rendered - returns null if no description * * {monitor.description} * * ``` */ export function StatusComponentDescription({ onClick, children, ...props }: React.ComponentProps) { const isTouch = useMediaQuery("(hover: none)"); const [open, setOpen] = useState(false); if (!children) return null; return ( { if (isTouch) setOpen((prev) => !prev); onClick?.(e); }} className="rounded-full" {...props} >

{children}

); } StatusComponentDescription.displayName = "StatusComponentDescription"; /** * StatusComponentIcon - Status indicator icon for component context * * This component wraps the unified StatusIcon with variant="component", configuring * it to respond to the parent StatusComponent's data-variant attribute. * The displayed icon and color automatically change based on the status type: * - success: Green check icon * - degraded: Yellow warning triangle * - error: Red alert circle * - info: Blue wrench icon * * The icon is smaller (size-[12.5px]) than other variants, optimized for inline * display next to monitor titles. * * @example * ```tsx * * * * CDN * * * ``` * * @see StatusComponent - For setting the variant context * @see StatusIcon from status-icon.tsx - For the underlying unified icon implementation */ export function StatusComponentIcon({ className, ...props }: React.ComponentProps<"div">) { return ( ); } StatusComponentIcon.displayName = "StatusComponentIcon"; /** * StatusComponentFooter - Date range footer for status visualizations * * Displays a date range footer showing the time span of the displayed data, * with the start date on the left (formatted as relative time like "45 days ago") * and "today" on the right. Shows a skeleton loader when data is loading. * * If no data is available, displays a dash (-) on the left side. * * @param data - Array of status bar data points (uses first item's date for start) * @param isLoading - Whether the data is currently loading * * @example * ```tsx * * * * * ``` * * @example * ```tsx * // With loading state * * ``` * * @see StatusBar - For the visualization that this footer describes */ export function StatusComponentFooter({ data, isLoading, }: { data: StatusBarData[]; isLoading?: boolean; }) { const labels = useStatusBlocksLabels(); return (
{isLoading ? ( ) : data.length > 0 ? ( formatDistanceToNowStrict(subDays(new Date(), data.length), { unit: "day", addSuffix: true, }) ) : ( "-" )}
{labels.today}
); } StatusComponentFooter.displayName = "StatusComponentFooter"; /** * StatusComponentUptime - Uptime percentage display * * Displays the uptime percentage in monospace font with slightly muted foreground * color. Typically shows values like "99.9%" or "100%". * * @example * ```tsx * 99.95% * ``` * * @example * ```tsx * * {calculateUptime(data)}% * * ``` * * @see StatusComponentUptimeSkeleton - For loading state */ export function StatusComponentUptime({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentUptime.displayName = "StatusComponentUptime"; /** * StatusComponentUptimeSkeleton - Loading skeleton for uptime percentage * * Displays a skeleton loader matching the size of the uptime percentage display * (h-4 w-16), used while uptime data is being fetched. * * @example * ```tsx * * {isLoading ? ( * * ) : ( * {uptime}% * )} * * ``` * * @see StatusComponentUptime - For the actual uptime display */ export function StatusComponentUptimeSkeleton({ className, ...props }: React.ComponentProps) { return ; } /** * StatusComponentLatency - Latency chip shown next to the monitor title. * * Presentational only; wrap in the app's link primitive to navigate to the * monitor page. The caller supplies the label text (e.g. "92ms p75"). * * @see StatusComponentLatencySkeleton - For loading state */ export function StatusComponentLatency({ className, children, ...props }: React.ComponentProps<"div">) { return (
{children}
); } StatusComponentLatency.displayName = "StatusComponentLatency"; /** * StatusComponentLatencySkeleton - Loading skeleton sized to the latency chip. * * @see StatusComponentLatency - For the actual chip */ export function StatusComponentLatencySkeleton({ className, ...props }: React.ComponentProps) { return ( ); } StatusComponentLatencySkeleton.displayName = "StatusComponentLatencySkeleton"; /** * StatusComponentStatus - Automatic status label display * * Displays a status label that automatically shows the appropriate text and color * based on the parent StatusComponent's variant. The component uses CSS data * attribute selectors to show only the relevant status label: * - success: "Operational" (green) * - degraded: "Degraded" (yellow) * - error: "Outage" (red) * - info: "Maintenance" (blue) * * The labels are sourced from systemStatusLabels.short for consistent messaging * across the application. * * @example * ```tsx * * * * // Displays "Operational" in green * * * ``` * * @example * ```tsx * * * * // Displays "Degraded" in yellow * * * ``` * * @see StatusComponent - For setting the variant that controls the displayed status * @see systemStatusLabels - For the status label text definitions */ export function StatusComponentStatus({ className, ...props }: React.ComponentProps<"div">) { const labels = useStatusBlocksLabels(); return (
{labels.systemStatus.success.short} {labels.systemStatus.degraded.short} {labels.systemStatus.error.short} {labels.systemStatus.info.short}
); } StatusComponentStatus.displayName = "StatusComponentStatus";