mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
feat(reconnect): replace top banner with animated sidebar overlay (#1510)
This commit is contained in:
@@ -1,72 +0,0 @@
|
||||
import { WifiOff } from "lucide-react";
|
||||
|
||||
import {
|
||||
isRelayConnectionDegraded,
|
||||
useRelayConnection,
|
||||
} from "@/shared/api/useRelayConnection";
|
||||
import { useReconnectRelay } from "@/shared/api/useReconnectRelay";
|
||||
import type { ConnectionState } from "@/shared/api/relayClientShared";
|
||||
import { isRelayUnreachableError } from "@/shared/lib/relayError";
|
||||
import { useSidebar } from "@/shared/ui/sidebar";
|
||||
|
||||
const COPY: Partial<Record<ConnectionState, string>> = {
|
||||
reconnecting: "Reconnecting to relay…",
|
||||
stalled: "Connection lost — relay is not responding.",
|
||||
disconnected: "Disconnected from relay.",
|
||||
};
|
||||
|
||||
/**
|
||||
* Thin warning strip surfaced when the relay connection is degraded.
|
||||
*
|
||||
* Renders null while the connection is healthy so it takes up no layout space.
|
||||
* The strip auto-disappears once the state transitions back to "connected" —
|
||||
* no success toast needed.
|
||||
*/
|
||||
type ConnectionBannerProps = {
|
||||
errorMessage?: string;
|
||||
};
|
||||
|
||||
export function ConnectionBanner({ errorMessage }: ConnectionBannerProps) {
|
||||
const state = useRelayConnection();
|
||||
const { isPending, isWaitingOnReconnectHook, reconnect } =
|
||||
useReconnectRelay();
|
||||
const { state: sidebarState } = useSidebar();
|
||||
const hasCollapsedRelayError =
|
||||
sidebarState === "collapsed" &&
|
||||
state !== "connected" &&
|
||||
Boolean(errorMessage && isRelayUnreachableError(errorMessage));
|
||||
|
||||
if (!isRelayConnectionDegraded(state) && !hasCollapsedRelayError) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const message = hasCollapsedRelayError
|
||||
? "Can't reach the relay."
|
||||
: (COPY[state] ?? "Connection issue detected.");
|
||||
|
||||
const buttonLabel = isWaitingOnReconnectHook
|
||||
? "Waiting to reconnect…"
|
||||
: isPending
|
||||
? "Reconnecting…"
|
||||
: "Reconnect";
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative z-30 mt-10 flex shrink-0 items-center gap-2 border-b border-warning/30 bg-warning/5 px-3 py-2 text-xs"
|
||||
data-testid="connection-banner"
|
||||
role="alert"
|
||||
>
|
||||
<WifiOff className="h-3 w-3 shrink-0 text-warning" />
|
||||
<span className="flex-1 text-muted-foreground">{message}</span>
|
||||
<button
|
||||
className="font-medium text-warning hover:underline disabled:opacity-50"
|
||||
data-testid="connection-banner-reconnect"
|
||||
disabled={isPending}
|
||||
onClick={reconnect}
|
||||
type="button"
|
||||
>
|
||||
{buttonLabel}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -264,7 +264,10 @@ export function SidebarCompactActionCard({
|
||||
type="button"
|
||||
>
|
||||
<motion.span
|
||||
className="relative top-[0.1875rem] flex min-h-10 min-w-0 flex-1 flex-col justify-center"
|
||||
className={cn(
|
||||
"relative flex min-h-10 min-w-0 flex-1 flex-col justify-center",
|
||||
description && "top-[0.1875rem]",
|
||||
)}
|
||||
layout="position"
|
||||
transition={contentTransition}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user