Skip to content

Commit

Permalink
feat: add media images fullscreen slider (#889)
Browse files Browse the repository at this point in the history
* feat: add media images fullscreen slider
  • Loading branch information
qradle-yndx authored Apr 9, 2024
1 parent b8aacc5 commit eec646d
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 7 deletions.
6 changes: 4 additions & 2 deletions src/blocks/Slider/Slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface SliderProps
dotsClassName?: string;
blockClassName?: string;
arrowSize?: number;
initialIndex?: number;
}

export const SliderBlock = (props: WithChildren<SliderProps>) => {
Expand All @@ -83,6 +84,7 @@ export const SliderBlock = (props: WithChildren<SliderProps>) => {
arrowSize,
onAfterChange: handleAfterChange,
onBeforeChange: handleBeforeChange,
initialIndex = 0,
} = props;

const {isServer} = useContext(SSRContext);
Expand All @@ -107,7 +109,7 @@ export const SliderBlock = (props: WithChildren<SliderProps>) => {
const slidesToShowCount = getSlidesToShowCount(slidesToShow);
const slidesCountByBreakpoint = getSlidesCountByBreakpoint(breakpoint, slidesToShow);

const [currentIndex, setCurrentIndex] = useState<number>(0);
const [currentIndex, setCurrentIndex] = useState<number>(initialIndex);
const [childStyles, setChildStyles] = useState<Object>({});
const [slider, setSlider] = useState<SlickSlider>();
const autoplayTimeId = useRef<Timeout>();
Expand Down Expand Up @@ -346,7 +348,7 @@ export const SliderBlock = (props: WithChildren<SliderProps>) => {
responsive: getSliderResponsiveParams(slidesToShow),
beforeChange: onBeforeChange,
afterChange: onAfterChange,
initialSlide: 0,
initialSlide: initialIndex,
nextArrow: <Arrow type="right" handleClick={handleArrowClick} size={arrowSize} />,
prevArrow: <Arrow type="left" handleClick={handleArrowClick} size={arrowSize} />,
lazyLoad,
Expand Down
21 changes: 21 additions & 0 deletions src/components/FullscreenImage/FullscreenImage.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ $closeButtonSize: 36px;
overflow: hidden;
}

&__modal-slider {
max-width: $newContentWidth;
width: 100%;
max-height: 70vh;
overflow: hidden;
border-radius: $borderRadius;

&_item {
height: 100%;

&-image {
display: block;
max-height: 70vh;
max-width: 100%;
width: 100%;
object-fit: contain;
object-position: center;
}
}
}

&__modal .yc-modal__content,
&__modal-image {
border-radius: $borderRadius;
Expand Down
37 changes: 35 additions & 2 deletions src/components/FullscreenImage/FullscreenImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import React, {CSSProperties, HTMLProps, useState} from 'react';
import {ChevronsExpandUpRight, Xmark} from '@gravity-ui/icons';
import {Icon, Modal} from '@gravity-ui/uikit';

import SliderBlock from '../../blocks/Slider/Slider';
import {ImageProps as ModelImageProps, SliderType} from '../../models';
import {block} from '../../utils';
import Image, {ImageProps} from '../Image/Image';
import {getMediaImage} from '../Media/Image/utils';

import {i18n} from './i18n';

Expand All @@ -15,14 +18,22 @@ export interface FullscreenImageProps extends ImageProps {
modalImageClass?: string;
imageStyle?: CSSProperties;
extraProps?: HTMLProps<HTMLDivElement>;
sliderData?: {items: ModelImageProps[]; initialIndex: number};
}

const b = block('fullscreen-image');
const FULL_SCREEN_ICON_SIZE = 18;
const CLOSE_ICON_SIZE = 24;

const FullscreenImage = (props: FullscreenImageProps) => {
const {imageClassName, modalImageClass, imageStyle, alt = i18n('img-alt'), extraProps} = props;
const {
imageClassName,
sliderData,
modalImageClass,
imageStyle,
alt = i18n('img-alt'),
extraProps,
} = props;
const [isOpened, setIsOpened] = useState(false);

const openModal = () => setIsOpened(true);
Expand Down Expand Up @@ -66,7 +77,29 @@ const FullscreenImage = (props: FullscreenImageProps) => {
className={b('icon', {hover: true})}
/>
</button>
<Image {...props} className={b('modal-image', modalImageClass)} />
{sliderData ? (
<div className={b('modal-slider')}>
<SliderBlock
initialIndex={sliderData.initialIndex}
slidesToShow={1}
type={SliderType.MediaCard}
>
{sliderData.items.map((item, index) => (
<div key={index} className={b('modal-slider_item')}>
<Image
className={b(
'modal-slider_item-image',
modalImageClass,
)}
{...getMediaImage(item)}
/>
</div>
))}
</SliderBlock>
</div>
) : (
<Image {...props} className={b('modal-image', modalImageClass)} />
)}
</Modal>
)}
</div>
Expand Down
15 changes: 12 additions & 3 deletions src/components/Media/Image/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SliderBlock from '../../../blocks/Slider/Slider';
import {ImageProps, MediaComponentImageProps, QAProps, SliderType} from '../../../models';
import {block, getQaAttrubutes} from '../../../utils';
import BackgroundImage from '../../BackgroundImage/BackgroundImage';
import FullscreenImage from '../../FullscreenImage/FullscreenImage';
import FullscreenImage, {FullscreenImageProps} from '../../FullscreenImage/FullscreenImage';
import ImageView from '../../Image/Image';

import {getMediaImage} from './utils';
Expand All @@ -20,6 +20,7 @@ export interface ImageAdditionProps {
imageClassName?: string;
isBackground?: boolean;
fullscreen?: boolean;
fullscreenClassName?: string;
onLoad?: () => void;
}

Expand All @@ -36,6 +37,7 @@ const Image = (props: ImageAllProps) => {
parallax,
height,
imageClassName,
fullscreenClassName,
isBackground,
hasVideoFallback,
video,
Expand Down Expand Up @@ -87,16 +89,21 @@ const Image = (props: ImageAllProps) => {

const imageClass = b('item', {withVideo: Boolean(video) && !hasVideoFallback}, imageClassName);

const renderFullscreenImage = (item: ImageProps) => {
const renderFullscreenImage = (
item: ImageProps,
sliderData?: FullscreenImageProps['sliderData'],
) => {
const itemData = getMediaImage(item);

return (
<FullscreenImage
key={itemData.alt}
{...itemData}
imageClassName={imageClass}
modalImageClass={fullscreenClassName}
imageStyle={{height}}
qa={qaAttributes.fullscreenImage}
sliderData={sliderData}
/>
);
};
Expand Down Expand Up @@ -135,7 +142,9 @@ const Image = (props: ImageAllProps) => {
<SliderBlock slidesToShow={1} type={SliderType.MediaCard}>
{imageArray.map((item, index) => (
<Fragment key={index}>
{fullscreenItem ? renderFullscreenImage(item) : imageOnly(item)}
{fullscreenItem
? renderFullscreenImage(item, {items: imageArray, initialIndex: index})
: imageOnly(item)}
</Fragment>
))}
</SliderBlock>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Media/Media.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,9 @@ $block: '.#{$ns}Media';
display: flex;
align-items: center;
}

&__fullscreen-image-cover {
object-fit: cover;
object-position: top;
}
}
6 changes: 6 additions & 0 deletions src/components/Media/Media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const b = block('Media');

export interface MediaAllProps extends MediaProps, VideoAdditionProps, ImageAdditionProps, QAProps {
className?: string;
isFullscreenImageCover?: boolean;
youtubeClassName?: string;
autoplay?: boolean;
onImageLoad?: () => void;
Expand All @@ -32,6 +33,7 @@ export const Media = (props: MediaAllProps) => {
previewImg,
parallax = false,
fullscreen,
isFullscreenImageCover,
analyticsEvents,
className,
imageClassName,
Expand Down Expand Up @@ -66,6 +68,9 @@ export const Media = (props: MediaAllProps) => {
disableImageSliderForArrayInput={disableImageSliderForArrayInput}
height={height}
imageClassName={imageClassName}
fullscreenClassName={
isFullscreenImageCover ? b('fullscreen-image-cover') : undefined
}
isBackground={isBackground}
video={video}
hasVideoFallback={hasVideoFallback}
Expand Down Expand Up @@ -137,6 +142,7 @@ export const Media = (props: MediaAllProps) => {
isBackground,
hasVideoFallback,
fullscreen,
isFullscreenImageCover,
qaAttributes.image,
qaAttributes.video,
onImageLoad,
Expand Down

0 comments on commit eec646d

Please sign in to comment.