diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts index 223fb3561d78..3ff416c02ef1 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts @@ -1,5 +1,3 @@ -import PropTypes from 'prop-types'; -import Box from '../../ui/box'; import type { BoxProps } from '../../ui/box/box.d'; export enum BadgeWrapperPosition { @@ -14,9 +12,7 @@ export enum BadgeWrapperAnchorElementShape { circular = 'circular', } -export interface BadgeWrapperProps - extends PropTypes.InferProps, - React.HTMLAttributes { +export interface BadgeWrapperProps extends BoxProps { /** * The element to be wrapped by the BadgeWrapper and for the badge to be positioned on top of */ diff --git a/ui/components/component-library/component-library-components.scss b/ui/components/component-library/component-library-components.scss index 6a10d8f99656..8d26b3e61115 100644 --- a/ui/components/component-library/component-library-components.scss +++ b/ui/components/component-library/component-library-components.scss @@ -29,3 +29,5 @@ @import 'form-text-field/form-text-field'; @import 'banner-alert/banner-alert'; @import 'banner-tip/banner-tip'; +@import 'modal-overlay/modal-overlay'; + diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js index fbf0282f809b..3e59c121edd8 100644 --- a/ui/components/component-library/index.js +++ b/ui/components/component-library/index.js @@ -31,6 +31,7 @@ export { Text, TEXT_DIRECTIONS, INVISIBLE_CHARACTER } from './text'; export { Input, INPUT_TYPES } from './input'; export { TextField, TEXT_FIELD_TYPES, TEXT_FIELD_SIZES } from './text-field'; export { TextFieldSearch } from './text-field-search'; +export { ModalOverlay } from './modal-overlay'; // Molecules export { BannerBase } from './banner-base'; diff --git a/ui/components/component-library/modal-overlay/README.mdx b/ui/components/component-library/modal-overlay/README.mdx new file mode 100644 index 000000000000..cb42da5d003f --- /dev/null +++ b/ui/components/component-library/modal-overlay/README.mdx @@ -0,0 +1,40 @@ +import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; + +import { ModalOverlay } from './modal-overlay'; + +# ModalOverlay + +`ModalOverlay` is a transparent overlay that covers the entire screen. It is used to dim the background when a modal is open. + + + + + +## Props + +The `ModalOverlay` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props + + + +### On Click + +Use the `onClick` prop to handle clicks on the overlay + + + + + +```jsx +import React, { useState } from 'react'; +import { ModalOverlay } from '../../component-library'; + +const [open, setOpen] = useState(false); +const handleOnClick = () => { + setOpen(!open); +}; + +; +{ + open && ; +} +``` diff --git a/ui/components/component-library/modal-overlay/__snapshots__/modal-overlay.test.tsx.snap b/ui/components/component-library/modal-overlay/__snapshots__/modal-overlay.test.tsx.snap new file mode 100644 index 000000000000..10f22ae8d9b9 --- /dev/null +++ b/ui/components/component-library/modal-overlay/__snapshots__/modal-overlay.test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ModalOverlay should match snapshot 1`] = ` +
+
+
+`; diff --git a/ui/components/component-library/modal-overlay/index.ts b/ui/components/component-library/modal-overlay/index.ts new file mode 100644 index 000000000000..bc283f8985c2 --- /dev/null +++ b/ui/components/component-library/modal-overlay/index.ts @@ -0,0 +1,2 @@ +export { ModalOverlay } from './modal-overlay'; +export type { ModalOverlayProps } from './modal-overlay.types'; diff --git a/ui/components/component-library/modal-overlay/modal-overlay.scss b/ui/components/component-library/modal-overlay/modal-overlay.scss new file mode 100644 index 000000000000..afa528a1853c --- /dev/null +++ b/ui/components/component-library/modal-overlay/modal-overlay.scss @@ -0,0 +1,7 @@ +.mm-modal-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} diff --git a/ui/components/component-library/modal-overlay/modal-overlay.stories.tsx b/ui/components/component-library/modal-overlay/modal-overlay.stories.tsx new file mode 100644 index 000000000000..fb2cec5970de --- /dev/null +++ b/ui/components/component-library/modal-overlay/modal-overlay.stories.tsx @@ -0,0 +1,44 @@ +import React, { useState } from 'react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import { ModalOverlay } from './modal-overlay'; + +import README from './README.mdx'; + +export default { + title: 'Components/ComponentLibrary/ModalOverlay', + component: ModalOverlay, + parameters: { + docs: { + page: README, + }, + }, + argTypes: { + className: { + control: 'text', + }, + onClick: { + action: 'onClick', + }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const DefaultStory = Template.bind({}); +DefaultStory.storyName = 'Default'; + +export const OnClick: ComponentStory = (args) => { + const [open, setOpen] = useState(false); + const handleOnClick = () => { + setOpen(!open); + }; + return ( + <> + + {open && } + + ); +}; diff --git a/ui/components/component-library/modal-overlay/modal-overlay.test.tsx b/ui/components/component-library/modal-overlay/modal-overlay.test.tsx new file mode 100644 index 000000000000..e3347176676b --- /dev/null +++ b/ui/components/component-library/modal-overlay/modal-overlay.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { render } from '@testing-library/react'; + +import { ModalOverlay } from './modal-overlay'; + +describe('ModalOverlay', () => { + it('should render ModalOverlay without error', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('modal-overlay')).toBeDefined(); + expect(getByTestId('modal-overlay')).toHaveClass('mm-modal-overlay'); + }); + it('should match snapshot', () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + it('should render with and additional className', () => { + const { getByTestId } = render( + , + ); + expect(getByTestId('modal-overlay')).toHaveClass('test-class'); + }); + it('should fire the onClick function when clicked', () => { + const onClick = jest.fn(); + const { getByTestId } = render( + , + ); + getByTestId('modal-overlay').click(); + expect(onClick).toHaveBeenCalled(); + }); +}); diff --git a/ui/components/component-library/modal-overlay/modal-overlay.tsx b/ui/components/component-library/modal-overlay/modal-overlay.tsx new file mode 100644 index 000000000000..76b9586cba88 --- /dev/null +++ b/ui/components/component-library/modal-overlay/modal-overlay.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import classnames from 'classnames'; + +import { + BackgroundColor, + BLOCK_SIZES, +} from '../../../helpers/constants/design-system'; + +import Box from '../../ui/box/box'; + +import { ModalOverlayProps } from './modal-overlay.types'; + +export const ModalOverlay: React.FC = ({ + onClick, + className = '', + ...props +}) => ( + +); + +export default ModalOverlay; diff --git a/ui/components/component-library/modal-overlay/modal-overlay.types.ts b/ui/components/component-library/modal-overlay/modal-overlay.types.ts new file mode 100644 index 000000000000..a1045bc96783 --- /dev/null +++ b/ui/components/component-library/modal-overlay/modal-overlay.types.ts @@ -0,0 +1,13 @@ +import { BoxProps } from '../../ui/box/box.d'; + +export interface ModalOverlayProps extends BoxProps { + /** + * onClick handler for the overlay + * Not necessary when used with Modal and closeOnClickOutside is true + */ + onClick?: (event: React.MouseEvent) => void; + /** + * Additional className to add to the ModalOverlay + */ + className?: string; +} diff --git a/ui/components/ui/box/box.d.ts b/ui/components/ui/box/box.d.ts index 4c91a50e508e..4a3e0ac2cdeb 100644 --- a/ui/components/ui/box/box.d.ts +++ b/ui/components/ui/box/box.d.ts @@ -87,7 +87,7 @@ export type Size = | SizeNumber | [SizeNumber, SizeNumber?, SizeNumber?, SizeNumber?]; -export interface BoxProps { +export interface BoxProps extends React.HTMLAttributes { children?: React.ReactNode; flexDirection?: | BoxFlexDirection[keyof BoxFlexDirection]