diff --git a/semcore/base-components/__tests__/hint.test.tsx b/semcore/base-components/__tests__/hint.test.tsx index 3d99e95201..14a943c07a 100644 --- a/semcore/base-components/__tests__/hint.test.tsx +++ b/semcore/base-components/__tests__/hint.test.tsx @@ -1,9 +1,9 @@ import { expect, test, describe, vi, afterEach } from '@semcore/testing-utils/vitest'; -import { render, fireEvent, waitFor, cleanup, act } from '@testing-library/react'; +import { render, fireEvent, waitFor, cleanup } from '@testing-library/react'; import React, { useRef } from 'react'; import { userEvent } from 'storybook/test'; -import { Hint } from '../src'; +import { Hint, PortalProvider } from '../src'; describe('Hint', () => { afterEach(cleanup); @@ -142,4 +142,58 @@ describe('Hint', () => { vi.useRealTimers(); }); + + test('Should ignore portal stacking by default and render into document.body', async () => { + const containerRef = React.createRef(); + + const TestComponent = () => { + const ref = useRef(null); + return ( + <> +
+ + + + Hint text + + + + ); + }; + + render(); + + await waitFor(() => { + expect(document.body.querySelector('[data-testid="hint"]')).not.toBeNull(); + }); + + const container = document.querySelector('[data-testid="portal-container"]'); + expect(container?.querySelector('[data-testid="hint"]')).toBeNull(); + }); + + test('Should respect portal stacking when ignorePortalsStacking is false', async () => { + const containerRef = React.createRef(); + + const TestComponent = () => { + const ref = useRef(null); + return ( + <> +
+ + + + Hint text + + + + ); + }; + + render(); + + await waitFor(() => { + const container = document.querySelector('[data-testid="portal-container"]'); + expect(container?.querySelector('[data-testid="hint"]')).not.toBeNull(); + }); + }); }); diff --git a/semcore/base-components/src/components/hint/Hint.tsx b/semcore/base-components/src/components/hint/Hint.tsx index 2d158f1fc7..c3778cbd64 100644 --- a/semcore/base-components/src/components/hint/Hint.tsx +++ b/semcore/base-components/src/components/hint/Hint.tsx @@ -43,6 +43,11 @@ export type SimpleHintPopperProps = { defaultVisible?: boolean; /** Function called when visibility changes */ onVisibleChange?: (visible: boolean, e?: Event) => boolean | void; + /** + * Set ignore for portal stacking + * @default true + */ + ignorePortalsStacking?: boolean; }; type DefaultProps = { @@ -50,6 +55,7 @@ type DefaultProps = { timeout: number | [number, number]; timingFunction: DataType.EasingFunction; placement?: Placement; + ignorePortalsStacking?: boolean; }; type State = { @@ -100,6 +106,7 @@ class HintPopperRoot extends Component + { const links = await within(document.body).findAllByRole('link'); const first = links[0]; @@ -10,5 +8,12 @@ export async function Link({ canvasElement }: { canvasElement: HTMLElement }) { return first; }); - await userEvent.hover(await trigger); + const box = trigger.getBoundingClientRect(); + await userEvent.pointer({ + target: trigger, + coords: { + clientX: Math.round(box.left + box.width / 6), + clientY: Math.round(box.top + box.height / 2), + }, + }); } diff --git a/stories/components/base-components/hint/tests/examples/base-example-props.tsx b/stories/components/base-components/hint/tests/examples/base-example-props.tsx index aa60c2530e..2442e86d78 100644 --- a/stories/components/base-components/hint/tests/examples/base-example-props.tsx +++ b/stories/components/base-components/hint/tests/examples/base-example-props.tsx @@ -17,6 +17,7 @@ const Demo = (props: Partial) => { timeout={props.timeout} visible={props.visible} defaultVisible={props.defaultVisible} + ignorePortalsStacking={props.ignorePortalsStacking} triggerRef={ref} onVisibleChange={(visible) => console.log('Hint visibility changed:', visible)} > @@ -33,6 +34,7 @@ export const defaultProps: Partial = { timeout: undefined, visible: undefined, defaultVisible: undefined, + ignorePortalsStacking: true, }; Demo.defaultProps = defaultProps; diff --git a/stories/components/base-components/hint/tests/hint.stories.tsx b/stories/components/base-components/hint/tests/hint.stories.tsx index 8dc8f57319..1cec9d069e 100644 --- a/stories/components/base-components/hint/tests/hint.stories.tsx +++ b/stories/components/base-components/hint/tests/hint.stories.tsx @@ -37,6 +37,9 @@ export const Hint: StoryObj = { defaultVisible: { control: { type: 'boolean' }, }, + ignorePortalsStacking: { + control: { type: 'boolean' }, + }, }, args: defaultProps, };