authorgravatar for 113233555+caezium@users.noreply.github.comHenry Zhang <113233555+caezium@users.noreply.github.com> 2026-09-11 02:37:15+08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-10 15:37:15-03:00
log3997b9a3a4ee6b43ee768a9b372ff3dd52fd840e
tree1a84b4ab478819cb9690d88d8f1faef006273e41
parent21d744039bf76c072c875886ee497e391a0dd430
signature Signed by PGP key B5690EEEBB952194

fix(web): align floating browser preview corners (#10915)


1 files changed, 17 insertions(+), 5 deletions(-)

apps/web/src/components/preview/ThreadPreviewMiniPlayer.tsx+17-5
......@@ -44,6 +44,8 @@ interface Props {
4444 readonly bottomInset: number;
4545}
4646
47const PREVIEW_MINI_PLAYER_CORNER_RADIUS = 12;
48
4749// Invisible grab zones straddling each edge; the cursor is the only affordance.
4850const RESIZE_HANDLES: ReadonlyArray<{
4951 readonly direction: BrowserViewportResizeDirection;
......@@ -59,6 +61,10 @@ const RESIZE_HANDLES: ReadonlyArray<{
5961 { direction: "southeast", className: "-bottom-2 -right-2 size-4 cursor-nwse-resize" },
6062];
6163
64/**
65 * Floats the thread's browser surface over chat. Native clipping and the DOM
66 * frame use the same radius so their separately composited edges stay aligned.
67 */
6268export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props) {
6369 const containerRef = useRef<HTMLDivElement | null>(null);
6470 const gestureRef = useRef<PointerGesture | null>(null);
......@@ -193,7 +199,13 @@ export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props
193199 aria-label="Floating browser preview"
194200 data-preview-mini-player={tabId}
195201 className="pointer-events-none absolute select-none"
196 style={{ left: frame.x, top: frame.y, width: frame.width, height: frame.height }}
202 style={{
203 left: frame.x,
204 top: frame.y,
205 width: frame.width,
206 height: frame.height,
207 borderRadius: PREVIEW_MINI_PLAYER_CORNER_RADIUS,
208 }}
197209 >
198210 <div className="group pointer-events-auto absolute right-2 top-2 z-[49] size-3">
199211 <div
......@@ -267,19 +279,19 @@ export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props
267279 </div>
268280 </div>
269281
270 <div className="absolute inset-0 z-[47] rounded-xl bg-muted shadow-2xl/35" />
282 <div className="absolute inset-0 z-[47] rounded-[inherit] bg-muted shadow-2xl/35" />
271283 <BrowserSurfaceSlot
272284 tabId={runtimeTabId}
273285 visible={Boolean(desktopOverlay?.hasWebContents)}
274 cornerRadius={12}
286 cornerRadius={PREVIEW_MINI_PLAYER_CORNER_RADIUS}
275287 zIndex={PREVIEW_MINI_PLAYER_WEBVIEW_Z_INDEX}
276288 fitSourceContent
277289 layoutVersion={`${frame.x}:${frame.y}`}
278290 className="absolute inset-0"
279291 />
280 <div className="pointer-events-none absolute inset-0 z-[49] rounded-xl ring-1 ring-inset ring-border/80" />
292 <div className="pointer-events-none absolute inset-0 z-[49] rounded-[inherit] ring-1 ring-inset ring-border/80" />
281293 {!desktopOverlay?.hasWebContents ? (
282 <div className="pointer-events-none absolute inset-0 z-[49] flex items-center justify-center rounded-xl bg-muted text-xs text-muted-foreground">
294 <div className="pointer-events-none absolute inset-0 z-[49] flex items-center justify-center rounded-[inherit] bg-muted text-xs text-muted-foreground">
283295 Reconnecting preview…
284296 </div>
285297 ) : null}