/** * Shared visual shell for the three runtime-provider settings cards * (Hermes, OpenClaw, Paperclip). * * Renders a consistent header (logo + name + status badge + Learn more link), * a description block, a slot for connection-mode tabs, the form contents the * caller passes as children, and a footer with Test/Save/Save & Test buttons * plus a status toast that surfaces probe + save outcomes. */ import { ReactNode } from "react"; import { Loader2 } from "lucide-react"; export type RuntimeStatusKind = "neutral" | "ok" | "err" | "loading"; export interface RuntimeCardShellProps { /** Name shown next to the logo (e.g. "Hermes"). */ name: string; /** Optional sub-line under the name (e.g. "by Nous Research"). */ subname?: string; /** The provider logo. Use a `` or an inline `` for brand SVGs. */ logo: ReactNode; /** "Learn more" target — official documentation/site. */ learnMoreHref: string; /** Status kind drives the badge color. */ statusKind: RuntimeStatusKind; /** Status text (e.g. "✓ Detected v0.8.0"). */ statusText: string; /** Description shown under the header. */ description: ReactNode; /** Optional extra header chrome (e.g. tabs). Rendered above the form. */ tabs?: ReactNode; /** The form fields. */ children: ReactNode; /** Disabled state for the action row. */ busy: "loading" | "saving" | "testing" | "save-test" | null; /** Disable Test if some required input is missing. */ canTest?: boolean; /** Toast under the action row — shown when not null. */ toast?: { kind: "ok" | "err"; message: string } | null; onTest: () => void; onSave: () => void; onSaveAndTest: () => void; /** Optional extra content right above the footer (e.g. an install hint). */ belowForm?: ReactNode; /** A test-id forwarded to the root element. */ testId?: string; } export function RuntimeCardShell(props: RuntimeCardShellProps) { const { name, subname, logo, learnMoreHref, statusKind, statusText, description, tabs, children, busy, canTest = true, toast, onTest, onSave, onSaveAndTest, belowForm, testId, } = props; const statusClass = statusKind === "ok" ? "runtime-card__status runtime-card__status--ok" : statusKind === "err" ? "runtime-card__status runtime-card__status--err" : "runtime-card__status runtime-card__status--neutral"; return (
{logo}

{name}

{subname && ( {subname} )} {statusKind === "loading" && } {statusText}
Learn more →

{description}

{tabs}
{children}
{belowForm}
); }