mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-02 13:51:48 +00:00
Added proper blurred background for modals
This commit is contained in:
committed by
Alejandro Celaya
parent
e7466ced18
commit
f97ef8df83
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered>
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered>
|
||||
<ModalHeader toggle={toggle}><span className="text-danger">Remove server</span></ModalHeader>
|
||||
<ModalBody>
|
||||
<p>Are you sure you want to remove <b>{server ? server.name : ''}</b>?</p>
|
||||
@@ -35,7 +36,7 @@ const DeleteServerModal = ({ server, toggle, isOpen, deleteServer, history }: De
|
||||
<button className="btn btn-link" onClick={toggle}>Cancel</button>
|
||||
<button className="btn btn-danger" onClick={() => closeModal()}>Delete</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 }) => (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered size="lg">
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered size="lg">
|
||||
<ModalHeader toggle={toggle}>Info</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>
|
||||
@@ -33,7 +34,7 @@ const InfoModal = ({ isOpen, toggle }: { isOpen: boolean; toggle: () => void })
|
||||
</li>
|
||||
</ul>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
|
||||
const UseExistingIfFoundInfoIcon = () => {
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={close} centered>
|
||||
<BlurredModal isOpen={isOpen} toggle={close} centered>
|
||||
<form onSubmit={handleDeleteUrl}>
|
||||
<ModalHeader toggle={close}>
|
||||
<span className="text-danger">Delete short URL</span>
|
||||
@@ -67,7 +68,7 @@ const DeleteShortUrlModal = (
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={close} centered>
|
||||
<BlurredModal isOpen={isOpen} toggle={close} centered>
|
||||
<ModalHeader toggle={close}>
|
||||
<FontAwesomeIcon icon={infoIcon} id="metaTitleInfo" /> Edit metadata for <ExternalLink href={url} />
|
||||
<UncontrolledTooltip target="metaTitleInfo" placement="bottom">
|
||||
@@ -94,7 +95,7 @@ const EditMetaModal = (
|
||||
<button className="btn btn-primary" type="submit" disabled={saving}>{saving ? 'Saving...' : 'Save'}</button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered size="lg">
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered size="lg">
|
||||
<ModalHeader toggle={toggle}>
|
||||
Edit long URL for <ExternalLink href={url} />
|
||||
</ModalHeader>
|
||||
@@ -49,7 +50,7 @@ const EditShortUrlModal = ({ isOpen, toggle, shortUrl, shortUrlEdition, editShor
|
||||
<Button color="primary" disabled={saving || !hasValue(longUrl)}>{saving ? 'Saving...' : 'Save'}</Button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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<TagsSelectorProps>) => (
|
||||
.catch(() => {});
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered>
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered>
|
||||
<ModalHeader toggle={toggle}>
|
||||
Edit tags for <ExternalLink href={url} />
|
||||
</ModalHeader>
|
||||
@@ -46,7 +47,7 @@ const EditTagsModal = (TagsSelector: FC<TagsSelectorProps>) => (
|
||||
{saving ? 'Saving tags...' : 'Save tags'}
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered size={modalSize}>
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered size={modalSize}>
|
||||
<ModalHeader toggle={toggle}>
|
||||
QR code for <ExternalLink href={shortUrl}>{shortUrl}</ExternalLink>
|
||||
</ModalHeader>
|
||||
@@ -98,7 +99,7 @@ const QrCodeModal = ({ shortUrl: { shortUrl }, toggle, isOpen, selectedServer }:
|
||||
<div className="mt-2">{size}x{size}</div>
|
||||
</div>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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<void>;
|
||||
@@ -21,7 +22,7 @@ const DeleteTagConfirmModal = (
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal toggle={toggle} isOpen={isOpen} centered>
|
||||
<BlurredModal toggle={toggle} isOpen={isOpen} centered>
|
||||
<ModalHeader toggle={toggle}>
|
||||
<span className="text-danger">Delete tag</span>
|
||||
</ModalHeader>
|
||||
@@ -39,7 +40,7 @@ const DeleteTagConfirmModal = (
|
||||
{deleting ? 'Deleting tag...' : 'Delete tag'}
|
||||
</button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<Modal isOpen={isOpen} toggle={toggle} centered onClosed={hideColorPicker}>
|
||||
<BlurredModal isOpen={isOpen} toggle={toggle} centered onClosed={hideColorPicker}>
|
||||
<form onSubmit={saveTag}>
|
||||
<ModalHeader toggle={toggle}>Edit tag</ModalHeader>
|
||||
<ModalBody>
|
||||
@@ -68,7 +69,7 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
|
||||
<button type="submit" className="btn btn-primary" disabled={editing}>{editing ? 'Saving...' : 'Save'}</button>
|
||||
</ModalFooter>
|
||||
</form>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
11
src/utils/BlurredModal.scss
Normal file
11
src/utils/BlurredModal.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
@import './base';
|
||||
|
||||
@media (min-width: $smMin) {
|
||||
#root {
|
||||
transition: filter 300ms;
|
||||
}
|
||||
|
||||
.with-modal #root {
|
||||
filter: blur(1.5px);
|
||||
}
|
||||
}
|
||||
12
src/utils/BlurredModal.tsx
Normal file
12
src/utils/BlurredModal.tsx
Normal file
@@ -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<ModalProps> = ({ children, ...rest }) => (
|
||||
<Modal {...rest} modalTransition={{ onEnter, onExit }}>
|
||||
{children}
|
||||
</Modal>
|
||||
);
|
||||
@@ -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) => (
|
||||
<Modal toggle={toggle} isOpen={isOpen} className="map-modal__modal" contentClassName="map-modal__modal-content">
|
||||
<BlurredModal toggle={toggle} isOpen={isOpen} className="map-modal__modal" contentClassName="map-modal__modal-content">
|
||||
<ModalBody className="map-modal__modal-body">
|
||||
<h3 className="map-modal__modal-title">
|
||||
{title}
|
||||
@@ -51,7 +52,7 @@ const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProps) => (
|
||||
))}
|
||||
</MapContainer>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
</BlurredModal>
|
||||
);
|
||||
|
||||
export default MapModal;
|
||||
|
||||
Reference in New Issue
Block a user