Skip to content

Commit a064393

Browse files
Add scrollable carousel for product cards and story this is for a full carousel. There will be a future PR for carousels with 2 cards + stories
1 parent 59030e6 commit a064393

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { ArticleFormat } from '../lib/articleFormat';
2+
import type { ProductBlockElement } from '../types/content';
3+
import { ProductCarouselCard } from './ProductCarouselCard';
4+
import type { FixedSlideWidth } from './ScrollableCarousel';
5+
import { CarouselKind, ScrollableCarousel } from './ScrollableCarousel';
6+
7+
export const ScrollableProduct = ({
8+
products,
9+
format,
10+
}: {
11+
products: ProductBlockElement[];
12+
format: ArticleFormat;
13+
}) => {
14+
const fixedCardWidth: FixedSlideWidth = {
15+
defaultWidth: 240,
16+
widthFromBreakpoints: [
17+
{ breakpoint: 'mobileMedium', width: 280 },
18+
{ breakpoint: 'tablet', width: 220 },
19+
],
20+
};
21+
return (
22+
<ScrollableCarousel
23+
isArticle={true}
24+
kind={CarouselKind.FixedWidthSlides}
25+
carouselLength={products.length}
26+
fixedSlideWidth={fixedCardWidth}
27+
gapSizes={{ row: 'none', column: 'large' }}
28+
>
29+
{products.map((product: ProductBlockElement) => (
30+
<ScrollableCarousel.SubgridItem
31+
key={product.productCtas[0]?.url ?? product.elementId}
32+
subgridRows={4}
33+
>
34+
<ProductCarouselCard product={product} format={format} />
35+
</ScrollableCarousel.SubgridItem>
36+
))}
37+
</ScrollableCarousel>
38+
);
39+
};
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { breakpoints } from '@guardian/source/foundations';
2+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
3+
import { centreColumnDecorator } from '../../.storybook/decorators/gridDecorators';
4+
import { exampleProduct } from '../../fixtures/manual/productBlockElement';
5+
import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat';
6+
import { ScrollableProduct } from './ScrollableProduct.importable';
7+
8+
const meta = {
9+
title: 'Article Carousel/Scrollable Products',
10+
component: ScrollableProduct,
11+
parameters: {
12+
chromatic: {
13+
viewports: [
14+
breakpoints.mobile,
15+
breakpoints.tablet,
16+
breakpoints.wide,
17+
],
18+
},
19+
},
20+
args: {
21+
products: [
22+
{ ...exampleProduct, h2Id: 'product' },
23+
{
24+
...exampleProduct,
25+
h2Id: 'product-1',
26+
productName: 'Lorem ipsum dolor sit amet',
27+
},
28+
{ ...exampleProduct, h2Id: 'product-2' },
29+
{ ...exampleProduct, h2Id: 'product-3' },
30+
{ ...exampleProduct, h2Id: 'product-4' },
31+
],
32+
format: {
33+
design: ArticleDesign.Review,
34+
display: ArticleDisplay.Standard,
35+
theme: Pillar.Lifestyle,
36+
},
37+
},
38+
decorators: [centreColumnDecorator],
39+
render: (args) => (
40+
<>
41+
<ScrollableProduct {...args} />
42+
<h1 style={{ fontSize: '50px' }} id={'product'}>
43+
Product 0
44+
</h1>
45+
<div style={{ fontSize: '20px' }}>
46+
The standard Lorem Ipsum passage, used since the 1500s
47+
</div>
48+
<h1 style={{ fontSize: '50px' }} id={'product-1'}>
49+
Product 1
50+
</h1>
51+
<div style={{ fontSize: '20px' }}>
52+
The standard Lorem Ipsum passage, used since the 1500s
53+
</div>
54+
<h1 style={{ fontSize: '50px' }} id={'product-2'}>
55+
Product 2
56+
</h1>
57+
<div style={{ fontSize: '20px' }}>
58+
The standard Lorem Ipsum passage, used since the 1500s
59+
</div>
60+
<h1 style={{ fontSize: '50px' }} id={'product-3'}>
61+
Product 3
62+
</h1>
63+
<div style={{ fontSize: '20px' }}>
64+
The standard Lorem Ipsum passage, used since the 1500s
65+
</div>
66+
<h1 style={{ fontSize: '50px' }} id={'product-4'}>
67+
Product 4
68+
</h1>
69+
<div style={{ fontSize: '20px', height: '100vh' }}>
70+
The standard Lorem Ipsum passage, used since the 1500s
71+
</div>
72+
</>
73+
),
74+
} satisfies Meta<typeof ScrollableProduct>;
75+
76+
export default meta;
77+
78+
type Story = StoryObj<typeof meta>;
79+
80+
export const With5Cards = {} satisfies Story;

0 commit comments

Comments
 (0)