Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: tooltip: adds two props to improve configuration of portal mode #382

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/components/Tooltip/Tooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ Tooltips.args = {
tabIndex: 0,
positionStrategy: 'absolute',
portal: false,
portalId: 'my-portal-id',
portalRoot: null,
children: (
<PrimaryButton
ariaLabel="Show Tooltip"
Expand Down
133 changes: 133 additions & 0 deletions src/components/Tooltip/Tooltip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React from 'react';
import Enzyme from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import MatchMediaMock from 'jest-matchmedia-mock';
import { Tooltip, TooltipSize } from './';
import {
fireEvent,
render,
screen,
waitFor,
waitForElementToBeRemoved,
} from '@testing-library/react';

Enzyme.configure({ adapter: new Adapter() });

let matchMedia: any;

describe('Tooltip', () => {
beforeAll(() => {
matchMedia = new MatchMediaMock();
});

afterEach(() => {
matchMedia.clear();
});

test('Tooltip shows and hides', async () => {
const { container } = render(
<Tooltip
content={<div data-testid="tooltip">This is a tooltip.</div>}
>
<div className="test-div">test</div>
</Tooltip>
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltip'));
expect(container.querySelector('.tooltip')).toBeTruthy();
fireEvent.mouseOut(container.querySelector('.test-div'));
await waitForElementToBeRemoved(() => screen.getByTestId('tooltip'));
expect(container.querySelector('.tooltip')).toBeFalsy();
});

test('Tooltip is large', async () => {
const { container } = render(
<Tooltip
size={TooltipSize.Large}
content={
<div data-testid="tooltipLarge">This is a tooltip.</div>
}
>
<div className="test-div">test</div>
</Tooltip>
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltipLarge'));
expect(container.querySelector('.large')).toBeTruthy();
});

test('Tooltip is medium', async () => {
const { container } = render(
<Tooltip
size={TooltipSize.Medium}
content={
<div data-testid="tooltipMedium">This is a tooltip.</div>
}
>
<div className="test-div">test</div>
</Tooltip>
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltipMedium'));
expect(container.querySelector('.medium')).toBeTruthy();
});

test('Tooltip is small', async () => {
const { container } = render(
<Tooltip
size={TooltipSize.Small}
content={
<div data-testid="tooltipSmall">This is a tooltip.</div>
}
>
<div className="test-div">test</div>
</Tooltip>
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltipSmall'));
expect(container.querySelector('.small')).toBeTruthy();
});

test('Tooltip is portaled', async () => {
const { container } = render(
<>
<Tooltip
portal
content={
<div data-testid="tooltipPortaled">
This is a tooltip.
</div>
}
>
<div className="test-div">test</div>
</Tooltip>
</>,
{ container: document.body }
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltipPortaled'));
expect(container.querySelector('.tooltip')).toBeTruthy();
});

test('Tooltip is portaled in a defined root element', async () => {
const { container } = render(
<>
<Tooltip
portal
portalRoot={document.body}
content={
<div data-testid="tooltipPortaled">
This is a tooltip.
</div>
}
>
<div className="test-div">test</div>
</Tooltip>
</>,
{ container: document.body }
);
fireEvent.mouseOver(container.querySelector('.test-div'));
await waitFor(() => screen.getByTestId('tooltipPortaled'));
expect(container.querySelector('.tooltip')).toBeTruthy();
});
});
6 changes: 5 additions & 1 deletion src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const Tooltip: FC<TooltipProps> = ({
content,
placement = 'bottom',
portal = false,
portalId,
portalRoot,
disabled,
id,
visibleArrow = true,
Expand Down Expand Up @@ -160,7 +162,9 @@ export const Tooltip: FC<TooltipProps> = ({
<ConditionalWrapper
condition={portal}
wrapper={(children) => (
<FloatingPortal>{getChild(children)}</FloatingPortal>
<FloatingPortal id={portalId} root={portalRoot}>
{getChild(children)}
</FloatingPortal>
)}
>
{visible && (
Expand Down
8 changes: 8 additions & 0 deletions src/components/Tooltip/Tooltip.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export interface TooltipProps extends OcBaseProps<HTMLDivElement> {
* @default false
*/
portal?: boolean;
/**
* The id of the floating portal
*/
portalId?: string;
/**
* The element in which to render the portal
*/
portalRoot?: HTMLElement | null;
/**
* Positioning strategy for the tooltip
* @default absolute
Expand Down