diff --git a/packages/@mantine/core/src/components/FloatingIndicator/FloatingIndicator.test.tsx b/packages/@mantine/core/src/components/FloatingIndicator/FloatingIndicator.test.tsx index 4fa6a5bbe64..4ac27e62615 100644 --- a/packages/@mantine/core/src/components/FloatingIndicator/FloatingIndicator.test.tsx +++ b/packages/@mantine/core/src/components/FloatingIndicator/FloatingIndicator.test.tsx @@ -1,4 +1,4 @@ -import { tests } from '@mantine-tests/core'; +import { render, tests } from '@mantine-tests/core'; import { FloatingIndicator, FloatingIndicatorProps, @@ -22,4 +22,43 @@ describe('@mantine/core/FloatingIndicator', () => { displayName: '@mantine/core/FloatingIndicator', stylesApiSelectors: ['root'], }); + + it('normalizes geometry when parent container is scaled', () => { + const parent = document.createElement('div'); + const target = document.createElement('div'); + const indicatorRef = { current: document.createElement('div') }; + + Object.defineProperty(parent, 'offsetWidth', { value: 200, configurable: true }); + Object.defineProperty(parent, 'offsetHeight', { value: 100, configurable: true }); + + jest.spyOn(parent, 'getBoundingClientRect').mockReturnValue({ + top: 100, + left: 100, + width: 100, + height: 50, + bottom: 150, + right: 200, + x: 100, + y: 100, + toJSON: () => {}, + }); + + jest.spyOn(target, 'getBoundingClientRect').mockReturnValue({ + top: 125, + left: 150, + width: 50, + height: 25, + bottom: 150, + right: 200, + x: 150, + y: 125, + toJSON: () => {}, + }); + + render(); + + expect(indicatorRef.current.style.width).toBe('100px'); + expect(indicatorRef.current.style.height).toBe('50px'); + expect(indicatorRef.current.style.transform).toBe('translateY(50px) translateX(100px)'); + }); }); diff --git a/packages/@mantine/core/src/components/FloatingIndicator/use-floating-indicator.ts b/packages/@mantine/core/src/components/FloatingIndicator/use-floating-indicator.ts index 899b6d6d74f..86517423124 100644 --- a/packages/@mantine/core/src/components/FloatingIndicator/use-floating-indicator.ts +++ b/packages/@mantine/core/src/components/FloatingIndicator/use-floating-indicator.ts @@ -54,6 +54,9 @@ export function useFloatingIndicator({ const targetRect = target.getBoundingClientRect(); const parentRect = parent.getBoundingClientRect(); + const scaleX = parent.offsetWidth === 0 ? 1 : parentRect.width / parent.offsetWidth; + const scaleY = parent.offsetHeight === 0 ? 1 : parentRect.height / parent.offsetHeight; + const targetComputedStyle = window.getComputedStyle(target); const parentComputedStyle = window.getComputedStyle(parent); @@ -63,10 +66,10 @@ export function useFloatingIndicator({ toInt(targetComputedStyle.borderLeftWidth) + toInt(parentComputedStyle.borderLeftWidth); const position = { - top: targetRect.top - parentRect.top - borderTopWidth, - left: targetRect.left - parentRect.left - borderLeftWidth, - width: targetRect.width, - height: targetRect.height, + top: (targetRect.top - parentRect.top) / scaleY - borderTopWidth, + left: (targetRect.left - parentRect.left) / scaleX - borderLeftWidth, + width: targetRect.width / scaleX, + height: targetRect.height / scaleY, }; ref.current.style.transform = `translateY(${position.top}px) translateX(${position.left}px)`; diff --git a/packages/@mantine/core/src/components/SegmentedControl/SegmentedControl.story.tsx b/packages/@mantine/core/src/components/SegmentedControl/SegmentedControl.story.tsx index 800698430dc..a193c3b8554 100644 --- a/packages/@mantine/core/src/components/SegmentedControl/SegmentedControl.story.tsx +++ b/packages/@mantine/core/src/components/SegmentedControl/SegmentedControl.story.tsx @@ -166,3 +166,21 @@ export function NextToInput() {
{sizes}
); } + +export function ScaledAncestor() { + return ( +
+
+ +
+
+ ); +}