@@ -562,9 +562,9 @@ class PositionData {
562562 }
563563
564564 /**
565- * Maximum height/width (in CSS px) the positioned element can occupy in
566- * the resolved placement before crossing the constraint. Drives the
567- * `--ui-position-available-{height,width}` CSS variables
565+ * Maximum height/width (in CSS px) an *inner* box inside the positioned
566+ * element can occupy before the wrapper crosses the constraint edge.
567+ * Drives the `--ui-position-available-{height,width}` CSS variables.
568568 */
569569 get availableSpace ( ) : { height : number ; width : number } {
570570 const targetNode = this . target ?. node as Element | undefined
@@ -622,11 +622,29 @@ class PositionData {
622622 width = constraintRect . width
623623 }
624624
625- // Floor at 16px so a consumer's `max-height` doesn't collapse to 0 in the
626- // frame(s) before placement flips when the trigger sits right at the edge.
625+ // Measure the wrapper's frame
626+ let vFrame = 0
627+ let hFrame = 0
628+ if ( elementNode && 'ownerDocument' in elementNode ) {
629+ const view = ( elementNode as Element ) . ownerDocument ?. defaultView
630+ if ( view ) {
631+ const cs = view . getComputedStyle ( elementNode as Element )
632+ vFrame =
633+ ( parseFloat ( cs . borderTopWidth ) || 0 ) +
634+ ( parseFloat ( cs . borderBottomWidth ) || 0 ) +
635+ ( parseFloat ( cs . paddingTop ) || 0 ) +
636+ ( parseFloat ( cs . paddingBottom ) || 0 )
637+ hFrame =
638+ ( parseFloat ( cs . borderLeftWidth ) || 0 ) +
639+ ( parseFloat ( cs . borderRightWidth ) || 0 ) +
640+ ( parseFloat ( cs . paddingLeft ) || 0 ) +
641+ ( parseFloat ( cs . paddingRight ) || 0 )
642+ }
643+ }
644+
627645 return {
628- height : Math . max ( 16 , height ) ,
629- width : Math . max ( 16 , width )
646+ height : Math . max ( 0 , Math . floor ( height - vFrame - 1 ) ) ,
647+ width : Math . max ( 0 , Math . floor ( width - hFrame - 1 ) )
630648 }
631649 }
632650}
0 commit comments