From f97ef8df83291f2eb975057466bf83810836f889 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 20 Feb 2021 13:22:45 +0100 Subject: [PATCH] Added proper blurred background for modals --- src/index.scss | 10 ---------- src/servers/DeleteServerModal.tsx | 7 ++++--- src/short-urls/UseExistingIfFoundInfoIcon.tsx | 9 +++++---- src/short-urls/helpers/DeleteShortUrlModal.tsx | 7 ++++--- src/short-urls/helpers/EditMetaModal.tsx | 7 ++++--- src/short-urls/helpers/EditShortUrlModal.tsx | 7 ++++--- src/short-urls/helpers/EditTagsModal.tsx | 7 ++++--- src/short-urls/helpers/QrCodeModal.tsx | 7 ++++--- src/tags/helpers/DeleteTagConfirmModal.tsx | 7 ++++--- src/tags/helpers/EditTagModal.tsx | 7 ++++--- src/utils/BlurredModal.scss | 11 +++++++++++ src/utils/BlurredModal.tsx | 12 ++++++++++++ src/visits/helpers/MapModal.tsx | 7 ++++--- test/servers/DeleteServerModal.test.tsx | 5 +++-- test/short-urls/helpers/EditMetaModal.test.tsx | 2 +- test/short-urls/helpers/EditShortUrlModal.test.tsx | 2 +- test/short-urls/helpers/EditTagsModal.test.tsx | 4 ++-- test/short-urls/helpers/QrCodeModal.test.tsx | 5 +++-- test/tags/helpers/DeleteTagConfirmModal.test.tsx | 5 +++-- test/visits/helpers/MapModal.test.tsx | 4 ++-- 20 files changed, 79 insertions(+), 53 deletions(-) create mode 100644 src/utils/BlurredModal.scss create mode 100644 src/utils/BlurredModal.tsx diff --git a/src/index.scss b/src/index.scss index 407826cd..8926936a 100644 --- a/src/index.scss +++ b/src/index.scss @@ -17,16 +17,6 @@ body, color: var(--text-color); } -@media (min-width: $smMin) { - #root { - transition: filter 300ms; - } - - .modal-open #root { - filter: blur(1.5px); - } -} - .bg-main { background-color: $mainColor !important; } diff --git a/src/servers/DeleteServerModal.tsx b/src/servers/DeleteServerModal.tsx index 4d74869e..2c2c2eee 100644 --- a/src/servers/DeleteServerModal.tsx +++ b/src/servers/DeleteServerModal.tsx @@ -1,5 +1,6 @@ -import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { RouterProps } from 'react-router'; +import { BlurredModal } from '../utils/BlurredModal'; import { ServerWithId } from './data'; export interface DeleteServerModalProps { @@ -20,7 +21,7 @@ const DeleteServerModal = ({ server, toggle, isOpen, deleteServer, history }: De }; return ( - + Remove server

Are you sure you want to remove {server ? server.name : ''}?

@@ -35,7 +36,7 @@ const DeleteServerModal = ({ server, toggle, isOpen, deleteServer, history }: De -
+ ); }; diff --git a/src/short-urls/UseExistingIfFoundInfoIcon.tsx b/src/short-urls/UseExistingIfFoundInfoIcon.tsx index c737d690..3db7c9b1 100644 --- a/src/short-urls/UseExistingIfFoundInfoIcon.tsx +++ b/src/short-urls/UseExistingIfFoundInfoIcon.tsx @@ -1,11 +1,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faInfoCircle as infoIcon } from '@fortawesome/free-solid-svg-icons'; -import { Modal, ModalBody, ModalHeader } from 'reactstrap'; -import './UseExistingIfFoundInfoIcon.scss'; +import { ModalBody, ModalHeader } from 'reactstrap'; import { useToggle } from '../utils/helpers/hooks'; +import { BlurredModal } from '../utils/BlurredModal'; +import './UseExistingIfFoundInfoIcon.scss'; const InfoModal = ({ isOpen, toggle }: { isOpen: boolean; toggle: () => void }) => ( - + Info

@@ -33,7 +34,7 @@ const InfoModal = ({ isOpen, toggle }: { isOpen: boolean; toggle: () => void }) - + ); const UseExistingIfFoundInfoIcon = () => { diff --git a/src/short-urls/helpers/DeleteShortUrlModal.tsx b/src/short-urls/helpers/DeleteShortUrlModal.tsx index 435b3318..621a03fb 100644 --- a/src/short-urls/helpers/DeleteShortUrlModal.tsx +++ b/src/short-urls/helpers/DeleteShortUrlModal.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { identity, pipe } from 'ramda'; import { ShortUrlDeletion } from '../reducers/shortUrlDeletion'; import { ShortUrlModalProps } from '../data'; @@ -7,6 +7,7 @@ import { handleEventPreventingDefault, OptionalString } from '../../utils/utils' import { Result } from '../../utils/Result'; import { isInvalidDeletionError } from '../../api/utils'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; interface DeleteShortUrlModalConnectProps extends ShortUrlModalProps { shortUrlDeletion: ShortUrlDeletion; @@ -32,7 +33,7 @@ const DeleteShortUrlModal = ( }); return ( - +

Delete short URL @@ -67,7 +68,7 @@ const DeleteShortUrlModal = ( -
+ ); }; diff --git a/src/short-urls/helpers/EditMetaModal.tsx b/src/short-urls/helpers/EditMetaModal.tsx index 688cf9be..8b8d1b4c 100644 --- a/src/short-urls/helpers/EditMetaModal.tsx +++ b/src/short-urls/helpers/EditMetaModal.tsx @@ -1,5 +1,5 @@ import { ChangeEvent, useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader, FormGroup, Input, UncontrolledTooltip } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader, FormGroup, Input, UncontrolledTooltip } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faInfoCircle as infoIcon } from '@fortawesome/free-solid-svg-icons'; import { ExternalLink } from 'react-external-link'; @@ -12,6 +12,7 @@ import { ShortUrl, ShortUrlMeta, ShortUrlModalProps } from '../data'; import { handleEventPreventingDefault, Nullable, OptionalString } from '../../utils/utils'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; interface EditMetaModalConnectProps extends ShortUrlModalProps { shortUrlMeta: ShortUrlMetaEdition; @@ -42,7 +43,7 @@ const EditMetaModal = ( }).then(close); return ( - + Edit metadata for @@ -94,7 +95,7 @@ const EditMetaModal = ( - + ); }; diff --git a/src/short-urls/helpers/EditShortUrlModal.tsx b/src/short-urls/helpers/EditShortUrlModal.tsx index 0a09e27e..cee662d4 100644 --- a/src/short-urls/helpers/EditShortUrlModal.tsx +++ b/src/short-urls/helpers/EditShortUrlModal.tsx @@ -1,11 +1,12 @@ import { useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader, FormGroup, Input, Button } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader, FormGroup, Input, Button } from 'reactstrap'; import { ExternalLink } from 'react-external-link'; import { ShortUrlEdition } from '../reducers/shortUrlEdition'; import { handleEventPreventingDefault, hasValue, OptionalString } from '../../utils/utils'; import { ShortUrlModalProps } from '../data'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; interface EditShortUrlModalProps extends ShortUrlModalProps { shortUrlEdition: ShortUrlEdition; @@ -20,7 +21,7 @@ const EditShortUrlModal = ({ isOpen, toggle, shortUrl, shortUrlEdition, editShor const doEdit = async () => editShortUrl(shortUrl.shortCode, shortUrl.domain, longUrl).then(toggle); return ( - + Edit long URL for @@ -49,7 +50,7 @@ const EditShortUrlModal = ({ isOpen, toggle, shortUrl, shortUrlEdition, editShor - + ); }; diff --git a/src/short-urls/helpers/EditTagsModal.tsx b/src/short-urls/helpers/EditTagsModal.tsx index a390499c..bc6875ed 100644 --- a/src/short-urls/helpers/EditTagsModal.tsx +++ b/src/short-urls/helpers/EditTagsModal.tsx @@ -1,5 +1,5 @@ import { FC, useEffect, useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { ExternalLink } from 'react-external-link'; import { ShortUrlTags } from '../reducers/shortUrlTags'; import { ShortUrlModalProps } from '../data'; @@ -7,6 +7,7 @@ import { OptionalString } from '../../utils/utils'; import { TagsSelectorProps } from '../../tags/helpers/TagsSelector'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; interface EditTagsModalProps extends ShortUrlModalProps { shortUrlTags: ShortUrlTags; @@ -28,7 +29,7 @@ const EditTagsModal = (TagsSelector: FC) => ( .catch(() => {}); return ( - + Edit tags for @@ -46,7 +47,7 @@ const EditTagsModal = (TagsSelector: FC) => ( {saving ? 'Saving tags...' : 'Save tags'} - + ); }; diff --git a/src/short-urls/helpers/QrCodeModal.tsx b/src/short-urls/helpers/QrCodeModal.tsx index e26d289a..9b1c7bad 100644 --- a/src/short-urls/helpers/QrCodeModal.tsx +++ b/src/short-urls/helpers/QrCodeModal.tsx @@ -1,5 +1,5 @@ import { useMemo, useState } from 'react'; -import { DropdownItem, FormGroup, Modal, ModalBody, ModalHeader, Row } from 'reactstrap'; +import { DropdownItem, FormGroup, ModalBody, ModalHeader, Row } from 'reactstrap'; import { ExternalLink } from 'react-external-link'; import classNames from 'classnames'; import { ShortUrlModalProps } from '../data'; @@ -9,6 +9,7 @@ import { DropdownBtn } from '../../utils/DropdownBtn'; import { CopyToClipboardIcon } from '../../utils/CopyToClipboardIcon'; import { buildQrCodeUrl, QrCodeCapabilities, QrCodeFormat } from '../../utils/helpers/qrCodes'; import './QrCodeModal.scss'; +import { BlurredModal } from '../../utils/BlurredModal'; interface QrCodeModalConnectProps extends ShortUrlModalProps { selectedServer: ReachableServer; @@ -37,7 +38,7 @@ const QrCodeModal = ({ shortUrl: { shortUrl }, toggle, isOpen, selectedServer }: }, [ totalSize ]); return ( - + QR code for {shortUrl} @@ -98,7 +99,7 @@ const QrCodeModal = ({ shortUrl: { shortUrl }, toggle, isOpen, selectedServer }:
{size}x{size}
-
+ ); }; diff --git a/src/tags/helpers/DeleteTagConfirmModal.tsx b/src/tags/helpers/DeleteTagConfirmModal.tsx index c4ef46ab..dc4d2838 100644 --- a/src/tags/helpers/DeleteTagConfirmModal.tsx +++ b/src/tags/helpers/DeleteTagConfirmModal.tsx @@ -1,8 +1,9 @@ -import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { TagDeletion } from '../reducers/tagDelete'; import { TagModalProps } from '../data'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; interface DeleteTagConfirmModalProps extends TagModalProps { deleteTag: (tag: string) => Promise; @@ -21,7 +22,7 @@ const DeleteTagConfirmModal = ( }; return ( - + Delete tag @@ -39,7 +40,7 @@ const DeleteTagConfirmModal = ( {deleting ? 'Deleting tag...' : 'Delete tag'} - + ); }; diff --git a/src/tags/helpers/EditTagModal.tsx b/src/tags/helpers/EditTagModal.tsx index 7cbd5169..938d8b6d 100644 --- a/src/tags/helpers/EditTagModal.tsx +++ b/src/tags/helpers/EditTagModal.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader, Popover } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader, Popover } from 'reactstrap'; import { ChromePicker } from 'react-color'; import { faPalette as colorIcon } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -10,6 +10,7 @@ import { TagModalProps } from '../data'; import { TagEdition } from '../reducers/tagEdit'; import { Result } from '../../utils/Result'; import { ShlinkApiError } from '../../api/ShlinkApiError'; +import { BlurredModal } from '../../utils/BlurredModal'; import './EditTagModal.scss'; interface EditTagModalProps extends TagModalProps { @@ -31,7 +32,7 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( .catch(() => {})); return ( - +
Edit tag @@ -68,7 +69,7 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( -
+ ); }; diff --git a/src/utils/BlurredModal.scss b/src/utils/BlurredModal.scss new file mode 100644 index 00000000..66d4e435 --- /dev/null +++ b/src/utils/BlurredModal.scss @@ -0,0 +1,11 @@ +@import './base'; + +@media (min-width: $smMin) { + #root { + transition: filter 300ms; + } + + .with-modal #root { + filter: blur(1.5px); + } +} diff --git a/src/utils/BlurredModal.tsx b/src/utils/BlurredModal.tsx new file mode 100644 index 00000000..62f68373 --- /dev/null +++ b/src/utils/BlurredModal.tsx @@ -0,0 +1,12 @@ +import { FC } from 'react'; +import { ModalProps, Modal } from 'reactstrap'; // eslint-disable-line import/named +import './BlurredModal.scss'; + +const onEnter = () => document.body.classList.add('with-modal'); +const onExit = () => document.body.classList.remove('with-modal'); + +export const BlurredModal: FC = ({ children, ...rest }) => ( + + {children} + +); diff --git a/src/visits/helpers/MapModal.tsx b/src/visits/helpers/MapModal.tsx index ae57ed12..4d29be2a 100644 --- a/src/visits/helpers/MapModal.tsx +++ b/src/visits/helpers/MapModal.tsx @@ -1,8 +1,9 @@ import { FC } from 'react'; -import { Modal, ModalBody } from 'reactstrap'; +import { ModalBody } from 'reactstrap'; import { MapContainer, TileLayer, Marker, Popup, MapContainerProps } from 'react-leaflet'; import { prop } from 'ramda'; import { CityStats } from '../types'; +import { BlurredModal } from '../../utils/BlurredModal'; import './MapModal.scss'; interface MapModalProps { @@ -36,7 +37,7 @@ const calculateMapProps = (locations: CityStats[]): MapContainerProps => { }; const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => ( - +

{title} @@ -51,7 +52,7 @@ const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => ( ))} - + ); export default MapModal; diff --git a/test/servers/DeleteServerModal.test.tsx b/test/servers/DeleteServerModal.test.tsx index 14eed177..fc844b32 100644 --- a/test/servers/DeleteServerModal.test.tsx +++ b/test/servers/DeleteServerModal.test.tsx @@ -1,9 +1,10 @@ import { shallow, ShallowWrapper } from 'enzyme'; -import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; +import { ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { History } from 'history'; import { Mock } from 'ts-mockery'; import DeleteServerModal from '../../src/servers/DeleteServerModal'; import { ServerWithId } from '../../src/servers/data'; +import { BlurredModal } from '../../src/utils/BlurredModal'; describe('', () => { let wrapper: ShallowWrapper; @@ -27,7 +28,7 @@ describe('', () => { afterEach(jest.clearAllMocks); it('renders a modal window', () => { - expect(wrapper.find(Modal)).toHaveLength(1); + expect(wrapper.find(BlurredModal)).toHaveLength(1); expect(wrapper.find(ModalHeader)).toHaveLength(1); expect(wrapper.find(ModalBody)).toHaveLength(1); expect(wrapper.find(ModalFooter)).toHaveLength(1); diff --git a/test/short-urls/helpers/EditMetaModal.test.tsx b/test/short-urls/helpers/EditMetaModal.test.tsx index b5553125..b06f2a40 100644 --- a/test/short-urls/helpers/EditMetaModal.test.tsx +++ b/test/short-urls/helpers/EditMetaModal.test.tsx @@ -71,7 +71,7 @@ describe('', () => { it.each([ [ '.btn-link', 'onClick' ], - [ 'Modal', 'toggle' ], + [ 'BlurredModal', 'toggle' ], [ 'ModalHeader', 'toggle' ], ])('resets meta when modal is toggled in any way', (componentToFind, propToCall) => { const wrapper = createWrapper({ saving: false, error: false }); diff --git a/test/short-urls/helpers/EditShortUrlModal.test.tsx b/test/short-urls/helpers/EditShortUrlModal.test.tsx index 2ab14c4b..0400d379 100644 --- a/test/short-urls/helpers/EditShortUrlModal.test.tsx +++ b/test/short-urls/helpers/EditShortUrlModal.test.tsx @@ -67,7 +67,7 @@ describe('', () => { it.each([ [ '[color="link"]', 'onClick' ], - [ 'Modal', 'toggle' ], + [ 'BlurredModal', 'toggle' ], [ 'ModalHeader', 'toggle' ], ])('toggles modal with different mechanisms', (componentToFind, propToCall) => { const wrapper = createWrapper({}, { saving: false, error: false }); diff --git a/test/short-urls/helpers/EditTagsModal.test.tsx b/test/short-urls/helpers/EditTagsModal.test.tsx index 3da11f62..bbff8bb7 100644 --- a/test/short-urls/helpers/EditTagsModal.test.tsx +++ b/test/short-urls/helpers/EditTagsModal.test.tsx @@ -1,10 +1,10 @@ import { shallow, ShallowWrapper } from 'enzyme'; -import { Modal } from 'reactstrap'; import { Mock } from 'ts-mockery'; import createEditTagsModal from '../../../src/short-urls/helpers/EditTagsModal'; import { ShortUrl } from '../../../src/short-urls/data'; import { ShortUrlTags } from '../../../src/short-urls/reducers/shortUrlTags'; import { OptionalString } from '../../../src/utils/utils'; +import { BlurredModal } from '../../../src/utils/BlurredModal'; describe('', () => { let wrapper: ShallowWrapper; @@ -98,7 +98,7 @@ describe('', () => { saving: false, error: false, }); - const modal = wrapper.find(Modal); + const modal = wrapper.find(BlurredModal); modal.simulate('closed'); expect(editShortUrlTags).not.toHaveBeenCalled(); diff --git a/test/short-urls/helpers/QrCodeModal.test.tsx b/test/short-urls/helpers/QrCodeModal.test.tsx index d84b5572..67089d06 100644 --- a/test/short-urls/helpers/QrCodeModal.test.tsx +++ b/test/short-urls/helpers/QrCodeModal.test.tsx @@ -1,12 +1,13 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { ExternalLink } from 'react-external-link'; -import { Modal, ModalBody, ModalHeader, Row } from 'reactstrap'; +import { ModalBody, ModalHeader, Row } from 'reactstrap'; import { Mock } from 'ts-mockery'; import QrCodeModal from '../../../src/short-urls/helpers/QrCodeModal'; import { ShortUrl } from '../../../src/short-urls/data'; import { ReachableServer } from '../../../src/servers/data'; import { CopyToClipboardIcon } from '../../../src/utils/CopyToClipboardIcon'; import { DropdownBtn } from '../../../src/utils/DropdownBtn'; +import { BlurredModal } from '../../../src/utils/BlurredModal'; describe('', () => { let wrapper: ShallowWrapper; @@ -80,7 +81,7 @@ describe('', () => { expect(wrapper.find('.mt-2').text()).toEqual(`${size}x${size}`); expect(wrapper.find('label').at(0).text()).toEqual(`Size: ${size}px`); expect(wrapper.find('label').at(1).text()).toEqual(`Margin: ${margin}px`); - expect(wrapper.find(Modal).prop('size')).toEqual(modalSize); + expect(wrapper.find(BlurredModal).prop('size')).toEqual(modalSize); }); it.each([ diff --git a/test/tags/helpers/DeleteTagConfirmModal.test.tsx b/test/tags/helpers/DeleteTagConfirmModal.test.tsx index 866dadce..090e31e4 100644 --- a/test/tags/helpers/DeleteTagConfirmModal.test.tsx +++ b/test/tags/helpers/DeleteTagConfirmModal.test.tsx @@ -1,7 +1,8 @@ import { shallow, ShallowWrapper } from 'enzyme'; -import { Modal, ModalBody, ModalFooter } from 'reactstrap'; +import { ModalBody, ModalFooter } from 'reactstrap'; import DeleteTagConfirmModal from '../../../src/tags/helpers/DeleteTagConfirmModal'; import { TagDeletion } from '../../../src/tags/reducers/tagDelete'; +import { BlurredModal } from '../../../src/utils/BlurredModal'; describe('', () => { let wrapper: ShallowWrapper; @@ -68,7 +69,7 @@ describe('', () => { it('does no further actions when modal is closed without deleting tag', () => { wrapper = createWrapper({ error: false, deleting: false }); - const modal = wrapper.find(Modal); + const modal = wrapper.find(BlurredModal); modal.simulate('closed'); expect(deleteTag).not.toHaveBeenCalled(); diff --git a/test/visits/helpers/MapModal.test.tsx b/test/visits/helpers/MapModal.test.tsx index 9c286b11..da6c18ec 100644 --- a/test/visits/helpers/MapModal.test.tsx +++ b/test/visits/helpers/MapModal.test.tsx @@ -1,8 +1,8 @@ import { shallow, ShallowWrapper } from 'enzyme'; -import { Modal } from 'reactstrap'; import { Marker, Popup } from 'react-leaflet'; import MapModal from '../../../src/visits/helpers/MapModal'; import { CityStats } from '../../../src/visits/types'; +import { BlurredModal } from '../../../src/utils/BlurredModal'; describe('', () => { let wrapper: ShallowWrapper; @@ -33,7 +33,7 @@ describe('', () => { afterEach(() => wrapper.unmount()); it('renders modal with provided props', () => { - const modal = wrapper.find(Modal); + const modal = wrapper.find(BlurredModal); const header = wrapper.find('.map-modal__modal-title'); expect(modal.prop('toggle')).toEqual(toggle);