From 64fc79cbc22f452d6faa22a181939d1384f1d0c2 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 29 Nov 2024 08:50:08 +0100 Subject: [PATCH] [Glitch] Change design of modal loading and error screens in web UI Port 7f2cfcccab8d81feca98328e371373a9dd7f7c12 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/components/gif.tsx | 22 +++ .../ui/components/bundle_column_error.jsx | 53 +------- .../ui/components/bundle_modal_error.jsx | 56 -------- .../features/ui/components/modal_loading.jsx | 18 --- .../ui/components/modal_placeholder.tsx | 61 +++++++++ .../features/ui/components/modal_root.jsx | 13 +- .../flavours/glitch/styles/components.scss | 127 ++++-------------- 7 files changed, 117 insertions(+), 233 deletions(-) create mode 100644 app/javascript/flavours/glitch/components/gif.tsx delete mode 100644 app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx delete mode 100644 app/javascript/flavours/glitch/features/ui/components/modal_loading.jsx create mode 100644 app/javascript/flavours/glitch/features/ui/components/modal_placeholder.tsx diff --git a/app/javascript/flavours/glitch/components/gif.tsx b/app/javascript/flavours/glitch/components/gif.tsx new file mode 100644 index 00000000000000..be2742c0d49395 --- /dev/null +++ b/app/javascript/flavours/glitch/components/gif.tsx @@ -0,0 +1,22 @@ +import { useHovering } from '@/hooks/useHovering'; +import { autoPlayGif } from 'flavours/glitch/initial_state'; + +export const GIF: React.FC<{ + src: string; + staticSrc: string; + className: string; + animate?: boolean; +}> = ({ src, staticSrc, className, animate = autoPlayGif }) => { + const { hovering, handleMouseEnter, handleMouseLeave } = useHovering(animate); + + return ( + + ); +}; diff --git a/app/javascript/flavours/glitch/features/ui/components/bundle_column_error.jsx b/app/javascript/flavours/glitch/features/ui/components/bundle_column_error.jsx index e717960d3b0736..8578cb299b9acc 100644 --- a/app/javascript/flavours/glitch/features/ui/components/bundle_column_error.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/bundle_column_error.jsx @@ -9,58 +9,7 @@ import { Link } from 'react-router-dom'; import { Button } from 'flavours/glitch/components/button'; import Column from 'flavours/glitch/components/column'; -import { autoPlayGif } from 'flavours/glitch/initial_state'; - -class GIF extends PureComponent { - - static propTypes = { - src: PropTypes.string.isRequired, - staticSrc: PropTypes.string.isRequired, - className: PropTypes.string, - animate: PropTypes.bool, - }; - - static defaultProps = { - animate: autoPlayGif, - }; - - state = { - hovering: false, - }; - - handleMouseEnter = () => { - const { animate } = this.props; - - if (!animate) { - this.setState({ hovering: true }); - } - }; - - handleMouseLeave = () => { - const { animate } = this.props; - - if (!animate) { - this.setState({ hovering: false }); - } - }; - - render () { - const { src, staticSrc, className, animate } = this.props; - const { hovering } = this.state; - - return ( - - ); - } - -} +import { GIF } from 'flavours/glitch/components/gif'; class CopyButton extends PureComponent { diff --git a/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx b/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx deleted file mode 100644 index d1c9e368838719..00000000000000 --- a/app/javascript/flavours/glitch/features/ui/components/bundle_modal_error.jsx +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import { PureComponent } from 'react'; - -import { defineMessages, injectIntl } from 'react-intl'; - -import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react'; - -import { IconButton } from '../../../components/icon_button'; - -const messages = defineMessages({ - error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' }, - retry: { id: 'bundle_modal_error.retry', defaultMessage: 'Try again' }, - close: { id: 'bundle_modal_error.close', defaultMessage: 'Close' }, -}); - -class BundleModalError extends PureComponent { - - static propTypes = { - onRetry: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - handleRetry = () => { - this.props.onRetry(); - }; - - render () { - const { onClose, intl: { formatMessage } } = this.props; - - // Keep the markup in sync with - // (make sure they have the same dimensions) - return ( -
-
- - {formatMessage(messages.error)} -
- -
-
- -
-
-
- ); - } - -} - -export default injectIntl(BundleModalError); diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_loading.jsx b/app/javascript/flavours/glitch/features/ui/components/modal_loading.jsx deleted file mode 100644 index 7d19e73513336d..00000000000000 --- a/app/javascript/flavours/glitch/features/ui/components/modal_loading.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import { LoadingIndicator } from '../../../components/loading_indicator'; - -// Keep the markup in sync with -// (make sure they have the same dimensions) -const ModalLoading = () => ( -
-
- -
-
-
-
-
-
-); - -export default ModalLoading; diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_placeholder.tsx b/app/javascript/flavours/glitch/features/ui/components/modal_placeholder.tsx new file mode 100644 index 00000000000000..826c3007e60427 --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/components/modal_placeholder.tsx @@ -0,0 +1,61 @@ +import { useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import { Button } from 'flavours/glitch/components/button'; +import { GIF } from 'flavours/glitch/components/gif'; +import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator'; + +export const ModalPlaceholder: React.FC<{ + loading: boolean; + onClose: (arg0: string | undefined, arg1: boolean) => void; + onRetry?: () => void; +}> = ({ loading, onClose, onRetry }) => { + const handleClose = useCallback(() => { + onClose(undefined, false); + }, [onClose]); + + const handleRetry = useCallback(() => { + if (onRetry) onRetry(); + }, [onRetry]); + + return ( +
+ {loading ? ( + + ) : ( +
+ + +
+

+ +

+ +
+ + +
+
+
+ )} +
+ ); +}; diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx index b437ef10eb7c6c..729ae67497cc2e 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.jsx @@ -27,7 +27,6 @@ import BundleContainer from '../containers/bundle_container'; import ActionsModal from './actions_modal'; import AudioModal from './audio_modal'; import { BoostModal } from './boost_modal'; -import BundleModalError from './bundle_modal_error'; import { ConfirmationModal, ConfirmDeleteStatusModal, @@ -44,7 +43,7 @@ import { FavouriteModal } from './favourite_modal'; import FocalPointModal from './focal_point_modal'; import ImageModal from './image_modal'; import MediaModal from './media_modal'; -import ModalLoading from './modal_loading'; +import { ModalPlaceholder } from './modal_placeholder'; import VideoModal from './video_modal'; export const MODAL_COMPONENTS = { @@ -109,14 +108,16 @@ export default class ModalRoot extends PureComponent { this.setState({ backgroundColor: color }); }; - renderLoading = modalId => () => { - return ['MEDIA', 'VIDEO', 'BOOST', 'FAVOURITE', 'DOODLE', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? : null; + renderLoading = () => { + const { onClose } = this.props; + + return ; }; renderError = (props) => { const { onClose } = this.props; - return ; + return ; }; handleClose = (ignoreFocus = false) => { @@ -141,7 +142,7 @@ export default class ModalRoot extends PureComponent { {visible && ( <> - + {(SpecificComponent) => { const ref = typeof SpecificComponent !== 'function' ? this.setModalRef : undefined; return ; diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss index 34354ee1d60544..fb99806ff4c738 100644 --- a/app/javascript/flavours/glitch/styles/components.scss +++ b/app/javascript/flavours/glitch/styles/components.scss @@ -6306,119 +6306,44 @@ a.status-card { } } -.onboarding-modal, -.error-modal, -.embed-modal { - background: $ui-secondary-color; - color: $inverted-text-color; - border-radius: 8px; - overflow: hidden; - display: flex; +.modal-placeholder { + width: 588px; + min-height: 478px; flex-direction: column; -} - -.error-modal__body { - height: 80vh; - width: 80vw; - max-width: 520px; - max-height: 420px; - position: relative; + background: var(--modal-background-color); + backdrop-filter: var(--background-filter); + border: 1px solid var(--modal-border-color); + border-radius: 16px; - & > div { - position: absolute; - top: 0; - inset-inline-start: 0; - width: 100%; - height: 100%; - box-sizing: border-box; - padding: 25px; - flex-direction: column; - align-items: center; - justify-content: center; + &__error { + padding: 24px; display: flex; - opacity: 0; - user-select: text; - } -} - -.error-modal__body { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; -} - -.onboarding-modal__paginator, -.error-modal__footer { - flex: 0 0 auto; - background: darken($ui-secondary-color, 8%); - display: flex; - padding: 25px; - - & > div { - min-width: 33px; - } - - .onboarding-modal__nav, - .error-modal__nav { - color: $lighter-text-color; - border: 0; - font-size: 14px; - font-weight: 500; - padding: 10px 25px; - line-height: inherit; - height: auto; - margin: -10px; - border-radius: 4px; - background-color: transparent; + align-items: center; + flex-direction: column; - &:hover, - &:focus, - &:active { - color: darken($lighter-text-color, 4%); - background-color: darken($ui-secondary-color, 16%); + &__image { + width: 70%; + max-width: 350px; } - &.onboarding-modal__done, - &.onboarding-modal__next { - color: $inverted-text-color; + &__message { + text-align: center; + text-wrap: balance; + font-size: 14px; + line-height: 20px; + letter-spacing: 0.25px; - &:hover, - &:focus, - &:active { - color: lighten($inverted-text-color, 4%); + &__actions { + margin-top: 24px; + display: flex; + gap: 10px; + align-items: center; + justify-content: center; } } } } -.error-modal__footer { - justify-content: center; -} - -.display-case { - text-align: center; - font-size: 15px; - margin-bottom: 15px; - - &__label { - font-weight: 500; - color: $inverted-text-color; - margin-bottom: 5px; - text-transform: uppercase; - font-size: 12px; - } - - &__case { - background: $ui-base-color; - color: $secondary-text-color; - font-weight: 500; - padding: 10px; - border-radius: 4px; - } -} - .safety-action-modal { width: 600px; flex-direction: column;