Skip to content

Commit

Permalink
Refactor(web-react): Introduce ModalCloseButton component
Browse files Browse the repository at this point in the history
  • Loading branch information
literat committed Sep 27, 2023
1 parent de5f9b2 commit cdc8913
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 23 deletions.
14 changes: 14 additions & 0 deletions packages/web-react/src/components/Modal/ModalCloseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { ModalCloseButtonProps } from '../../types';
import { Icon } from '../Icon';
import { VisuallyHidden } from '../VisuallyHidden';
import { Button } from '../Button';

const ModalCloseButton = ({ label = 'Close', onClose, id, isOpen, ...restProps }: ModalCloseButtonProps) => (
<Button {...restProps} isSquare color="tertiary" onClick={onClose} aria-expanded={isOpen} aria-controls={id}>
<Icon name="close" />
<VisuallyHidden>{label}</VisuallyHidden>
</Button>
);

export default ModalCloseButton;
19 changes: 3 additions & 16 deletions packages/web-react/src/components/Modal/ModalHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import classNames from 'classnames';
import React from 'react';
import { useStyleProps } from '../../hooks';
import { ClickEvent, ModalHeaderProps } from '../../types';
import { Button } from '../Button';
import { Icon } from '../Icon';
import { VisuallyHidden } from '../VisuallyHidden';
import { ModalHeaderProps } from '../../types';
import ModalCloseButton from './ModalCloseButton';
import { useModalContext } from './ModalContext';
import { useModalStyleProps } from './useModalStyleProps';

Expand All @@ -22,18 +20,7 @@ const ModalHeader = (props: ModalHeaderProps) => {
{children}
</h2>
)}
<Button
isSquare
color="tertiary"
onClick={(event: ClickEvent) => {
onClose(event);
}}
aria-expanded={isOpen}
aria-controls={id}
>
<Icon name="close" />
<VisuallyHidden>{closeLabel}</VisuallyHidden>
</Button>
<ModalCloseButton id={id} isOpen={isOpen} label={closeLabel} onClose={onClose} />
</header>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import '@testing-library/jest-dom';
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import { classNamePrefixProviderTest } from '../../../../tests/providerTests/classNamePrefixProviderTest';
import { restPropsTest } from '../../../../tests/providerTests/restPropsTest';
import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest';
import ModalCloseButton from '../ModalCloseButton';

describe('ModalCloseButton', () => {
classNamePrefixProviderTest(ModalCloseButton, 'Button');

stylePropsTest(ModalCloseButton);

restPropsTest(ModalCloseButton, 'button');

it('should have icon', () => {
const dom = render(<ModalCloseButton label="close" id="test" isOpen onClose={() => {}} />);

expect(dom.container.querySelector('svg')).toBeDefined();
});

it('should have visually hidden label', () => {
const dom = render(<ModalCloseButton label="close" id="test" isOpen onClose={() => {}} />);

expect(dom.container.querySelector('button > span')?.textContent).toBe('close');
expect(dom.container.querySelector('button > span')).toHaveClass('accessibility-hidden');
});

it('should be square', () => {
const dom = render(<ModalCloseButton label="close" id="test" isOpen onClose={() => {}} />);

expect(dom.container.querySelector('button')).toHaveClass('Button--square');
});

it('should have tertiary color', () => {
const dom = render(<ModalCloseButton label="close" id="test" isOpen onClose={() => {}} />);

expect(dom.container.querySelector('button')).toHaveClass('Button--tertiary');
});

it('should handle on close click', () => {
const mockedOnClose = jest.fn();
const dom = render(<ModalCloseButton label="close" id="test" isOpen onClose={mockedOnClose} />);

const button = dom.getByRole('button');
fireEvent.click(button);

expect(mockedOnClose).toHaveBeenCalled();
});
});
7 changes: 4 additions & 3 deletions packages/web-react/src/components/Modal/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export { default as Modal } from './Modal';
export { default as ModalDialog } from './ModalDialog';
export { default as ModalBody } from './ModalBody';
export { default as ModalHeader } from './ModalHeader';
export { default as ModalFooter } from './ModalFooter';
export { default as ModalCloseButton } from './ModalCloseButton';
export * from './ModalContext';
export { default as ModalDialog } from './ModalDialog';
export { default as ModalFooter } from './ModalFooter';
export { default as ModalHeader } from './ModalHeader';
export * from './useModalStyleProps';
13 changes: 9 additions & 4 deletions packages/web-react/src/types/modal.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ElementType, ComponentPropsWithRef } from 'react';
import { ComponentPropsWithRef, ElementType } from 'react';
import {
AlignmentXDictionaryType,
ChildrenProps,
ClickEvent,
OmittedExtendedUnsafeStyleProps,
StyleProps,
SpiritDivElementProps,
SpiritDialogElementProps,
SpiritDivElementProps,
SpiritElementProps,
AlignmentXDictionaryType,
StyleProps,
} from './shared';

export type ModalDialogElementType = 'article' | 'form';
Expand All @@ -17,6 +17,11 @@ export type ModalDialogHandlingProps = {
onClose: (event: ClickEvent) => void;
};

export interface ModalCloseButtonProps extends ModalDialogHandlingProps {
id: string;
label: string;
}

export type ModalDialogBaseProps<E extends ElementType = ModalDialogElementType> = {
elementType?: E;
isExpandedOnMobile?: boolean;
Expand Down

0 comments on commit cdc8913

Please sign in to comment.