Skip to content

Commit

Permalink
Merge pull request #287 from sima-land/286-product-carousel-image-ratio
Browse files Browse the repository at this point in the history
#286 ProductCarousel: учитывать неквадратные изображения товаров
  • Loading branch information
krutoo authored Aug 26, 2024
2 parents cec75ef + 24ac0dc commit 7cbfc3a
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { ProductCarousel } from '@sima-land/moleculas/desktop/components/product-carousel';
import { ProductInfo, Parts } from '@sima-land/moleculas/common/components/product-info';
import { ReactNode } from 'react';
import { Layout } from '@sima-land/ui-nucleons/layout';
import { Stepper } from '@sima-land/ui-nucleons/stepper';
import FavSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/Favorite';
import ComparisonAddSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/ComparisonAdd';
import { items } from './fixture';

export const meta = {
category: 'desktop/ProductCarousel',
title: 'Неквадратные картинки',
parameters: {
layout: 'fullscreen',
},
};

const Placeholder = () => (
<div style={{ borderRadius: 4, background: '#eee', height: 40, margin: '20px 0' }} />
);

const DemoBlock = ({ children }: { children: ReactNode }) => (
<Layout>
<Placeholder />
{children}
<Placeholder />
</Layout>
);

export default function CustomImageRatio() {
return (
<DemoBlock>
<ProductCarousel itemImageRatio={4 / 3}>
{items.map((item, index) => (
<ProductInfo key={index}>
<Parts.Image
images={[{ src: item.imageSrc }]}
href={item.url}
style={{
'--product-info-media-ratio': '4 / 3',
}}
>
<Parts.ImageButton
icon={FavSVG}
position={{ x: 'left', y: 'top' }}
hint='Добавить в избранное'
hintDirection='right'
/>
<Parts.ImageButton
icon={ComparisonAddSVG}
position={{ x: 'right', y: 'top' }}
hint='Добавить в сравнение'
hintDirection='left'
/>
</Parts.Image>

<Parts.Prices
price={item.price}
oldPrice={item.oldPrice}
currencyGrapheme={item.currencyGrapheme}
/>

<Parts.Title href={item.url}>{item.name}</Parts.Title>

<Parts.Footer>
<Parts.CartControl
stepText='По 5 шт'
markupText='Комплектация + 50 ₽ при покупке до 20 шт'
>
<Stepper defaultValue={3} size='s' style={{ width: '122px' }} />
</Parts.CartControl>
</Parts.Footer>
</ProductInfo>
))}
</ProductCarousel>
</DemoBlock>
);
}
17 changes: 17 additions & 0 deletions src/common/components/product-info/__test__/product-info.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import FavoriteSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/Favorite';
import MagnifierPlusSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/MagnifierPlus';
import { Badge } from '../../badge';
import { Stepper } from '@sima-land/ui-nucleons/stepper';
import { createRef } from 'react';

describe('ProductInfo', () => {
it('should render all parts', () => {
Expand Down Expand Up @@ -505,4 +506,20 @@ describe('ProductInfo', () => {
expect(queryAllByTestId('product-image-link')).toHaveLength(1);
expect(queryAllByTestId('product-image')).toHaveLength(0);
});

it('Parts.Image should handle "anchorRef" prop', () => {
const anchorRef = createRef<HTMLAnchorElement>();

render(
<ProductInfo>
<Parts.Image
images={[{ src: 'https://hello.world/img' }]}
href='https://www.sima-land.ru'
anchorRef={anchorRef}
/>
</ProductInfo>,
);

expect(anchorRef.current instanceof HTMLAnchorElement).toBe(true);
});
});
2 changes: 2 additions & 0 deletions src/common/components/product-info/parts/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function ProductInfoImage({
children,
anchorProps,
sliderProps,
anchorRef,
...restProps
}: ProductInfoImageProps) {
const { restriction } = useContext(ProductInfoContext);
Expand All @@ -34,6 +35,7 @@ export function ProductInfoImage({
<ProductInfoMedia {...restProps}>
<a
{...anchorProps}
ref={anchorRef}
data-testid='product-image-link'
href={adult ? undefined : href}
className={rootClassName}
Expand Down
4 changes: 4 additions & 0 deletions src/common/components/product-info/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ export interface ProductInfoImageProps extends ProductInfoMediaProps {
/** Картинки. */
images?: ProductImageProps[];

/** Реф элемента-ссылки. */
anchorRef?: Ref<HTMLAnchorElement>;

/** Прочие атрибуты элемента-ссылки. */
anchorProps?: AnchorHTMLAttributes<HTMLAnchorElement>;

/** Свойства слайдера. */
sliderProps?: HoverSliderProps;
}

Expand Down
8 changes: 6 additions & 2 deletions src/desktop/components/product-carousel/product-carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export function ProductCarousel({
onInViewport,
onNeedRequest,
children,
controlProps,
itemImageRatio = 1,
}: ProductCarouselProps) {
const layer = useLayer();
const needBigArrows = useMedia('(min-width: 1600px)');
Expand Down Expand Up @@ -82,10 +84,12 @@ export function ProductCarousel({
size: needBigArrows ? 'l' : 's',
style: {
zIndex: layer + 2, // чтобы кнопки были над HoverCard
top: `${itemWidth / 2}px`,
top: `${(itemWidth * itemImageRatio) / 2}px`,
...controlProps?.style,
},
...controlProps,
}
: undefined
: controlProps
}
renderItem={(item: ReactNode, realIndex) => (
<CarouselItem
Expand Down
7 changes: 7 additions & 0 deletions src/desktop/components/product-carousel/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { CSSProperties, ReactNode, RefObject } from 'react';
import type { CarouselProps } from '@sima-land/ui-nucleons/carousel';

export interface ItemSize {
xs?: 2 | 3 | 4;
Expand Down Expand Up @@ -29,6 +30,12 @@ export interface ProductCarouselProps {

/** Активирует "бесконечную" прокрутку карусели. */
infinite?: boolean;

/** Свойства стрелок. */
controlProps?: CarouselProps['controlProps'];

/** Отношение высоты картинки товара к ее ширине. Нужно для позиционирования стрелок. */
itemImageRatio?: number;
}

export interface HoverCardProps {
Expand Down

0 comments on commit 7cbfc3a

Please sign in to comment.