From 8b2396303c860444edaeecb4729c8cab84132ffb Mon Sep 17 00:00:00 2001 From: Dmitry Yudakov Date: Fri, 10 Feb 2023 16:33:49 +0200 Subject: [PATCH] feat: align elements in different screen sections We support several screen elements that need to be aligned together: maximized elements on top-left (like video/screenshare/plugins), top-right elements (voice and text chats) and previews on bottom-right (video/plugins/screencast). Video/screencast/plugins can also move between top-left and bottom-right - the important thing here is to not make them detach from parent when moving between screen sections - and it's pretty challenging to satisfy all this. Current solution uses flexbox for SectionedScreen component and SectionedScreenPortal elements (used as Portal for all abovementioned). SectionedScreenPortal appends a child to SectionedScreen using proper class based on target section. Different sections' classes have slightly different styles/order and additional logic is applied to force the flexbox break into 2 rows if both top-right and bottom-right elements are detected. We use ":has" selector that currently has relatively limited support - it currently works on Chrome/Brave, but on Firefox you still need to activate it with config. There's a fallback option allowing almost same functionality without the ability to use full height of the screen when only top-left and/or top-right elements are present - they're at 60% height then. Using flexbox is a working though not perfect solution as it's not really intended for such layout. I tried display:grid but it becomes even more complex to manipulate it in flexible enough manner based on content. My original approach was with 2 nested containers - one for top/bottom row and one left/right for each row - it was working nicely as a layout but moving between sections triggers child detach, which causes interruptions with iframe videos, etc. It's probably possibly to use shadow DOM for translating screen element into different sections but I doubt it's possible using only css. Another planned approach was having React Context used by SectionedScreen and SectionedScreenPortals for sharing info between them and applying different styles and helper elements based on that, but it seems css with :has selector allows to satisfy all our current requirements. Some relatively new css selectors like :only-child, :only-of-type, :nth-of-type could also be of use in future. Some useful links: https://ishadeed.com/article/conditional-css/ https://tobiasahlin.com/blog/flexbox-break-to-new-row/ https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout Shadow DOM: https://github.com/whatwg/html/issues/5484#issuecomment-620481794 - nice and simple example https://stackoverflow.com/questions/42274721/shadow-dom-and-reactjs https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow --- packages/app/src/scenes/AppLayers.tsx | 4 +- .../ObjectPluginPage/ObjectPluginPage.tsx | 18 ++- .../ScreenShareWidget.styled.ts | 79 ---------- .../ScreenShareWidget/ScreenShareWidget.tsx | 10 +- .../TextChatWidget/TextChatWidget.styled.ts | 13 +- .../pages/TextChatWidget/TextChatWidget.tsx | 66 ++++----- .../VoiceChatWidget/VoiceChatWidget.styled.ts | 13 +- .../pages/VoiceChatWidget/VoiceChatWidget.tsx | 42 +++--- packages/app/src/static/styles/main.scss | 10 ++ packages/app/src/static/styles/variables.css | 1 - packages/ui-kit/src/atoms/Portal/Portal.ts | 3 + .../SectionedScreen/SectionedScreen.styled.ts | 138 ++++++------------ .../atoms/SectionedScreen/SectionedScreen.tsx | 108 +------------- .../SectionedScreenPortal.tsx | 25 ++++ .../src/atoms/SectionedScreenPortal/index.ts | 1 + packages/ui-kit/src/atoms/index.ts | 1 + packages/ui-kit/src/enums/index.ts | 1 + .../ui-kit/src/enums/screenSections.enum.ts | 5 + .../WindowPanel/WindowPanel.styled.ts | 21 ++- 19 files changed, 196 insertions(+), 363 deletions(-) delete mode 100644 packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.styled.ts create mode 100644 packages/ui-kit/src/atoms/SectionedScreenPortal/SectionedScreenPortal.tsx create mode 100644 packages/ui-kit/src/atoms/SectionedScreenPortal/index.ts create mode 100644 packages/ui-kit/src/enums/screenSections.enum.ts diff --git a/packages/app/src/scenes/AppLayers.tsx b/packages/app/src/scenes/AppLayers.tsx index 369558d7c..fe451b948 100644 --- a/packages/app/src/scenes/AppLayers.tsx +++ b/packages/app/src/scenes/AppLayers.tsx @@ -28,7 +28,9 @@ const AppLayers: FC = (props) => {
- +
+ +
{renderUnity && }
{children}
diff --git a/packages/app/src/scenes/object/pages/ObjectPluginPage/ObjectPluginPage.tsx b/packages/app/src/scenes/object/pages/ObjectPluginPage/ObjectPluginPage.tsx index 4e01bb9ba..38f2e27cf 100644 --- a/packages/app/src/scenes/object/pages/ObjectPluginPage/ObjectPluginPage.tsx +++ b/packages/app/src/scenes/object/pages/ObjectPluginPage/ObjectPluginPage.tsx @@ -1,7 +1,13 @@ import {FC, useEffect} from 'react'; import {observer} from 'mobx-react-lite'; import {useTheme} from 'styled-components'; -import {ErrorBoundary, SectionPortal, Text, WindowPanel} from '@momentum-xyz/ui-kit'; +import { + ErrorBoundary, + ScreenSectionsEnum, + SectionedScreenPortal, + Text, + WindowPanel +} from '@momentum-xyz/ui-kit'; import {useTranslation} from 'react-i18next'; import {toast} from 'react-toastify'; import { @@ -98,9 +104,11 @@ const PluginInnerWrapper = ({ const {content, objectView} = plugin.usePlugin(pluginProps); return !pluginLoader.isError ? ( - {content ? ( @@ -121,7 +129,7 @@ const PluginInnerWrapper = ({ ) : ( )} - + ) : ( ); diff --git a/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.styled.ts b/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.styled.ts deleted file mode 100644 index 5e977ae35..000000000 --- a/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.styled.ts +++ /dev/null @@ -1,79 +0,0 @@ -import styled from 'styled-components'; - -export const InnerContainer = styled.div` - display: flex; - height: 100%; - width: 100%; - min-height: 0; - flex-direction: column; - align-items: flex-start; -`; - -// export const Container = styled.div` -// border-radius: 10px; -// pointer-events: all; - -// padding-top: 60px; -// width: 100%; -// height: 100%; -// `; - -export const Container = styled.div` - // position: absolute; - display: flex; - aspect-ratio: 16 / 9; - // width: 96%; - // height: 90%; - pointer-events: all; - box-sizing: border-box; - - // top: 2%; - // left: 2%; - margin: 10px; - padding-top: 60px; - border-radius: 10px; - background: ${(props) => props.theme.bg}; - - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - // z-index: calc(var(--dialog-z-index) + 1); - - :not(&.expanded) { - // position: absolute; - flex-direction: column; - min-width: 500px; - min-height: 300px; - // margin: 10px; - // top: unset; - // left: unset; - // right: 20px; - // bottom: 61px; - } -`; - -export const HeaderElement = styled.div` - display: flex; - align-items: center; - justify-content: center; - position: absolute; - padding: 5px 20px; - opacity: 0.8; - - height: 60px; - gap: 20px; - top: 0; - &.left { - left: 0; - gap: 5px; - } - &.right { - right: 0; - } -`; - -export const Title = styled.div` - min-width: 0; -`; -export const SubTitle = styled.div` - min-width: 0; -`; diff --git a/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.tsx b/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.tsx index eb155f379..6ebe2603e 100644 --- a/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.tsx +++ b/packages/app/src/scenes/widgets/pages/ScreenShareWidget/ScreenShareWidget.tsx @@ -1,6 +1,6 @@ import React, {FC, useCallback, useEffect} from 'react'; import {observer} from 'mobx-react-lite'; -import {SectionPortal, WindowPanel} from '@momentum-xyz/ui-kit'; +import {ScreenSectionsEnum, SectionedScreenPortal, WindowPanel} from '@momentum-xyz/ui-kit'; import {useTranslation} from 'react-i18next'; import {useStore} from 'shared/hooks'; @@ -41,9 +41,11 @@ const ScreenShareWidget: FC = () => { }; return ( - { )} - + ); }; diff --git a/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.styled.ts b/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.styled.ts index 87e410b63..7fac31589 100644 --- a/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.styled.ts +++ b/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.styled.ts @@ -1,22 +1,13 @@ import {rgba} from 'polished'; import styled from 'styled-components'; -export const Modal = styled.div` - display: flex; - // margin: 10px; - // box-sizing: border-box; - // position: absolute; - // right: 0; - // top: 0; - // margin: 20px; -`; - export const Container = styled.div` background: ${(props) => props.theme.bg && rgba(props.theme.bg, 0.75)}; border-radius: 10px; overflow: hidden; width: 280px; - height: 584px; + max-height: 584px; + height: 100%; display: flex; flex-direction: column; diff --git a/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.tsx b/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.tsx index f40c5286a..810512fe3 100644 --- a/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.tsx +++ b/packages/app/src/scenes/widgets/pages/TextChatWidget/TextChatWidget.tsx @@ -1,5 +1,11 @@ import React, {FC, useEffect} from 'react'; -import {Heading, IconSvg, SectionPortal, SvgButton} from '@momentum-xyz/ui-kit'; +import { + Heading, + IconSvg, + ScreenSectionsEnum, + SectionedScreenPortal, + SvgButton +} from '@momentum-xyz/ui-kit'; import {observer} from 'mobx-react-lite'; import {useTranslation} from 'react-i18next'; @@ -11,10 +17,7 @@ import * as styled from './TextChatWidget.styled'; const TextChatWidget: FC = () => { const {widgetsStore, sessionStore, unityStore} = useStore(); const {unityInstanceStore} = unityStore; - const { - textChatStore - // voiceChatStore - } = widgetsStore; + const {textChatStore} = widgetsStore; const {streamChat} = textChatStore; const {t} = useTranslation(); @@ -28,35 +31,30 @@ const TextChatWidget: FC = () => { }, [sessionStore.user, sessionStore.userId, streamChat, unityStore.worldId]); return ( - - {/* FIXME: Design discussion in order to avoid relation to VoiceChatStore */} - - - - - - - - - - - - - - {streamChat.client && streamChat.currentChannel && ( - unityInstanceStore.changeKeyboardControl(false)} - onBlur={() => unityInstanceStore.changeKeyboardControl(true)} - /> - )} - - - - + + + + + + + + + + + + + + {streamChat.client && streamChat.currentChannel && ( + unityInstanceStore.changeKeyboardControl(false)} + onBlur={() => unityInstanceStore.changeKeyboardControl(true)} + /> + )} + + + ); }; diff --git a/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.styled.ts b/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.styled.ts index 87e410b63..7fac31589 100644 --- a/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.styled.ts +++ b/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.styled.ts @@ -1,22 +1,13 @@ import {rgba} from 'polished'; import styled from 'styled-components'; -export const Modal = styled.div` - display: flex; - // margin: 10px; - // box-sizing: border-box; - // position: absolute; - // right: 0; - // top: 0; - // margin: 20px; -`; - export const Container = styled.div` background: ${(props) => props.theme.bg && rgba(props.theme.bg, 0.75)}; border-radius: 10px; overflow: hidden; width: 280px; - height: 584px; + max-height: 584px; + height: 100%; display: flex; flex-direction: column; diff --git a/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.tsx b/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.tsx index ebc0574f7..34b960368 100644 --- a/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.tsx +++ b/packages/app/src/scenes/widgets/pages/VoiceChatWidget/VoiceChatWidget.tsx @@ -1,7 +1,13 @@ import React, {FC, useCallback, useEffect} from 'react'; import {observer} from 'mobx-react-lite'; import {useTranslation} from 'react-i18next'; -import {Heading, IconSvg, SectionPortal, SvgButton} from '@momentum-xyz/ui-kit'; +import { + Heading, + IconSvg, + ScreenSectionsEnum, + SectionedScreenPortal, + SvgButton +} from '@momentum-xyz/ui-kit'; import {useStore} from 'shared/hooks'; @@ -28,24 +34,22 @@ const VoiceChatWidget: FC = () => { }, [agoraStore, agoraVoiceChatStore.hasJoined, voiceChatStore.dialog]); return ( - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + ); }; diff --git a/packages/app/src/static/styles/main.scss b/packages/app/src/static/styles/main.scss index c9d9b0e26..d41f10f1d 100644 --- a/packages/app/src/static/styles/main.scss +++ b/packages/app/src/static/styles/main.scss @@ -25,6 +25,16 @@ body { z-index: 1; } +#sectioned-screen-container { + width: 100%; + height: calc(100% - 50px); + position: absolute; + top: 0; + left: 0; + z-index: var(--base-z-index); + pointer-events: none; +} + .noScrollIndicator { -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ diff --git a/packages/app/src/static/styles/variables.css b/packages/app/src/static/styles/variables.css index f9663b781..c9afea5ba 100644 --- a/packages/app/src/static/styles/variables.css +++ b/packages/app/src/static/styles/variables.css @@ -95,7 +95,6 @@ --overlay-z-index: 40; --base-z-index: 1; - /* MUSIC PLAYER */ --player-default-color: rgba(255, 255, 255, 0.5); diff --git a/packages/ui-kit/src/atoms/Portal/Portal.ts b/packages/ui-kit/src/atoms/Portal/Portal.ts index c756c272a..00e52eec5 100644 --- a/packages/ui-kit/src/atoms/Portal/Portal.ts +++ b/packages/ui-kit/src/atoms/Portal/Portal.ts @@ -17,6 +17,9 @@ const Portal: FC = ({children, className, parentId, maximized}) if (maximized) { // set flex-grow to 1 to make it fill the parent domContainer.current.style.flexGrow = '1'; + } else { + // set flex-grow to 0 to make it not fill the parent + domContainer.current.style.flexGrow = '0'; } useEffect(() => { diff --git a/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.styled.ts b/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.styled.ts index 0c9773cd8..835766295 100644 --- a/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.styled.ts +++ b/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.styled.ts @@ -1,113 +1,71 @@ import styled from 'styled-components'; -// TODO try css masonry layout +// this should allow debugging the layout even on prod - just set DEBUG=1 in sessionStorage and refresh +const DEBUG = sessionStorage.getItem('DEBUG') !== null; export const Container = styled.div` - display: flex; - flex-direction: column; - width: 100%; - height: calc(100% - 50px); - position: absolute; - top: 0; - left: 0; - z-index: 1; pointer-events: none; -`; - -export const InnerContainer = styled.div` - display: flex; - // width: 100%; - // height: 100%; -`; -export const Section = styled.div` display: flex; - // flex: 1 0 auto; - position: relative; - padding: 10px; + flex-wrap: wrap; + justify-content: flex-end; + align-items: flex-start; gap: 10px; -`; - -export const ContainerG = styled.div` - display: grid; - grid-template-columns: repeat(6, minmax(0, auto)); - grid-template-rows: minmax(0, auto) minmax(0, auto); - grid-gap: 10px; - grid-template-areas: - 'left-top left-top left-top right-top right-top right-top' - 'left-bottom left-bottom left-bottom right-bottom right-bottom right-bottom'; + padding: 10px; width: 100%; - height: calc(100% - 50px); - position: absolute; - top: 0; - left: 0; - z-index: 1; - pointer-events: none; + height: 100%; - .section-screen-item { + .sectioned-screen-top-left { + flex-grow: 1; + order: 1; + } + .sectioned-screen-top-right { + order: 2; + justify-content: end; + } + .sectioned-screen-bottom-right { display: flex; justify-content: end; + order: 10; + align-self: flex-end; } - .left-top:nth-child(1), - .left-bottom:nth-child(1) { - grid-column: 1 / 2; + .sectioned-screen-top-left, + .sectioned-screen-top-right { + height: 60%; } - .left-top:nth-child(2), - .left-bottom:nth-child(2) { - grid-column: 2 / 3; - } - .left-top:nth-child(3), - .left-bottom:nth-child(3) { - grid-column: 3 / 4; + .sectioned-screen-bottom-right { + height: 38%; } - .right-top:nth-child(1), - .right-bottom:nth-child(1) { - grid-column: 6 / 7; - } - .right-top:nth-child(2), - .right-bottom:nth-child(2) { - grid-column: 5 / 6; - } - .right-top:nth-child(3), - .right-bottom:nth-child(3) { - grid-column: 4 / 5; + .sectioned-screen-section-break { + flex-basis: 100%; + height: ${() => (DEBUG ? '2px' : '0')}; + background: ${() => (DEBUG ? 'red' : 'transparent')}; + margin: -5px 0; + order: 5; } - .left-top { - grid-area: left-top; - flex-grow: 1; - } - .right-top { - grid-area: right-top; - } - .left-bottom { - grid-area: left-bottom; + @supports (selector(:has(div))) { + .sectioned-screen-section-break { + display: none; + } + .sectioned-screen-top-left, + .sectioned-screen-top-right { + height: 100%; + } } - .right-bottom { - // grid-column: 2 / 3; - // grid-row: 2 / 3; - grid-area: right-bottom; - } -`; -export const SectionG = styled.div` - // &.top-left { - // grid-column: 1 / 2; - // grid-row: 1 / 2; - // } - // &.top-right { - // grid-column: 2 / 3; - // grid-row: 1 / 2; - // } - // &.bottom-left { - // grid-column: 1 / 2; - // grid-row: 2 / 3; - // } - // &.bottom-right { - // grid-column: 2 / 3; - // grid-row: 2 / 3; - // } + // right now we're ok with having top-left and bottom-right sections on the same row but alighed differently + // if we have top-right and bottom-right, then we need to split them into two rows and limit the top row height + &:has(.sectioned-screen-bottom-right):has(.sectioned-screen-top-right) { + .sectioned-screen-section-break { + display: block; + } + .sectioned-screen-top-left, + .sectioned-screen-top-right { + height: 60%; + } + } `; diff --git a/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.tsx b/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.tsx index babb5e5cb..7ab27143c 100644 --- a/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.tsx +++ b/packages/ui-kit/src/atoms/SectionedScreen/SectionedScreen.tsx @@ -1,109 +1,17 @@ import {FC} from 'react'; -import cn from 'classnames'; - -import {Portal} from '../Portal'; import * as styled from './SectionedScreen.styled'; -// this should allow debugging the layout even on prod - just set DEBUG=1 in sessionStorage and refresh -// const DEBUG = sessionStorage.getItem('DEBUG') !== null; - -export const SectionedScreen: FC = () => { - return ( - - {/* - - - */} - - // - // - // - // - // - // - // - // - // - // - ); -}; +export const SECTIONED_SCREEN_ID = 'sectioned-screen'; -interface SectionPortalPropsInterface { - section: string; - maximized?: boolean; +export interface PropsInterface { + id?: string; } -export const SectionPortal: FC = ({children, section, maximized}) => { + +export const SectionedScreen: FC = ({id = SECTIONED_SCREEN_ID}) => { return ( - - {children} - {/* {children} */} - + +
+ ); }; diff --git a/packages/ui-kit/src/atoms/SectionedScreenPortal/SectionedScreenPortal.tsx b/packages/ui-kit/src/atoms/SectionedScreenPortal/SectionedScreenPortal.tsx new file mode 100644 index 000000000..8a5632809 --- /dev/null +++ b/packages/ui-kit/src/atoms/SectionedScreenPortal/SectionedScreenPortal.tsx @@ -0,0 +1,25 @@ +import {FC} from 'react'; + +import {ScreenSectionsEnum} from '../../enums'; +import {Portal} from '../Portal'; +import {SECTIONED_SCREEN_ID} from '../SectionedScreen/SectionedScreen'; + +interface SectionedScreenPortalPropsInterface { + section: ScreenSectionsEnum; + maximized?: boolean; +} +export const SectionedScreenPortal: FC = ({ + children, + section, + maximized +}) => { + return ( + + {children} + + ); +}; diff --git a/packages/ui-kit/src/atoms/SectionedScreenPortal/index.ts b/packages/ui-kit/src/atoms/SectionedScreenPortal/index.ts new file mode 100644 index 000000000..4578e19b1 --- /dev/null +++ b/packages/ui-kit/src/atoms/SectionedScreenPortal/index.ts @@ -0,0 +1 @@ +export * from './SectionedScreenPortal'; diff --git a/packages/ui-kit/src/atoms/index.ts b/packages/ui-kit/src/atoms/index.ts index c50380531..205d6baba 100644 --- a/packages/ui-kit/src/atoms/index.ts +++ b/packages/ui-kit/src/atoms/index.ts @@ -19,3 +19,4 @@ export * from './ErrorBoundary'; export * from './SpacePage'; export * from './LoaderFallback'; export * from './SectionedScreen'; +export * from './SectionedScreenPortal'; diff --git a/packages/ui-kit/src/enums/index.ts b/packages/ui-kit/src/enums/index.ts index 8f6cca7ec..0c0c26b56 100644 --- a/packages/ui-kit/src/enums/index.ts +++ b/packages/ui-kit/src/enums/index.ts @@ -1,3 +1,4 @@ export * from './userStatus.enum'; export * from './imageSize.enum'; export * from './errors.enum'; +export * from './screenSections.enum'; diff --git a/packages/ui-kit/src/enums/screenSections.enum.ts b/packages/ui-kit/src/enums/screenSections.enum.ts new file mode 100644 index 000000000..14883eefe --- /dev/null +++ b/packages/ui-kit/src/enums/screenSections.enum.ts @@ -0,0 +1,5 @@ +export enum ScreenSectionsEnum { + TOP_LEFT = 'top-left', + TOP_RIGHT = 'top-right', + BOTTOM_RIGHT = 'bottom-right' +} diff --git a/packages/ui-kit/src/molecules/WindowPanel/WindowPanel.styled.ts b/packages/ui-kit/src/molecules/WindowPanel/WindowPanel.styled.ts index d234a1bed..07105f5b4 100644 --- a/packages/ui-kit/src/molecules/WindowPanel/WindowPanel.styled.ts +++ b/packages/ui-kit/src/molecules/WindowPanel/WindowPanel.styled.ts @@ -4,21 +4,26 @@ import styled from 'styled-components'; export const Container = styled.div` display: flex; flex-direction: column; - // flex: 1 0 auto; ?? overflow: hidden; pointer-events: auto; - width: 680px; - height: 420px; + background: ${(props) => props.theme.bg && rgba(props.theme.bg, 0.9)}; border-radius: 10px 10px 0px 0px; - &.expanded { - // margin-top: 20px; - width: 100%; - height: 100%; - // height: calc(100% - 20px); + &:not(.expanded) { + max-height: 420px; + // max-height: 40vh; + aspect-ratio: 16 / 9; + // @media (max-height: 680px) { + // max-height: 35vh; + // } } + // &.expanded { + width: 100%; + height: 100%; + // } + transition: all 0.2s ease-in-out; `;