Skip to content

Commit

Permalink
fix(popover/help/helpinfo): help button contains two button, it desac…
Browse files Browse the repository at this point in the history
…tivate the default onKeyPress
  • Loading branch information
GuillaumeKESTEMAN authored Jan 16, 2024
1 parent e6ef73f commit f9f0341
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ exports[`<File.FileInput> renders Preview correctly for other type 1`] = `
exports[`<File.FileInput> renders Preview correctly for type image 1`] = `
<DocumentFragment>
<div
class="af-popover__wrapper"
class="af-popover__wrapper af-popover__wrapper--over"
role="button"
tabindex="0"
>
<div
class="af-popover__container"
Expand Down
7 changes: 4 additions & 3 deletions packages/help/src/Help.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { PopoverModes, PopoverPlacements } from '@axa-fr/react-toolkit-popover';
import { Meta, Story } from '@storybook/react';
import { PopoverPlacements, PopoverModes } from '@axa-fr/react-toolkit-popover';
import Help from './Help';
import React from 'react';
import readme from '../README.md';
import Help from './Help';
import './help-custom.scss';

export default {
Expand Down Expand Up @@ -43,6 +43,7 @@ const Template: Story<HelpProps> = ({ children, ...args }) => (
export const TextStory: Story<HelpProps> = Template.bind({});
TextStory.args = {
children: 'Lorem ipsum dolor sit amet',
classModifier: 'circle',
mode: PopoverModes.click,
placement: PopoverPlacements.right,
};
Expand Down
8 changes: 3 additions & 5 deletions packages/help/src/Help.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { ComponentPropsWithoutRef, ReactNode } from 'react';
import { getComponentClassName } from '@axa-fr/react-toolkit-core';
import Popover, {
PopoverBase,
PopoverPlacements,
} from '@axa-fr/react-toolkit-popover';
import { getComponentClassName } from '@axa-fr/react-toolkit-core';
import React, { ComponentPropsWithoutRef, ReactNode } from 'react';

export type HelpProps = ComponentPropsWithoutRef<typeof Popover> & {
helpButtonContent?: ReactNode;
Expand Down Expand Up @@ -31,9 +31,7 @@ const Help = ({
mode={mode}>
<PopoverBase.Pop>{children}</PopoverBase.Pop>
<PopoverBase.Over>
<button className={buttonClassName} type="button">
{helpButtonContent}
</button>
<div className={buttonClassName}>{helpButtonContent}</div>
</PopoverBase.Over>
</Popover>
);
Expand Down
10 changes: 9 additions & 1 deletion packages/help/src/help-custom.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
@import '@axa-fr/react-toolkit-core/src/common/scss/core.scss';

.af-popover__container--custom {
margin-top: 50px;
margin-top: 25px;
margin-bottom: 25px;

.af-popover {
&__container-pop {
Expand Down Expand Up @@ -64,3 +65,10 @@
font-size: 1.2rem;
vertical-align: middle;
}

.af-popover__wrapper {
outline-offset: 2px;
&:has(.af-popover__container--circle) {
border-radius: 100vmax;
}
}
11 changes: 6 additions & 5 deletions packages/helpinfo/src/HelpInfo.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { Meta, Story } from '@storybook/react';
import { PopoverPlacements, PopoverModes } from '@axa-fr/react-toolkit-popover';
import Button from '@axa-fr/react-toolkit-button';
import Badge from '@axa-fr/react-toolkit-badge';
import HelpInfo from './HelpInfo';
import Button from '@axa-fr/react-toolkit-button';
import { PopoverModes, PopoverPlacements } from '@axa-fr/react-toolkit-popover';
import { Meta, Story } from '@storybook/react';
import React from 'react';
import readme from '../README.md';
import HelpInfo from './HelpInfo';

export default {
title: 'Components high level/HelpInfo',
Expand Down Expand Up @@ -92,6 +92,7 @@ ButtonStory.args = {
export const BadgeStory: Story<HelpProps> = Template.bind({});
BadgeStory.args = {
content: 'Nombre de notifications',
classModifier: 'circle',
mode: PopoverModes.over,
placement: PopoverPlacements.top,
children: <Badge classModifier="error">5</Badge>,
Expand Down
1 change: 0 additions & 1 deletion packages/helpinfo/src/help-info.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

.af-popover__wrapper:has(.af-popover__container--short) {
position: relative;
display: block;
}

.af-popover__container--short {
Expand Down
53 changes: 23 additions & 30 deletions packages/popover/src/Popover.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Constants } from '@axa-fr/react-toolkit-core';
import React from 'react';
import PopoverBase from './PopoverBase';
import PopoverModes from './PopoverModes';
import Placement from './PopoverPlacements';
Expand All @@ -23,38 +23,28 @@ const PopoverClick = ({
}: Props) => {
const wrapperRef = React.useRef(null);
const [isOpen, setOpen] = React.useState(false);
const [isHover, setHover] = React.useState(false);
const [isPopoverHover, setPopoverHover] = React.useState(false);

const handleClickOutside = (event: MouseEvent | React.MouseEvent) => {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setOpen(false);
document.removeEventListener('click', handleClickOutside);
}
};

const handleClick = (
event: MouseEvent | React.MouseEvent | React.KeyboardEvent<HTMLDivElement>
event:
| MouseEvent
| React.MouseEvent
| React.KeyboardEvent<HTMLDivElement>
| React.FocusEvent,
isOpenValue?: boolean
) => {
if (isPopoverHover) {
if (isPopoverHover || !wrapperRef.current || isOpenValue === isOpen) {
event.stopPropagation();
return;
}

const shouldOpen = !isOpen && isHover;
setOpen(shouldOpen);

if (shouldOpen) {
document.addEventListener('click', handleClickOutside);
}
setOpen((oldIsOpen) => isOpenValue ?? !oldIsOpen);
};

const handleMouseEnter = () => {
setHover(true);
};

const handleMouseLeave = () => {
setHover(false);
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === 'Enter') {
handleClick(event);
}
};

const handleMouseEnterPopover = () => {
Expand All @@ -70,11 +60,10 @@ const PopoverClick = ({
role="button"
tabIndex={0}
ref={wrapperRef}
className="af-popover__wrapper"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onKeyDown={handleClick}
onClick={handleClick}>
className="af-popover__wrapper af-popover__wrapper--click"
onKeyDown={handleKeyDown}
onClick={handleClick}
onBlur={(event) => handleClick(event, false)}>
<PopoverBase
onMouseEnter={handleMouseEnterPopover}
onMouseLeave={handleMouseLeavePopover}
Expand Down Expand Up @@ -106,9 +95,13 @@ const PopoverOver = ({

return (
<div
className="af-popover__wrapper"
role="button"
tabIndex={0}
className="af-popover__wrapper af-popover__wrapper--over"
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
onMouseLeave={handleMouseLeave}
onFocus={handleMouseEnter}
onBlur={handleMouseLeave}>
<PopoverBase
isOpen={isOpen}
placement={placement}
Expand Down
129 changes: 128 additions & 1 deletion packages/popover/src/__tests__/Popover.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import Popover from '../Popover';

describe('<Popover />', () => {
Expand Down Expand Up @@ -40,6 +40,81 @@ describe('<Popover />', () => {
'af-popover__container-pop'
);
});

it('Should hide content when element reclicked', () => {
// Arrange
const { getByRole } = render(
<Popover mode="click">
<Popover.Pop>
<p>Modal content</p>
</Popover.Pop>
<Popover.Over>
<span>Source</span>
</Popover.Over>
</Popover>
);

userEvent.click(getByRole('presentation'));

expect(getByRole('presentation').nextElementSibling).toHaveClass(
'af-popover__container-pop'
);

userEvent.click(getByRole('presentation'));

expect(getByRole('presentation').nextElementSibling).toBeNull();
});

it('Should contain PopoverClick element when the "Enter" key is pressed and the button is focused', () => {
const { getByRole } = render(
<Popover mode="click">
<Popover.Pop>
<p>Modal content</p>
</Popover.Pop>
<Popover.Over>
<span>Source</span>
</Popover.Over>
</Popover>
);

const buttonElement = getByRole('button');
buttonElement.focus();

expect(buttonElement).toHaveFocus();

userEvent.keyboard('{Enter}');

expect(getByRole('presentation').nextElementSibling).toHaveClass(
'af-popover__container-pop'
);
});
});

it('Should hide PopoverClick element when the button loses focus', () => {
const { getByRole } = render(
<Popover mode="click">
<Popover.Pop>
<p>Modal content</p>
</Popover.Pop>
<Popover.Over>
<span>Source</span>
</Popover.Over>
</Popover>
);

const buttonElement = getByRole('button');
buttonElement.focus();

expect(buttonElement).toHaveFocus();

userEvent.keyboard('{Enter}');
expect(getByRole('presentation').nextElementSibling).toHaveClass(
'af-popover__container-pop'
);

userEvent.tab();
expect(buttonElement).not.toHaveFocus();
expect(getByRole('presentation').nextElementSibling).toBeNull();
});

describe('mode "hover"', () => {
Expand Down Expand Up @@ -83,6 +158,30 @@ describe('<Popover />', () => {
);
});

it('Should display content when element is focused', () => {
// Arrange
const { getByRole } = render(
<Popover mode="hover">
<Popover.Pop>
<p>Modal content</p>
</Popover.Pop>
<Popover.Over>
<span>Source</span>
</Popover.Over>
</Popover>
);

const buttonElement = getByRole('button');
buttonElement.focus();

expect(buttonElement).toHaveFocus();

// Assert
expect(getByRole('presentation').nextElementSibling).toHaveClass(
'af-popover__container-pop'
);
});

it('Should hide content when element not hovered', () => {
// Arrange
const { getByRole } = render(
Expand All @@ -104,4 +203,32 @@ describe('<Popover />', () => {
expect(getByRole('presentation').nextSibling).toBeNull();
});
});

it('Should hide content when element loses focus', () => {
// Arrange
const { getByRole } = render(
<Popover mode="hover">
<Popover.Pop>
<p>Modal content</p>
</Popover.Pop>
<Popover.Over>
<span>Source</span>
</Popover.Over>
</Popover>
);

const buttonElement = getByRole('button');
buttonElement.focus();

expect(buttonElement).toHaveFocus();

expect(getByRole('presentation').nextElementSibling).toHaveClass(
'af-popover__container-pop'
);

userEvent.tab();

expect(buttonElement).not.toHaveFocus();
expect(getByRole('presentation').nextElementSibling).toBeNull();
});
});
3 changes: 2 additions & 1 deletion packages/popover/src/help-custom.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
@import '@axa-fr/react-toolkit-core/src/common/scss/core.scss';

.af-popover__container--custom {
margin-top: 50px;
margin-top: 25px;
margin-bottom: 25px;

.af-popover {
&__container-pop {
Expand Down
5 changes: 4 additions & 1 deletion packages/popover/src/popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ $padding-popover: 0.5rem 1rem;
background: inherit;
border: 0;
padding: 0;

&--click {
cursor: pointer;
}
}

&__container {
cursor: initial;
display: inline-block;

&-pop {
Expand Down

0 comments on commit f9f0341

Please sign in to comment.