import type { EnvironmentConnectionPhase } from "@t3tools/client-runtime/connection"; import { cn } from "~/lib/utils";import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; /** Canonical connection-phase → dot color mapping shared by every status dot. */export function connectionPhaseDotClassName(phase: EnvironmentConnectionPhase): string { switch (phase) { case "connected": return "bg-success"; case "connecting": case "reconnecting": return "bg-warning"; case "error": return "bg-destructive"; default: return "bg-muted-foreground/40"; }} /** Ping halo for transitional phases; null renders no ping. */export function connectionPhasePingClassName(phase: EnvironmentConnectionPhase): string | null { return phase === "connecting" || phase === "reconnecting" ? "bg-warning/60 duration-2000" : null;} type ConnectionStatusDotProps = { tooltipText?: string | null; dotClassName: string; pingClassName?: string | null;}; export function ConnectionStatusDot({ tooltipText, dotClassName, pingClassName,}: ConnectionStatusDotProps) { const dotContent = ( <> {pingClassName ? ( <span className={cn( "absolute inline-flex h-full w-full animate-status-ping rounded-full", pingClassName, )} /> ) : null} <span className={cn("relative inline-flex size-2 rounded-full", dotClassName)} /> </> ); if (!tooltipText) { return ( <span className="relative flex size-3 shrink-0 items-center justify-center"> {dotContent} </span> ); } const dot = ( <button type="button" aria-label={tooltipText} className="relative flex size-3 shrink-0 cursor-help items-center justify-center rounded-full outline-hidden" > {dotContent} </button> ); return ( <Tooltip> <TooltipTrigger render={dot} /> <TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight"> {tooltipText} </TooltipPopup> </Tooltip> );}
import type { EnvironmentConnectionPhase } from "@t3tools/client-runtime/connection";
import { cn } from "~/lib/utils";
import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip";
/** Canonical connection-phase → dot color mapping shared by every status dot. */
export function connectionPhaseDotClassName(phase: EnvironmentConnectionPhase): string {
switch (phase) {
case "connected":
return "bg-success";
case "connecting":
case "reconnecting":
return "bg-warning";
case "error":
return "bg-destructive";
default:
return "bg-muted-foreground/40";
}
}
/** Ping halo for transitional phases; null renders no ping. */
export function connectionPhasePingClassName(phase: EnvironmentConnectionPhase): string | null {
return phase === "connecting" || phase === "reconnecting" ? "bg-warning/60 duration-2000" : null;
}
type ConnectionStatusDotProps = {
tooltipText?: string | null;
dotClassName: string;
pingClassName?: string | null;
};
export function ConnectionStatusDot({
tooltipText,
dotClassName,
pingClassName,
}: ConnectionStatusDotProps) {
const dotContent = (
<>
{pingClassName ? (
<span
className={cn(
"absolute inline-flex h-full w-full animate-status-ping rounded-full",
pingClassName,
)}
/>
) : null}
<span className={cn("relative inline-flex size-2 rounded-full", dotClassName)} />
</>
);
if (!tooltipText) {
return (
<span className="relative flex size-3 shrink-0 items-center justify-center">
{dotContent}
</span>
);
}
const dot = (
<button
type="button"
aria-label={tooltipText}
className="relative flex size-3 shrink-0 cursor-help items-center justify-center rounded-full outline-hidden"
>
{dotContent}
</button>
);
return (
<Tooltip>
<TooltipTrigger render={dot} />
<TooltipPopup side="top" className="max-w-80 whitespace-pre-wrap leading-tight">
{tooltipText}
</TooltipPopup>
</Tooltip>
);
}