Browse Source

Video Hero Updates (#1190)

* Video Hero Updates

fixes:  #1113

* style cleanup

* cr

* 2:1 video ratio

* updates

* Icons and warnings
Diego Cardenas 3 years ago
parent
commit
5e15f01358

+ 3 - 9
src/components/ChannelLink/ChannelLink.style.ts

@@ -1,8 +1,8 @@
 import styled from '@emotion/styled'
 import { Link } from 'react-router-dom'
 
-import { SkeletonLoader } from '@/shared/components'
-import { colors, sizes, typography } from '@/shared/theme'
+import { SkeletonLoader, Text } from '@/shared/components'
+import { sizes } from '@/shared/theme'
 
 type ContainerProps = {
   disabled?: boolean
@@ -19,13 +19,7 @@ type HandleProps = {
   withAvatar: boolean
 }
 
-export const Handle = styled.span<HandleProps>`
-  display: inline-block;
-  font-family: ${typography.fonts.headers};
-  font-size: 1rem;
-  line-height: 1;
-  font-weight: bold;
-  color: ${colors.white};
+export const StyledText = styled(Text)<HandleProps>`
   margin-left: ${({ withAvatar }) => (withAvatar ? sizes(2) : 0)};
 `
 

+ 12 - 2
src/components/ChannelLink/ChannelLink.tsx

@@ -7,13 +7,14 @@ import { AssetType, useAsset } from '@/providers'
 import { Avatar, AvatarSize } from '@/shared/components/Avatar'
 import { Logger } from '@/utils/logger'
 
-import { Container, Handle, HandleSkeletonLoader } from './ChannelLink.style'
+import { Container, HandleSkeletonLoader, StyledText } from './ChannelLink.style'
 
 type ChannelLinkProps = {
   id?: string
   onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
   hideHandle?: boolean
   hideAvatar?: boolean
+  variant?: 'primary' | 'secondary'
   noLink?: boolean
   overrideChannel?: BasicChannelFieldsFragment
   avatarSize?: AvatarSize
@@ -25,6 +26,7 @@ export const ChannelLink: React.FC<ChannelLinkProps> = ({
   id,
   hideHandle,
   hideAvatar,
+  variant = 'primary',
   noLink,
   overrideChannel,
   avatarSize = 'default',
@@ -48,7 +50,15 @@ export const ChannelLink: React.FC<ChannelLinkProps> = ({
       {!hideAvatar && <Avatar loading={!displayedChannel} size={avatarSize} assetUrl={avatarPhotoUrl} />}
       {!hideHandle &&
         (displayedChannel ? (
-          <Handle withAvatar={!hideAvatar}>{displayedChannel.title}</Handle>
+          variant === 'secondary' ? (
+            <StyledText withAvatar={!hideAvatar} secondary variant="button2">
+              {displayedChannel.title}
+            </StyledText>
+          ) : (
+            <StyledText withAvatar={!hideAvatar} variant="h6">
+              {displayedChannel.title}
+            </StyledText>
+          )
         ) : (
           <HandleSkeletonLoader withAvatar={!hideAvatar} height={16} width={150} />
         ))}

+ 43 - 136
src/components/VideoHero/VideoHero.style.ts

@@ -1,48 +1,18 @@
 import { css } from '@emotion/react'
 import styled from '@emotion/styled'
-import { fluidRange } from 'polished'
 
 import { Button, IconButton, SkeletonLoader, Text } from '@/shared/components'
-import { breakpoints, colors, media, sizes } from '@/shared/theme'
+import { colors, media, sizes, typography } from '@/shared/theme'
 
+import { TOP_NAVBAR_HEIGHT } from '..'
 import { ChannelLink } from '../ChannelLink'
 
-const CONTENT_OVERLAP_MAP = {
-  SMALL: 25,
-  MEDIUM: 150,
-  LARGE: 200,
-  XLARGE: 400,
-  XXLARGE: 600,
-}
-const GRADIENT_OVERLAP = 50
-const GRADIENT_HEIGHT = 250
-const INFO_BOTTOM_MARGIN = 100
-const BUTTONS_HEIGHT_PX = '54px'
+const BUTTONS_HEIGHT = 48
 
 export const Container = styled.section`
   position: relative;
-
-  /* because of the fixed aspect ratio, as the viewport width grows, the media will occupy more height as well
-   so that the media doesn't take too big of a portion of the space, we let the content overlap the media via a negative margin */
-  ${media.small} {
-    margin-bottom: -${CONTENT_OVERLAP_MAP.SMALL}px;
-  }
-
-  ${media.medium} {
-    margin-bottom: -${CONTENT_OVERLAP_MAP.MEDIUM}px;
-  }
-
-  ${media.large} {
-    margin-bottom: -${CONTENT_OVERLAP_MAP.LARGE}px;
-  }
-
-  ${media.xlarge} {
-    margin-bottom: -${CONTENT_OVERLAP_MAP.XLARGE}px;
-  }
-
-  ${media.xxlarge} {
-    margin-bottom: -${CONTENT_OVERLAP_MAP.XXLARGE}px;
-  }
+  max-height: calc(100vh - ${TOP_NAVBAR_HEIGHT}px);
+  margin-bottom: -${sizes(6)}px;
 `
 
 export const MediaWrapper = styled.div`
@@ -53,8 +23,18 @@ export const MediaWrapper = styled.div`
 export const Media = styled.div`
   width: 100%;
   height: 0;
-  padding-top: 56.25%;
+
+  /* 2:1 ratio */
+  padding-top: 50%;
   position: relative;
+
+  ${media.smalldium} {
+    margin-bottom: ${sizes(8)}px;
+  }
+
+  ${media.medium} {
+    margin-bottom: 0;
+  }
 `
 
 const absoluteMediaCss = css`
@@ -69,95 +49,36 @@ export const PlayerContainer = styled.div`
   ${absoluteMediaCss};
 `
 
-export const HorizontalGradientOverlay = styled.div`
+export const GradientOverlay = styled.div`
   ${absoluteMediaCss};
 
-  display: none;
-  background: linear-gradient(90deg, rgba(0, 0, 0, 0.8) 11.76%, rgba(0, 0, 0, 0) 100%);
-
-  ${media.small} {
-    display: block;
-  }
-`
-
-export const VerticalGradientOverlay = styled.div`
-  ${absoluteMediaCss};
-
-  /* as the content overlaps the media more and more as the viewport width grows, we need to hide some part of the media with a gradient
-   this helps with keeping a consistent background behind a page content - we don't want the media to peek out in the content spacing */
-  background: linear-gradient(0deg, black 0%, rgba(0, 0, 0, 0) ${GRADIENT_HEIGHT / 2}px);
-  ${media.small} {
-    background: linear-gradient(
-      0deg,
-      black 0%,
-      black ${CONTENT_OVERLAP_MAP.SMALL - GRADIENT_OVERLAP}px,
-      rgba(0, 0, 0, 0) ${CONTENT_OVERLAP_MAP.SMALL - GRADIENT_OVERLAP + GRADIENT_HEIGHT}px
-    );
-  }
-
-  ${media.medium} {
-    background: linear-gradient(
-      0deg,
-      black 0%,
-      black ${CONTENT_OVERLAP_MAP.MEDIUM - GRADIENT_OVERLAP}px,
-      rgba(0, 0, 0, 0) ${CONTENT_OVERLAP_MAP.MEDIUM - GRADIENT_OVERLAP + GRADIENT_HEIGHT}px
-    );
-  }
-
-  ${media.large} {
-    background: linear-gradient(
-      0deg,
-      black 0%,
-      black ${CONTENT_OVERLAP_MAP.LARGE - GRADIENT_OVERLAP}px,
-      rgba(0, 0, 0, 0) ${CONTENT_OVERLAP_MAP.LARGE - GRADIENT_OVERLAP + GRADIENT_HEIGHT}px
-    );
-  }
-
-  ${media.xlarge} {
-    background: linear-gradient(
-      0deg,
-      black 0%,
-      black ${CONTENT_OVERLAP_MAP.XLARGE - GRADIENT_OVERLAP}px,
-      rgba(0, 0, 0, 0) ${CONTENT_OVERLAP_MAP.XLARGE - GRADIENT_OVERLAP + GRADIENT_HEIGHT}px
-    );
-  }
-
-  ${media.xxlarge} {
-    background: linear-gradient(
-      0deg,
-      black 0%,
-      black ${CONTENT_OVERLAP_MAP.XXLARGE - GRADIENT_OVERLAP}px,
-      rgba(0, 0, 0, 0) ${CONTENT_OVERLAP_MAP.XXLARGE - GRADIENT_OVERLAP + GRADIENT_HEIGHT}px
-    );
-  }
+  background: linear-gradient(180deg, transparent 50%, ${colors.black} 93.23%, ${colors.black} 100%),
+    radial-gradient(50.66% 101.32% at 50% 50%, transparent 0%, ${colors.transparentBlack[54]} 100%),
+    ${colors.transparentBlack[54]};
 `
 
 export const InfoContainer = styled.div<{ isLoading: boolean }>`
   position: relative;
-  margin-top: -${sizes(8)};
-  padding-bottom: ${sizes(12)};
+  padding-bottom: ${sizes(16)};
+  width: 100%;
 
   ${media.small} {
+    margin-bottom: 64px;
+    padding-bottom: 0;
+  }
+
+  ${media.smalldium} {
     position: absolute;
     margin: 0;
-    padding-bottom: 0;
-    bottom: ${CONTENT_OVERLAP_MAP.SMALL + INFO_BOTTOM_MARGIN / 4}px;
+    bottom: 64px;
   }
 
   ${media.medium} {
-    bottom: ${CONTENT_OVERLAP_MAP.MEDIUM + INFO_BOTTOM_MARGIN / 2}px;
+    bottom: 96px;
   }
 
   ${media.large} {
-    bottom: ${CONTENT_OVERLAP_MAP.LARGE + INFO_BOTTOM_MARGIN}px;
-  }
-
-  ${media.xlarge} {
-    bottom: ${CONTENT_OVERLAP_MAP.XLARGE + INFO_BOTTOM_MARGIN}px;
-  }
-
-  ${media.xxlarge} {
-    bottom: ${CONTENT_OVERLAP_MAP.XXLARGE + INFO_BOTTOM_MARGIN}px;
+    bottom: 128px;
   }
 `
 
@@ -170,31 +91,20 @@ export const TitleContainer = styled.div`
     text-decoration: none;
   }
 
-  margin-bottom: ${sizes(8)};
-
-  ${media.medium} {
-    margin-bottom: ${sizes(10)};
-  }
-
-  span {
-    display: block;
-    max-width: 40ch;
-    ${fluidRange({ prop: 'fontSize', fromSize: '14px', toSize: '22px' }, breakpoints.base, breakpoints.xlarge)};
-    ${fluidRange({ prop: 'lineHeight', fromSize: '20px', toSize: '26px' }, breakpoints.base, breakpoints.xlarge)};
+  margin-bottom: ${sizes(4)};
 
-    color: ${colors.white};
+  ${media.small} {
+    margin-bottom: ${sizes(8)};
   }
 `
 
 export const Title = styled(Text)`
-  ${fluidRange({ prop: 'fontSize', fromSize: '40px', toSize: '72px' }, breakpoints.base, breakpoints.xlarge)};
-  ${fluidRange({ prop: 'lineHeight', fromSize: '48px', toSize: '68px' }, breakpoints.base, breakpoints.xlarge)};
-
-  display: inline-block;
-  margin-bottom: ${sizes(4)};
+  font-size: ${typography.sizes.h3};
+  line-height: ${typography.lineHeights.h3};
 
-  ${media.medium} {
-    margin-bottom: ${sizes(5)};
+  ${media.large} {
+    font-size: ${typography.sizes.h2};
+    line-height: ${typography.lineHeights.h2};
   }
 `
 
@@ -206,21 +116,18 @@ export const TitleSkeletonLoader = styled(SkeletonLoader)`
   }
 `
 
-export const ControlsContainer = styled.div`
-  min-height: ${BUTTONS_HEIGHT_PX};
-`
-
 export const ButtonsContainer = styled.div`
   display: flex;
 `
 
+export const ButtonsSpaceKeeper = styled.div`
+  min-height: ${BUTTONS_HEIGHT}px;
+`
+
 export const PlayButton = styled(Button)`
-  width: 140px;
-  height: ${BUTTONS_HEIGHT_PX};
+  width: 90px;
 `
 
 export const SoundButton = styled(IconButton)`
   margin-left: ${sizes(4)};
-  height: ${BUTTONS_HEIGHT_PX};
-  width: ${BUTTONS_HEIGHT_PX};
 `

+ 35 - 34
src/components/VideoHero/VideoHero.tsx

@@ -4,15 +4,18 @@ import { CSSTransition } from 'react-transition-group'
 
 import { absoluteRoutes } from '@/config/routes'
 import { AssetType, useAsset } from '@/providers'
-import { SkeletonLoader, VideoPlayer } from '@/shared/components'
-import { SvgPlayerPause, SvgPlayerPlay, SvgPlayerSoundOff, SvgPlayerSoundOn } from '@/shared/icons'
+import { GridItem, LayoutGrid, SkeletonLoader, VideoPlayer } from '@/shared/components'
+import { SvgActionPause } from '@/shared/icons/ActionPause'
+import { SvgActionPlay } from '@/shared/icons/ActionPlay'
+import { SvgActionSoundOff } from '@/shared/icons/ActionSoundOff'
+import { SvgActionSoundOn } from '@/shared/icons/ActionSoundOn'
 import { transitions } from '@/shared/theme'
 
 import {
   ButtonsContainer,
+  ButtonsSpaceKeeper,
   Container,
-  ControlsContainer,
-  HorizontalGradientOverlay,
+  GradientOverlay,
   InfoContainer,
   Media,
   MediaWrapper,
@@ -23,7 +26,6 @@ import {
   Title,
   TitleContainer,
   TitleSkeletonLoader,
-  VerticalGradientOverlay,
 } from './VideoHero.style'
 import { useVideoHero } from './VideoHeroData'
 
@@ -62,6 +64,7 @@ export const VideoHero: React.FC = () => {
           <PlayerContainer>
             {coverVideo && (
               <VideoPlayer
+                videoStyle={{ objectFit: 'cover' }}
                 fluid
                 isInBackground
                 muted={soundMuted}
@@ -75,34 +78,36 @@ export const VideoHero: React.FC = () => {
               />
             )}
           </PlayerContainer>
-          {coverVideo && <HorizontalGradientOverlay />}
-          <VerticalGradientOverlay />
+          <GradientOverlay />
         </Media>
       </MediaWrapper>
       <InfoContainer isLoading={!coverVideo}>
         <StyledChannelLink
+          variant="secondary"
           id={coverVideo?.video.channel.id}
-          hideHandle
           overrideChannel={coverVideo?.video.channel}
-          avatarSize="cover"
+          avatarSize="small"
         />
-        <TitleContainer>
-          {coverVideo ? (
-            <>
-              <Link to={absoluteRoutes.viewer.video(coverVideo.video.id)}>
-                <Title variant="h2">{coverVideo.coverTitle}</Title>
-              </Link>
-              <span>{coverVideo.coverDescription}</span>
-            </>
-          ) : (
-            <>
-              <TitleSkeletonLoader width={380} height={60} />
-              <SkeletonLoader width={300} height={20} bottomSpace={4} />
-              <SkeletonLoader width={200} height={20} />
-            </>
-          )}
-        </TitleContainer>
-        <ControlsContainer>
+        <LayoutGrid>
+          <GridItem colSpan={{ base: 12, compact: 10, small: 8, medium: 5, xlarge: 4, xxlarge: 3 }}>
+            <TitleContainer>
+              {coverVideo ? (
+                <>
+                  <Link to={absoluteRoutes.viewer.video(coverVideo.video.id)}>
+                    <Title variant="h2">{coverVideo.coverTitle}</Title>
+                  </Link>
+                </>
+              ) : (
+                <>
+                  <TitleSkeletonLoader width={380} height={60} />
+                  <SkeletonLoader width={300} height={20} bottomSpace={4} />
+                  <SkeletonLoader width={200} height={20} />
+                </>
+              )}
+            </TitleContainer>
+          </GridItem>
+        </LayoutGrid>
+        <ButtonsSpaceKeeper>
           <CSSTransition
             in={displayControls}
             timeout={parseInt(transitions.timings.loading)}
@@ -111,19 +116,15 @@ export const VideoHero: React.FC = () => {
             appear
           >
             <ButtonsContainer>
-              <PlayButton
-                onClick={handlePlayPauseClick}
-                icon={videoPlaying ? <SvgPlayerPause /> : <SvgPlayerPlay />}
-                size="large"
-              >
+              <PlayButton onClick={handlePlayPauseClick} icon={videoPlaying ? <SvgActionPause /> : <SvgActionPlay />}>
                 {videoPlaying ? 'Pause' : 'Play'}
               </PlayButton>
-              <SoundButton onClick={handleSoundToggleClick} size="large">
-                {!soundMuted ? <SvgPlayerSoundOn /> : <SvgPlayerSoundOff />}
+              <SoundButton variant="secondary" onClick={handleSoundToggleClick}>
+                {!soundMuted ? <SvgActionSoundOn /> : <SvgActionSoundOff />}
               </SoundButton>
             </ButtonsContainer>
           </CSSTransition>
-        </ControlsContainer>
+        </ButtonsSpaceKeeper>
       </InfoContainer>
     </Container>
   )

+ 4 - 2
src/shared/components/VideoPlayer/VideoPlayer.tsx

@@ -1,5 +1,5 @@
 import { debounce, round } from 'lodash'
-import React, { useCallback, useEffect, useRef, useState } from 'react'
+import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react'
 
 import { VideoFieldsFragment } from '@/api/queries'
 import { usePersonalDataStore } from '@/providers'
@@ -44,6 +44,7 @@ import { VideoJsConfig, useVideoJsPlayer } from './videoJsPlayer'
 export type VideoPlayerProps = {
   nextVideo?: VideoFieldsFragment | null
   className?: string
+  videoStyle?: CSSProperties
   autoplay?: boolean
   isInBackground?: boolean
   playing?: boolean
@@ -63,7 +64,7 @@ const isPiPSupported = 'pictureInPictureEnabled' in document
 export type PlayerState = 'loading' | 'ended' | 'error' | 'playing' | null
 
 const VideoPlayerComponent: React.ForwardRefRenderFunction<HTMLVideoElement, VideoPlayerProps> = (
-  { className, isInBackground, playing, nextVideo, channelId, videoId, autoplay, ...videoJsConfig },
+  { className, isInBackground, playing, nextVideo, channelId, videoId, autoplay, videoStyle, ...videoJsConfig },
   externalRef
 ) => {
   const [player, playerRef] = useVideoJsPlayer(videoJsConfig)
@@ -434,6 +435,7 @@ const VideoPlayerComponent: React.ForwardRefRenderFunction<HTMLVideoElement, Vid
           </BigPlayButtonOverlay>
         )}
         <video
+          style={videoStyle}
           ref={playerRef}
           className="video-js"
           onClick={() =>

+ 8 - 0
src/shared/icons/ActionPause.tsx

@@ -0,0 +1,8 @@
+// THIS FILE WAS AUTOGENERATED BY SVGR. DO NOT MODIFY IT MANUALLY.
+import * as React from 'react'
+
+export const SvgActionPause = (props: React.SVGProps<SVGSVGElement>) => (
+  <svg width={10} height={12} viewBox="0 0 10 12" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
+    <path d="M4 0H0v12h4V0zM10 0H6v12h4V0z" fill="#F4F6F8" />
+  </svg>
+)

+ 8 - 0
src/shared/icons/ActionPlay.tsx

@@ -0,0 +1,8 @@
+// THIS FILE WAS AUTOGENERATED BY SVGR. DO NOT MODIFY IT MANUALLY.
+import * as React from 'react'
+
+export const SvgActionPlay = (props: React.SVGProps<SVGSVGElement>) => (
+  <svg width={9} height={10} viewBox="0 0 9 10" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
+    <path d="M0 0l4.5 2.5L9 5 4.5 7.5 0 10V0z" fill="#F4F6F8" />
+  </svg>
+)

+ 11 - 0
src/shared/icons/ActionSoundOff.tsx

@@ -0,0 +1,11 @@
+// THIS FILE WAS AUTOGENERATED BY SVGR. DO NOT MODIFY IT MANUALLY.
+import * as React from 'react'
+
+export const SvgActionSoundOff = (props: React.SVGProps<SVGSVGElement>) => (
+  <svg width={14} height={14} viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
+    <path
+      d="M12.445 11.03l1.262 1.263-1.414 1.414-12-12L1.707.293l1.764 1.764L4 1h2v3.586l2 2V5a2 2 0 011.606 3.192l1.422 1.422A4 4 0 008 3V1a6 6 0 014.445 10.03zM6 9.914L1.086 5H1a1 1 0 00-1 1v2a1 1 0 001 1h1l2 4h2V9.914z"
+      fill="#F4F6F8"
+    />
+  </svg>
+)

+ 12 - 0
src/shared/icons/ActionSoundOn.tsx

@@ -0,0 +1,12 @@
+// THIS FILE WAS AUTOGENERATED BY SVGR. DO NOT MODIFY IT MANUALLY.
+import * as React from 'react'
+
+export const SvgActionSoundOn = (props: React.SVGProps<SVGSVGElement>) => (
+  <svg width={14} height={12} viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
+    <path
+      d="M2 4l2-4h2v12H4L2 8H1a1 1 0 01-1-1V5a1 1 0 011-1h1zM12 6a4 4 0 00-4-4V0a6 6 0 010 12v-2a4 4 0 004-4z"
+      fill="#F4F6F8"
+    />
+    <path d="M10 6a2 2 0 00-2-2v4a2 2 0 002-2z" fill="#F4F6F8" />
+  </svg>
+)

+ 4 - 0
src/shared/icons/svgs/action_pause.svg

@@ -0,0 +1,4 @@
+<svg width="10" height="12" viewBox="0 0 10 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 0H0V12H4V0Z" fill="#F4F6F8"/>
+<path d="M10 0H6V12H10V0Z" fill="#F4F6F8"/>
+</svg>

+ 3 - 0
src/shared/icons/svgs/action_play.svg

@@ -0,0 +1,3 @@
+<svg width="9" height="10" viewBox="0 0 9 10" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0 0L4.5 2.5L9 5L4.5 7.5L0 10V0Z" fill="#F4F6F8"/>
+</svg>

+ 4 - 0
src/shared/icons/svgs/action_sound_off.svg

@@ -0,0 +1,4 @@
+<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12.4447 11.0306L13.7071 12.293L12.2929 13.7072L0.292893 1.70718L1.70711 0.292969L3.4714 2.05727L4 1.00008H6V4.58586L8 6.58586V5.00008C9.10457 5.00008 10 5.89551 10 7.00008C10 7.44671 9.8536 7.85915 9.60616 8.19202L11.028 9.61385C11.6337 8.91281 12 7.99922 12 7.00008C12 4.79094 10.2091 3.00008 8 3.00008V1.00008C11.3137 1.00008 14 3.68637 14 7.00008C14 8.55155 13.4111 9.96549 12.4447 11.0306Z" fill="#F4F6F8"/>
+<path d="M6 9.91429L1.08579 5.00008H1C0.447715 5.00008 0 5.44779 0 6.00008V8.00008C0 8.55236 0.447715 9.00008 1 9.00008H2L4 13.0001H6V9.91429Z" fill="#F4F6F8"/>
+</svg>

+ 5 - 0
src/shared/icons/svgs/action_sound_on.svg

@@ -0,0 +1,5 @@
+<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 4L4 0H6V12H4L2 8H1C0.447715 8 0 7.55228 0 7V5C0 4.44772 0.447715 4 1 4H2Z" fill="#F4F6F8"/>
+<path d="M12 6C12 3.79086 10.2091 2 8 2V0C11.3137 0 14 2.68629 14 6C14 9.31371 11.3137 12 8 12V10C10.2091 10 12 8.20914 12 6Z" fill="#F4F6F8"/>
+<path d="M10 6C10 4.89543 9.10457 4 8 4V8C9.10457 8 10 7.10457 10 6Z" fill="#F4F6F8"/>
+</svg>

+ 1 - 0
src/shared/theme/breakpoints.ts

@@ -2,6 +2,7 @@ export const breakpoints = {
   base: '320px',
   compact: '450px',
   small: '600px',
+  smalldium: '768px',
   medium: '1024px',
   large: '1440px',
   xlarge: '1920px',

+ 1 - 0
src/shared/theme/media.ts

@@ -8,6 +8,7 @@ const media = {
   base: buildQuery(breakpoints.base),
   compact: buildQuery(breakpoints.compact),
   small: buildQuery(breakpoints.small),
+  smalldium: buildQuery(breakpoints.smalldium),
   medium: buildQuery(breakpoints.medium),
   large: buildQuery(breakpoints.large),
   xlarge: buildQuery(breakpoints.xlarge),

+ 9 - 3
src/views/viewer/HomeView.tsx

@@ -4,7 +4,13 @@ import { sub } from 'date-fns'
 import React from 'react'
 
 import useVideosConnection from '@/api/hooks/videosConnection'
-import { ErrorFallback, InfiniteVideoGrid, InterruptedVideosGallery, VideoHero, ViewWrapper } from '@/components'
+import {
+  ErrorFallback,
+  InfiniteVideoGrid,
+  InterruptedVideosGallery,
+  LimitedWidthContainer,
+  VideoHero,
+} from '@/components'
 import { usePersonalDataStore } from '@/providers'
 import { transitions } from '@/shared/theme'
 
@@ -36,7 +42,7 @@ export const HomeView: React.FC = () => {
     throw error
   }
   return (
-    <ViewWrapper>
+    <LimitedWidthContainer big>
       <VideoHero />
       <Container className={transitions.names.slide}>
         <InterruptedVideosGallery />
@@ -49,7 +55,7 @@ export const HomeView: React.FC = () => {
           />
         </ErrorBoundary>
       </Container>
-    </ViewWrapper>
+    </LimitedWidthContainer>
   )
 }