diff --git a/public/res/ic/outlined/external.svg b/public/res/ic/outlined/external.svg index 92b007c..adade1b 100644 --- a/public/res/ic/outlined/external.svg +++ b/public/res/ic/outlined/external.svg @@ -1,12 +1,4 @@ - - - - - - - - - - + + + diff --git a/src/app/atoms/modal/RawModal.jsx b/src/app/atoms/modal/RawModal.jsx index 306d7d1..450be0e 100644 --- a/src/app/atoms/modal/RawModal.jsx +++ b/src/app/atoms/modal/RawModal.jsx @@ -42,7 +42,6 @@ function RawModal({ shouldCloseOnEsc={closeFromOutside} shouldCloseOnOverlayClick={closeFromOutside} shouldReturnFocusAfterClose={false} - closeTimeoutMS={300} > {children} diff --git a/src/app/atoms/modal/RawModal.scss b/src/app/atoms/modal/RawModal.scss index 72a64d7..8045875 100644 --- a/src/app/atoms/modal/RawModal.scss +++ b/src/app/atoms/modal/RawModal.scss @@ -1,27 +1,3 @@ -.ReactModal__Overlay { - opacity: 0; - transition: opacity 200ms var(--fluid-slide-up); -} -.ReactModal__Overlay--after-open{ - opacity: 1; -} -.ReactModal__Overlay--before-close{ - opacity: 0; -} - -.ReactModal__Content { - transform: translateY(100%); - transition: transform 200ms var(--fluid-slide-up); -} - -.ReactModal__Content--after-open{ - transform: translateY(0); -} - -.ReactModal__Content--before-close{ - transform: translateY(100%); -} - .raw-modal { --small-modal-width: 525px; --medium-modal-width: 712px; @@ -60,4 +36,31 @@ height: 100%; background-color: var(--bg-overlay); } +} + +.ReactModal__Overlay { + animation: raw-modal--overlay 150ms; +} + +.ReactModal__Content { + animation: raw-modal--content 150ms; +} + +@keyframes raw-modal--content { + 0% { + transform: translateY(100px); + opacity: .5; + } + 100% { + transform: translateY(0); + opacity: 1; + } +} +@keyframes raw-modal--overlay { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } } \ No newline at end of file diff --git a/src/app/molecules/image-lightbox/ImageLightbox.jsx b/src/app/molecules/image-lightbox/ImageLightbox.jsx new file mode 100644 index 0000000..c1c45db --- /dev/null +++ b/src/app/molecules/image-lightbox/ImageLightbox.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import './ImageLightbox.scss'; +import FileSaver from 'file-saver'; + +import Text from '../../atoms/text/Text'; +import RawModal from '../../atoms/modal/RawModal'; +import IconButton from '../../atoms/button/IconButton'; + +import DownloadSVG from '../../../../public/res/ic/outlined/download.svg'; +import ExternalSVG from '../../../../public/res/ic/outlined/external.svg'; + +function ImageLightbox({ + url, alt, isOpen, onRequestClose, +}) { + const handleDownload = () => { + FileSaver.saveAs(url, alt); + }; + + return ( + +
+ {alt} + window.open(url)} size="small" src={ExternalSVG} /> + +
+
+ {alt} +
+ + ); +} + +ImageLightbox.propTypes = { + url: PropTypes.string.isRequired, + alt: PropTypes.string.isRequired, + isOpen: PropTypes.bool.isRequired, + onRequestClose: PropTypes.func.isRequired, +}; + +export default ImageLightbox; diff --git a/src/app/molecules/image-lightbox/ImageLightbox.scss b/src/app/molecules/image-lightbox/ImageLightbox.scss new file mode 100644 index 0000000..5a900b9 --- /dev/null +++ b/src/app/molecules/image-lightbox/ImageLightbox.scss @@ -0,0 +1,50 @@ +@use '../../partials/flex'; +@use '../../partials/text'; + +.image-lightbox__modal { + box-shadow: none; + width: unset; + gap: var(--sp-normal); + + border-radius: 0; + pointer-events: none; + + & .text { + color: white; + } + & .ic-raw { + background-color: white; + } +} + +.image-lightbox__overlay { + background-color: var(--bg-overlay-low); +} + + +.image-lightbox__header > *, +.image-lightbox__content > * { + pointer-events: all; +} +.image-lightbox__header { + display: flex; + align-items: center; + + & > .text { + @extend .cp-fx__item-one; + @extend .cp-txt__ellipsis; + } +} +.image-lightbox__content { + display: flex; + justify-content: center; + max-height: 90vh; + + & img { + background-color: black; + object-fit: contain; + max-width: 100%; + max-height: 100%; + border-radius: var(--bo-radius); + } +} \ No newline at end of file diff --git a/src/app/molecules/media/Media.jsx b/src/app/molecules/media/Media.jsx index d7ba385..e2b6177 100644 --- a/src/app/molecules/media/Media.jsx +++ b/src/app/molecules/media/Media.jsx @@ -8,6 +8,7 @@ import { BlurhashCanvas } from 'react-blurhash'; import Text from '../../atoms/text/Text'; import IconButton from '../../atoms/button/IconButton'; import Spinner from '../../atoms/spinner/Spinner'; +import ImageLightbox from '../image-lightbox/ImageLightbox'; import DownloadSVG from '../../../../public/res/ic/outlined/download.svg'; import ExternalSVG from '../../../../public/res/ic/outlined/external.svg'; @@ -124,6 +125,7 @@ function Image({ }) { const [url, setUrl] = useState(null); const [blur, setBlur] = useState(true); + const [lightbox, setLightbox] = useState(false); useEffect(() => { let unmounted = false; @@ -138,14 +140,42 @@ function Image({ }; }, []); + const toggleLightbox = () => { + if (!url) return; + setLightbox(!lightbox); + }; + return ( -
- -
- { blurhash && blur && } - { url !== null && setBlur(false)} src={url || link} alt={name} />} + <> +
+
+ { blurhash && blur && } + { url !== null && ( + setBlur(false)} + src={url || link} + alt={name} + /> + )} +
-
+ {url && ( + + )} + ); } Image.defaultProps = { diff --git a/src/app/molecules/media/Media.scss b/src/app/molecules/media/Media.scss index 7c73305..8d98c42 100644 --- a/src/app/molecules/media/Media.scss +++ b/src/app/molecules/media/Media.scss @@ -62,6 +62,13 @@ margin: 0 !important; } } +.image-container { + max-height: 460px; + img { + cursor: pointer; + object-fit: cover; + } +} .video-container { position: relative; diff --git a/src/index.scss b/src/index.scss index 3a4707c..39d0612 100644 --- a/src/index.scss +++ b/src/index.scss @@ -105,7 +105,7 @@ /* shadow and overlay */ --bg-overlay: rgba(0, 0, 0, 20%); - --bg-overlay-low: rgba(0, 0, 0, 85%); + --bg-overlay-low: rgba(0, 0, 0, 50%); --bs-popup: 0 0 16px rgba(0, 0, 0, 10%); @@ -264,7 +264,8 @@ } /* shadow and overlay */ - --bg-overlay: rgba(0, 0, 0, 50%); + --bg-overlay: rgba(0, 0, 0, 60%); + --bg-overlay-low: rgba(0, 0, 0, 80%); --bs-popup: 0 0 16px rgba(0, 0, 0, 25%);