@@ -126,22 +126,53 @@ export default class Overlays extends Component<OverlaySignature> {
126126 protected offset = {
127127 name: ' offset' ,
128128 fn : (state : MiddlewareState ) => {
129- let { elements, rects } = state ;
129+ let { elements } = state ;
130130 let { floating, reference } = elements ;
131- let { width, height } = reference .getBoundingClientRect ();
131+ let refRect = reference .getBoundingClientRect ();
132132
133- floating .style .width = width + ' px' ;
134- floating .style .height = height + ' px' ;
133+ floating .style .width = refRect . width + ' px' ;
134+ floating .style .height = refRect . height + ' px' ;
135135 floating .style .position = ' absolute' ;
136136 // Mirror the underlying card's corner radius so any decorative
137137 // outline / box-shadow on the overlay follows the same curve.
138138 if (reference instanceof Element ) {
139139 floating .style .borderRadius =
140140 window .getComputedStyle (reference ).borderRadius ;
141141 }
142+
143+ // Position the overlay from the live reference rect relative to the
144+ // floating element's own offset parent, rather than floating-ui's
145+ // `rects.reference`. floating-ui's first one-or-two computePosition calls
146+ // omit the offset parent's offset (they return the reference in viewport
147+ // coordinates and only subtract the offset parent a frame later), so
148+ // trusting `rects.reference` makes the overlay — and everything riding it
149+ // (the type-label tab, the select chip, the menu, the outline) — paint
150+ // one frame off and visibly jump into place on first appearance.
151+ // Computing it ourselves from the current rects is correct on the very
152+ // first frame. We recover the offset parent's scale the same way the
153+ // Adorn label positioner does (the test runner scales `#ember-testing`),
154+ // and convert the viewport anchor into the offset parent's local space.
155+ let offsetParent = floating .offsetParent as HTMLElement | null ;
156+ let parentRect = offsetParent
157+ ? offsetParent .getBoundingClientRect ()
158+ : new DOMRect (0 , 0 , window .innerWidth , window .innerHeight );
159+ let scaleX =
160+ offsetParent && offsetParent .offsetWidth > 0
161+ ? parentRect .width / offsetParent .offsetWidth
162+ : 1 ;
163+ let scaleY =
164+ offsetParent && offsetParent .offsetHeight > 0
165+ ? parentRect .height / offsetParent .offsetHeight
166+ : 1 ;
167+ if (! Number .isFinite (scaleX ) || scaleX === 0 ) {
168+ scaleX = 1 ;
169+ }
170+ if (! Number .isFinite (scaleY ) || scaleY === 0 ) {
171+ scaleY = 1 ;
172+ }
142173 return {
143- x: rects . reference . x ,
144- y: rects . reference . y ,
174+ x: ( refRect . left - parentRect . left ) / scaleX ,
175+ y: ( refRect . top - parentRect . top ) / scaleY ,
145176 };
146177 },
147178 };
0 commit comments