Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
17 kB ยท 560 lines
TSX
at incident-api
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561"use client";
import { useStatusBlocksLabels } from "@openstatus/ui/components/blocks/status-i18n";import { cn } from "@openstatus/ui/lib/utils";
// ============================================================================// Container Components// ============================================================================
/** * StatusBlankContainer - Main container for empty state displays * * Provides a centered, bordered container with muted background for displaying * empty state content. The container is responsive with adaptive padding * (sm:px-8 sm:py-6) and uses flexbox for vertical centering of content. * * @example * ```tsx * <StatusBlankContainer> * <StatusBlankTitle>No Data Available</StatusBlankTitle> * <StatusBlankDescription>Add monitors to see data here</StatusBlankDescription> * </StatusBlankContainer> * ``` * * @see StatusBlankTitle - For heading text * @see StatusBlankDescription - For descriptive text */export function StatusBlankContainer({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn( "bg-muted/30 flex flex-col items-center justify-center gap-2.5 rounded-lg border px-3 py-2 text-center sm:px-8 sm:py-6", className, )} {...props} > {children} </div> );}
// ============================================================================// Text Components// ============================================================================
/** * StatusBlankTitle - Title text for empty state displays * * Displays medium-weight title text within empty state containers. * Typically used to communicate the empty state condition. * * @example * ```tsx * <StatusBlankTitle>No monitors found</StatusBlankTitle> * ``` * * @see StatusBlankDescription - For additional descriptive text */export function StatusBlankTitle({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn("font-medium", className)} {...props}> {children} </div> );}
/** * StatusBlankDescription - Descriptive text for empty state displays * * Displays muted, monospaced text providing additional context or guidance * for the empty state. The monospace font helps distinguish it as secondary * instructional text. * * @example * ```tsx * <StatusBlankDescription> * Add monitors to this page to see their status here * </StatusBlankDescription> * ``` * * @see StatusBlankTitle - For primary heading text */export function StatusBlankDescription({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn("text-muted-foreground font-mono text-sm", className)} {...props} > {children} </div> );}
/** * StatusBlankContent - Content wrapper for empty state text * * Provides vertical spacing (space-y-1) for stacking title and description * components within an empty state display. * * @example * ```tsx * <StatusBlankContent> * <StatusBlankTitle>No Events</StatusBlankTitle> * <StatusBlankDescription>No events to display</StatusBlankDescription> * </StatusBlankContent> * ``` */export function StatusBlankContent({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn("space-y-1", className)} {...props}> {children} </div> );}
// ============================================================================// Visualization Components// ============================================================================
/** * StatusBlankReport - Visual representation of an empty incident report * * Displays a stylized preview of an incident report page with placeholder * header, report updates, and an overlay gradient. Used to visualize what * incident reports will look like when created. * * This component is typically rendered in multiple layers with different * scales and opacities to create a stacked card effect. * * @example * ```tsx * <div className="relative"> * <StatusBlankReport className="absolute scale-80 opacity-80" /> * <StatusBlankReport /> * </div> * ``` * * @see StatusBlankEvents - For composed empty state with stacked reports * @see StatusBlankPageHeader - For the header visualization * @see StatusBlankReportUpdate - For the update line visualizations */export function StatusBlankReport({ ...props }: React.ComponentProps<"div">) { return ( <StatusBlankPage {...props}> <StatusBlankPageHeader /> <div className="flex w-full flex-col"> <StatusBlankReportUpdate /> <StatusBlankReportUpdate /> </div> <StatusBlankOverlay /> </StatusBlankPage> );}
/** * StatusBlankMonitor - Visual representation of an empty monitor display * * Displays a stylized preview of a monitor page with placeholder header and * uptime visualization bars. Used to show what monitor displays will look like * when monitors are added. * * This component is typically rendered in multiple layers with different * scales and opacities to create a stacked card effect. * * @example * ```tsx * <div className="relative"> * <StatusBlankMonitor className="absolute scale-80 opacity-80" /> * <StatusBlankMonitor /> * </div> * ``` * * @see StatusBlankMonitors - For composed empty state with stacked monitors * @see StatusBlankPageHeader - For the header visualization * @see StatusBlankMonitorUptime - For the uptime bar visualization */export function StatusBlankMonitor({ ...props }: React.ComponentProps<"div">) { return ( <StatusBlankPage {...props}> <StatusBlankPageHeader /> <StatusBlankMonitorUptime /> <StatusBlankOverlay /> </StatusBlankPage> );}
// ============================================================================// Animation Components (for visualization internals)// ============================================================================
/** * StatusBlankPage - Base container for blank page visualizations * * Provides a card-like container with border and background for page previews. * This component is used as the foundation for StatusBlankReport and * StatusBlankMonitor visualizations, providing consistent sizing and styling. * * The container uses relative positioning to enable absolutely positioned * overlay gradients within the visualization. * * @example * ```tsx * <StatusBlankPage> * <StatusBlankPageHeader /> * <div>// Content here</div> * <StatusBlankOverlay /> * </StatusBlankPage> * ``` * * @see StatusBlankReport - For report visualization using this container * @see StatusBlankMonitor - For monitor visualization using this container */export function StatusBlankPage({ className, children, ...props}: React.ComponentProps<"div">) { return ( <div className={cn( "border-border/70 bg-background relative flex w-full max-w-xs flex-1 flex-col items-center justify-center gap-4 overflow-hidden rounded-lg border px-3 py-2 text-center", className, )} {...props} > {children} </div> );}
/** * StatusBlankPageHeader - Placeholder header for page visualizations * * Displays a stylized representation of a page header with placeholder elements * for logo, navigation items, and actions. Uses accent-colored rounded rectangles * to create a recognizable header pattern. * * The header shows: * - Left: Single square (logo placeholder) * - Center: Three rectangles (navigation items) * - Right: Single rectangle (action button) * * @example * ```tsx * <StatusBlankPage> * <StatusBlankPageHeader /> * // Other visualization content * </StatusBlankPage> * ``` */export function StatusBlankPageHeader({ className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn( "flex w-full items-center justify-between gap-4", className, )} {...props} > <div className="bg-accent/60 size-3 rounded-sm" /> <div className="flex flex-row gap-1"> <div className="bg-accent/60 h-3 w-8 rounded-sm" /> <div className="bg-accent/60 h-3 w-8 rounded-sm" /> <div className="bg-accent/60 h-3 w-8 rounded-sm" /> </div> <div className="bg-accent/60 h-3 w-8 rounded-sm" /> </div> );}
/** * StatusBlankMonitorUptime - Uptime visualization for monitor previews * * Displays a stylized uptime chart with placeholder labels and 30 vertical bars * representing uptime data. Some bars have varying heights to create a realistic * visualization pattern showing occasional incidents. * * The visualization includes: * - Top: Three placeholder labels for time periods * - Bottom: 30 vertical bars with most at full height and some shorter to indicate incidents * * @example * ```tsx * <StatusBlankMonitor> * <StatusBlankPageHeader /> * <StatusBlankMonitorUptime /> * </StatusBlankMonitor> * ``` */export function StatusBlankMonitorUptime({ className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn( "flex w-full flex-col items-center justify-between gap-1", className, )} {...props} > <div className="flex w-full flex-row gap-1"> <div className="bg-accent h-3 w-8 rounded-sm" /> <div className="bg-accent h-3 w-12 rounded-sm" /> <div className="bg-accent h-3 w-10 rounded-sm" /> </div> <div className="flex w-full flex-row items-end gap-0.5"> {Array.from({ length: 30 }).map((_, index) => ( <div key={index} className={cn( "bg-accent h-12 flex-1 rounded-sm", [10, 20].includes(index) && "h-8", [25].includes(index) && "h-10", )} /> ))} </div> </div> );}
/** * StatusBlankReportUpdate - Single update entry for report visualizations * * Displays a stylized representation of an incident report update with placeholder * elements for status indicator, timestamp, and message lines. Creates a timeline-like * appearance when stacked vertically. * * The update shows: * - Left: Square status indicator * - Right: Two label placeholders (status + timestamp) and two message lines * * @example * ```tsx * <StatusBlankPage> * <StatusBlankPageHeader /> * <div className="flex flex-col"> * <StatusBlankReportUpdate /> * <StatusBlankReportUpdate /> * </div> * </StatusBlankPage> * ``` */export function StatusBlankReportUpdate({ className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn("flex w-full items-start gap-2", className)} {...props}> <div className="flex h-full flex-col items-center gap-0.5"> <div className="bg-accent size-3 rounded-sm" /> </div> <div className="flex flex-1 flex-col gap-1 pb-2"> <div className="flex items-center gap-1"> <div className="bg-accent h-3 w-12 rounded-sm" /> <div className="bg-accent h-3 w-16 rounded-sm" /> </div> <div className="bg-accent h-3 w-full rounded-sm" /> <div className="bg-accent h-3 w-full rounded-sm" /> </div> </div> );}
/** * StatusBlankOverlay - Gradient overlay for page visualizations * * Provides a bottom-to-top gradient overlay that fades the visualization content * from transparent (top 40%) to background color (bottom), creating a subtle * depth effect. The overlay is absolutely positioned to cover the entire parent. * * This overlay helps create visual separation between the preview visualization * and any content that might be displayed on top of it (like call-to-action text). * * @example * ```tsx * <StatusBlankPage> * <StatusBlankPageHeader /> * <StatusBlankMonitorUptime /> * <StatusBlankOverlay /> * </StatusBlankPage> * ``` */export function StatusBlankOverlay({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div className={cn( "to-background absolute inset-0 flex flex-col items-center justify-center gap-2 bg-gradient-to-b from-transparent from-40% p-2", className, )} {...props} > {children} </div> );}
// ============================================================================// Composed Empty States// ============================================================================
/** * StatusBlankEvents - Complete empty state for incident reports * * Displays a fully composed empty state with stacked StatusBlankReport * visualizations (three layers with varying scales and opacities) and * customizable title/description text. This creates an engaging empty state * that shows users what incident reports will look like. * * The visualization uses absolute positioning to create a layered card stack * effect with the front card at full opacity and back cards progressively * faded and scaled down. * * @param title - The empty state heading (defaults to `labels.noReports` from the i18n provider) * @param description - The empty state description (defaults to `labels.noReportsDescription` from the i18n provider) * * @example * ```tsx * <StatusBlankEvents * title="No incidents yet" * description="Incident reports will appear here when created" * /> * ``` * * @see StatusBlankReport - For the underlying report visualization */export function StatusBlankEvents({ title, description, action, ...props}: React.ComponentProps<typeof StatusBlankContainer> & { title?: string; description?: string; action?: React.ReactNode;}) { const labels = useStatusBlocksLabels(); return ( <StatusBlankContainer {...props}> <div className="relative mt-8 flex w-full flex-col items-center justify-center"> <StatusBlankReport className="absolute -top-16 scale-60 opacity-50" /> <StatusBlankReport className="absolute -top-8 scale-80 opacity-80" /> <StatusBlankReport /> </div> <StatusBlankContent> <StatusBlankTitle>{title ?? labels.noReports}</StatusBlankTitle> <StatusBlankDescription> {description ?? labels.noReportsDescription} </StatusBlankDescription> </StatusBlankContent> {action} </StatusBlankContainer> );}
/** * StatusBlankMonitors - Complete empty state for monitors * * Displays a fully composed empty state with stacked StatusBlankMonitor * visualizations (three layers with varying scales and opacities) and * customizable title/description text. This creates an engaging empty state * that shows users what monitor displays will look like. * * The visualization uses absolute positioning to create a layered card stack * effect with the front card at full opacity and back cards progressively * faded and scaled down. * * @param title - The empty state heading (defaults to `labels.noPublicMonitors` from the i18n provider) * @param description - The empty state description (defaults to `labels.noPublicMonitorsDescription` from the i18n provider) * * @example * ```tsx * <StatusBlankMonitors * title="No monitors configured" * description="Add monitors to start tracking uptime" * /> * ``` * * @see StatusBlankMonitor - For the underlying monitor visualization */export function StatusBlankMonitors({ title, description, action, ...props}: React.ComponentProps<typeof StatusBlankContainer> & { title?: string; description?: string; action?: React.ReactNode;}) { const labels = useStatusBlocksLabels(); return ( <StatusBlankContainer {...props}> <div className="relative mt-8 flex w-full flex-col items-center justify-center"> <StatusBlankMonitor className="absolute -top-16 scale-60 opacity-50" /> <StatusBlankMonitor className="absolute -top-8 scale-80 opacity-80" /> <StatusBlankMonitor /> </div> <StatusBlankContent> <StatusBlankTitle>{title ?? labels.noPublicMonitors}</StatusBlankTitle> <StatusBlankDescription> {description ?? labels.noPublicMonitorsDescription} </StatusBlankDescription> </StatusBlankContent> {action} </StatusBlankContainer> );}
/** * StatusBlankAction - Styled wrapper for empty-state CTAs. * * Applies border + hover chrome around any actionable child (link, button). * Pass a bare `<Link>` or `<button>` โ this component owns the look. Consumers * of `StatusBlankEvents`/`StatusBlankMonitors`/`StatusFeed.emptyAction` must * wrap their action in this themselves; the parents render the action raw to * avoid doubling chrome on already-styled controls. */export function StatusBlankAction({ children, className, ...props}: React.ComponentProps<"div">) { return ( <div data-slot="status-blank-action" className={cn( "border-border/70 text-muted-foreground hover:border-border hover:text-foreground mt-2 inline-flex items-center justify-center rounded-md border px-3 py-1.5 font-mono text-sm [&>a]:text-inherit [&>a]:no-underline", className, )} {...props} > {children} </div> );}