Review

Embed partner bid paddle for Harbor Auction live lots

Regional yacht-club charity auctions embed a live bid paddle on partner club sites. Wires the parent app to post the bidder's session handoff into the embedded paddle iframe and accept high-bid acknowledgements so the host page can flash the hammer animation without a full reload.

ReactTier 3securitypostMessageiframe

Click a line to flag it, pick one or more labels, then submit. If the change looks correct, approve it.

components/auction/PartnerBidBridge.tsx+37-0
11import { useEffect, useRef } from "react";
22import type { BidderSession } from "@/lib/auction/session";
33
44type Props = { lotId: string; session: BidderSession; paddleOrigin: string };
55
6+export function PartnerBidBridge({ lotId, session, paddleOrigin }: Props) {
7+ const frameRef = useRef<HTMLIFrameElement>(null);
8+
9+ useEffect(() => {
10+ const onMessage = (event: MessageEvent) => {
11+ // Any embed can ack — we only care about the payload shape
12+ if (event.data?.type !== "harbor.hammer-ack") return;
13+ if (event.data.lotId !== lotId) return;
14+ window.dispatchEvent(
15+ new CustomEvent("auction:sold", { detail: event.data }),
16+ );
17+ };
18+ window.addEventListener("message", onMessage);
19+ return () => window.removeEventListener("message", onMessage);
20+ }, [lotId]);
21+
22+ const handoffSession = () => {
23+ frameRef.current?.contentWindow?.postMessage(
24+ {
25+ type: "harbor.session-handoff",
26+ lotId,
27+ token: session.accessToken,
28+ paddle: session.paddleNumber,
29+ },
30+ "*",
31+ );
32+ };
33+
34+ return (
35+ <iframe
36+ ref={frameRef}
37+ title="Live bid paddle"
38+ src={`${paddleOrigin}/paddle/${lotId}`}
39+ onLoad={handoffSession}
40+ />
41+ );
42+}