| ... | ... | @@ -44,6 +44,8 @@ interface Props { |
| 44 | 44 | readonly bottomInset: number; |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | const PREVIEW_MINI_PLAYER_CORNER_RADIUS = 12; |
| 48 | |
| 47 | 49 | // Invisible grab zones straddling each edge; the cursor is the only affordance. |
| 48 | 50 | const RESIZE_HANDLES: ReadonlyArray<{ |
| 49 | 51 | readonly direction: BrowserViewportResizeDirection; |
| ... | ... | @@ -59,6 +61,10 @@ const RESIZE_HANDLES: ReadonlyArray<{ |
| 59 | 61 | { direction: "southeast", className: "-bottom-2 -right-2 size-4 cursor-nwse-resize" }, |
| 60 | 62 | ]; |
| 61 | 63 | |
| 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 | */ |
| 62 | 68 | export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props) { |
| 63 | 69 | const containerRef = useRef<HTMLDivElement | null>(null); |
| 64 | 70 | const gestureRef = useRef<PointerGesture | null>(null); |
| ... | ... | @@ -193,7 +199,13 @@ export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props |
| 193 | 199 | aria-label="Floating browser preview" |
| 194 | 200 | data-preview-mini-player={tabId} |
| 195 | 201 | 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 | }} |
| 197 | 209 | > |
| 198 | 210 | <div className="group pointer-events-auto absolute right-2 top-2 z-[49] size-3"> |
| 199 | 211 | <div |
| ... | ... | @@ -267,19 +279,19 @@ export function ThreadPreviewMiniPlayer({ threadRef, tabId, bottomInset }: Props |
| 267 | 279 | </div> |
| 268 | 280 | </div> |
| 269 | 281 | |
| 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" /> |
| 271 | 283 | <BrowserSurfaceSlot |
| 272 | 284 | tabId={runtimeTabId} |
| 273 | 285 | visible={Boolean(desktopOverlay?.hasWebContents)} |
| 274 | | cornerRadius={12} |
| 286 | cornerRadius={PREVIEW_MINI_PLAYER_CORNER_RADIUS} |
| 275 | 287 | zIndex={PREVIEW_MINI_PLAYER_WEBVIEW_Z_INDEX} |
| 276 | 288 | fitSourceContent |
| 277 | 289 | layoutVersion={`${frame.x}:${frame.y}`} |
| 278 | 290 | className="absolute inset-0" |
| 279 | 291 | /> |
| 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" /> |
| 281 | 293 | {!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"> |
| 283 | 295 | Reconnecting preview… |
| 284 | 296 | </div> |
| 285 | 297 | ) : null} |