@@ -425,6 +425,51 @@ const Floating = {
425425 content . style . transform = "none" ;
426426 }
427427
428+ // Clamp to viewport to prevent content from overflowing screen edges.
429+ // This runs regardless of smartPositioning to always keep content visible.
430+ const contentWidth = content . offsetWidth ;
431+ const contentHeight = content . offsetHeight ;
432+ const viewportLeft = window . scrollX ;
433+ const viewportRight = window . scrollX + window . innerWidth ;
434+ const viewportTop = window . scrollY ;
435+ const viewportBottom = window . scrollY + window . innerHeight ;
436+
437+ if ( pos === "top" || pos === "bottom" ) {
438+ // left is the center point (CSS translateX(-50%) shifts it), so actual edges are:
439+ const actualLeft = left - contentWidth / 2 ;
440+ const actualRight = left + contentWidth / 2 ;
441+
442+ if ( actualRight > viewportRight ) {
443+ left = viewportRight - contentWidth - gap ;
444+ content . style . transform = "none" ;
445+ } else if ( actualLeft < viewportLeft ) {
446+ left = viewportLeft + gap ;
447+ content . style . transform = "none" ;
448+ }
449+
450+ // When content is wider than viewport, the right-edge clamp pushes left off-screen.
451+ // Always anchor to left edge so the start of content stays visible (LTR).
452+ if ( left < viewportLeft + gap ) {
453+ left = viewportLeft + gap ;
454+ content . style . transform = "none" ;
455+ }
456+ } else if ( pos === "left" || pos === "right" ) {
457+ if ( top + contentHeight > viewportBottom ) {
458+ top = viewportBottom - contentHeight - gap ;
459+ }
460+ if ( top < viewportTop ) {
461+ top = viewportTop + gap ;
462+ }
463+
464+ // Horizontal clamping for left/right positions
465+ if ( left + contentWidth > viewportRight ) {
466+ left = viewportRight - contentWidth - gap ;
467+ }
468+ if ( left < viewportLeft + gap ) {
469+ left = viewportLeft + gap ;
470+ }
471+ }
472+
428473 content . style . position = "absolute" ;
429474 content . style . top = `${ top } px` ;
430475 content . style . left = `${ left } px` ;
0 commit comments