Skip to content

Commit

Permalink
[B2BP-933] [B2BP-934] - Video-image: add title and subtitle on image …
Browse files Browse the repository at this point in the history
…rendering and add image for mobile breakpoint (#475)

* add imageTitle and imageSubtitle

* change text align

* add overlay to image

* add review changes

* replace imageTitle and imageSubtitle with title and subtitle

* add image for mobile breakpoint
  • Loading branch information
salvatorediocaro authored Oct 17, 2024
1 parent 53c54ee commit 800b8fb
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 70 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-berries-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nextjs-website": patch
---

VideoImage: Show title and subtitle when displaying image and add image for mobile breakpoint
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ export const renderVideo = ({
fallback,
onClick,
onVideoEnd,
isMobileDevice
isMobileDevice,
}: RenderVideoProps) => {
// Define styles for mobile and non-mobile devices
const mobileStyle = {
overflow: 'hidden',
width: '100vw',
Expand Down Expand Up @@ -55,17 +54,18 @@ export const renderVideo = ({
onClick={onClick}
style={isMobileDevice ? mobileStyle : nonMobileStyle}
>
<source
src={src}
onError={() => setError(true)}
/>
<source src={src} onError={() => setError(true)} />
</video>
);
};

// Refactored renderImage function
export const renderImage = ({ src, alt, isMobileDevice }: RenderImageProps) => {
// Define styles for mobile and non-mobile devices
export const renderImage = ({
src,
alt,
mobileSrc,
mobileAlt,
isMobileDevice,
}: RenderImageProps) => {
const mobileStyle = {
overflow: 'hidden',
width: '100vw',
Expand All @@ -80,10 +80,13 @@ export const renderImage = ({ src, alt, isMobileDevice }: RenderImageProps) => {
height: '100%',
};

const imageSrc = isMobileDevice && mobileSrc ? mobileSrc : src;
const imageAlt = isMobileDevice && mobileAlt ? mobileAlt : alt;

return (
<Image
alt={alt}
src={src}
alt={imageAlt}
src={imageSrc}
width={0}
height={0}
style={isMobileDevice ? mobileStyle : nonMobileStyle}
Expand Down Expand Up @@ -118,6 +121,37 @@ export const VideoText = ({
);
};

export const ImageText = ({
title,
subtitle,
theme = 'dark',
}: {
title?: string;
subtitle?: string;
theme: 'dark' | 'light';
}) => {
const textColor = TextColor(theme);
return (
<>
{title && (
<Typography variant='h5' mb={4} color={textColor}>
{title}
</Typography>
)}
{subtitle && (
<Typography
paragraph
sx={{ fontSize: '16px' }}
mb={3}
color={textColor}
>
{subtitle}
</Typography>
)}
</>
);
};

export const VideoCaption = ({ caption, isCentered }: VideoCaptionProps) => {
const { palette } = useTheme();
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// Disable rule below since we'll be determining whether image or video exist based on mediaState
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import { useEffect, useRef, useState } from 'react';
import { useIsVisible } from '@react-components/types/common/Common.types';
import { VideoImageProps } from '@react-components/types';
Expand All @@ -11,6 +8,7 @@ import {
renderVideo,
VideoCaption,
VideoText,
ImageText,
} from './VideoImage.helpers';

const VideoImage = ({
Expand All @@ -20,12 +18,11 @@ const VideoImage = ({
isCentered,
theme,
image,
mobileImage,
video,
sectionID,
}: VideoImageProps) => {
if (!image && !video) {
// Disable lint for this case because we want the build to fail if user input nothing
// eslint-disable-next-line
throw new Error();
}

Expand All @@ -41,7 +38,6 @@ const VideoImage = ({

useEffect(() => {
setIsMobileDevice(window.innerWidth <= 768);

const handleResize = () => {
setIsMobileDevice(window.innerWidth <= 768);
};
Expand All @@ -52,7 +48,6 @@ const VideoImage = ({
useEffect(() => {
if (mediaState === 'image') return;
if (!isVisible) return;

const startVideoWhenVisible = async () => {
if (video?.autoplay && isVisible) play();
};
Expand All @@ -61,18 +56,14 @@ const VideoImage = ({

const play = (e?: React.MouseEvent) => {
e?.preventDefault();

if (mediaState === 'image') return;

if (videoRef.current) {
videoRef.current
.play()
.then(() => {
setMediaState('play');
})
.catch(() => {
// Handle play error
});
.catch(() => {});
}
};

Expand All @@ -95,7 +86,7 @@ const VideoImage = ({
position: 'relative',
overflow: 'hidden',
}}
{...sectionID && { id: sectionID }}
{...(sectionID && { id: sectionID })}
>
{video?.showControls &&
(mediaState === 'stop' || mediaState === 'pause') && (
Expand Down Expand Up @@ -165,29 +156,78 @@ const VideoImage = ({
</div>
</div>
)}
{mediaState === 'image' ? (
<>
<div
style={{ position: 'relative', width: '100%', height: '600px' }}
>
{renderImage({
src: image!.src,
alt: image!.alt,
mobileSrc: mobileImage!.src,
mobileAlt: mobileImage!.alt,
isMobileDevice,
})}

{(title || subtitle) && (
<>
<div
style={{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.25)',
zIndex: 10,
}}
/>

{mediaState === 'image'
? renderImage({
src: image!.src,
alt: image!.alt,
isMobileDevice,
})
: renderVideo({
videoRef,
error,
setError,
src: video!.src,
loop: video!.loop,
autoplay: video!.autoplay,
fallback: video!.fallback,
onVideoEnd: handleVideoEnd,
onClick: pause,
isMobileDevice,
})}
<div
style={{
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: isCentered ? 'center' : 'flex-start',
zIndex: 20,
padding: '20px',
marginLeft: isCentered ? '0' : '6em',
textAlign: isCentered ? 'center' : 'left',
}}
>
<ImageText
theme={theme}
title={title ?? ''}
subtitle={subtitle ?? ''}
/>
</div>
</>
)}
</div>
</>
) : (
renderVideo({
videoRef,
error,
setError,
src: video!.src,
loop: video!.loop,
autoplay: video!.autoplay,
fallback: video!.fallback,
onVideoEnd: handleVideoEnd,
onClick: pause,
isMobileDevice,
})
)}
</section>
{caption && (
<VideoCaption caption={caption} isCentered={isCentered} />
)}
{caption && <VideoCaption caption={caption} isCentered={isCentered} />}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { SectionProps, Theme } from '../common/Common.types';

export interface VideoImageProps extends SectionProps, VideoTextProps, VideoCaptionProps {
export interface VideoImageProps
extends SectionProps,
VideoTextProps,
VideoCaptionProps {
image?: {
src: string;
alt: string;
};
mobileImage?: {
src: string;
alt: string;
};
video?: {
src: string;
autoplay: boolean;
Expand Down Expand Up @@ -43,5 +50,7 @@ export interface RenderVideoProps {
export interface RenderImageProps {
src: string;
alt: string;
mobileSrc: string;
mobileAlt: string;
isMobileDevice: boolean;
}
24 changes: 8 additions & 16 deletions apps/nextjs-website/src/components/VideoImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ const makeVideoImageProps = ({
subtitle,
caption,
image,
mobileImage,
video,
...rest
}: VideoImageSection): VideoImageProps => ({
...rest,
...(title && { title }),
...(subtitle && { subtitle }),
...(caption && { caption }),
// If user uploaded a video, use it
...(video &&
video.src.data && {
video: {
Expand All @@ -28,27 +28,19 @@ const makeVideoImageProps = ({
pausedPlayButtonLabel: video.pausedPlayButtonLabel,
},
}),
// If user did not upload a video, check if they input a URL
...(video &&
!video.src.data &&
video.srcURL && {
video: {
src: video.srcURL,
autoplay: video.autoplay,
loop: video.loop,
showControls: video.showControls,
fallback: video.fallback,
playButtonLabel: video.playButtonLabel,
pausedPlayButtonLabel: video.pausedPlayButtonLabel,
},
}),
// If user did not input any video source, check if they uploaded an image
...((!video || (!video.srcURL && !video.src.data)) &&
image.data && {
image: {
src: image.data.attributes.url,
alt: image.data.attributes.alternativeText ?? '',
},
mobileImage: {
src: mobileImage?.data?.attributes?.url ?? image.data.attributes.url,
alt:
mobileImage?.data?.attributes?.alternativeText ??
image.data.attributes.alternativeText ??
'',
},
}),
});

Expand Down
1 change: 1 addition & 0 deletions apps/nextjs-website/src/lib/fetch/types/PageSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ const VideoImageSectionCodec = t.strict({
caption: t.union([t.string, t.null]),
isCentered: t.boolean,
image: StrapiImageSchema,
mobileImage: StrapiImageSchema,
video: t.union([VideoCodec, t.null]),
});

Expand Down
Loading

0 comments on commit 800b8fb

Please sign in to comment.