From 7ff741cecb6c13d699176db579d458dc3fe7a410 Mon Sep 17 00:00:00 2001 From: Charley_Campbell Date: Fri, 28 Nov 2025 10:01:19 +0000 Subject: [PATCH 01/10] Adding new product card for the Carousel: - initial build of the card + a storybook - trying to ruse the product card buttons which required an override to be added as we want a different label on the button --- .../src/components/ProductCardButtons.tsx | 4 +- .../ProductCarouselCard.stories.tsx | 264 ++++++++++++++++++ .../src/components/ProductCarouselCard.tsx | 121 ++++++++ 3 files changed, 388 insertions(+), 1 deletion(-) create mode 100644 dotcom-rendering/src/components/ProductCarouselCard.stories.tsx create mode 100644 dotcom-rendering/src/components/ProductCarouselCard.tsx diff --git a/dotcom-rendering/src/components/ProductCardButtons.tsx b/dotcom-rendering/src/components/ProductCardButtons.tsx index 57ae0ea0c0f..02ab212fc8c 100644 --- a/dotcom-rendering/src/components/ProductCardButtons.tsx +++ b/dotcom-rendering/src/components/ProductCardButtons.tsx @@ -8,12 +8,14 @@ const getLabel = (cta: ProductCta): string => { export const ProductCardButtons = ({ productCtas, + buttonLabelOverride, }: { productCtas: ProductCta[]; + buttonLabelOverride?: string; }) => ( <> {productCtas.map((productCta, index) => { - const label = getLabel(productCta); + const label = buttonLabelOverride || getLabel(productCta); return ( Offering variable temperatures and a double-walled stainless-steel housing, the 3kW Sky is a brilliant blend of robust form and function. It boasts a low minimum boil (300ml), a keep-warm setting and touch controls.

', + elementId: '4a27eb68-6a03-4e82-a7d0-e4f1ef3ccb6f', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

Why we love it
I found it difficult to select a best kettle from so many that performed well, but the Bosch Sky clinched it because it’s such a good all-rounder that will suit most people. It pours well, has a button that’s within easy reach of the handle so it’s simple to open the lid without touching it, and it’s insulated so the exterior doesn’t become too hot to touch. From a design perspective, it has a more industrial feel than many others – no frippery here – but not too modern that it wouldn’t fit into most kitchens. Its display is thoughtfully designed, easy to keep clean and lights up as it heats.

', + elementId: 'f48f03d4-bece-4763-874b-4027a311643e', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

The exterior doesn’t get too hot (up to 40C), and while it wasn’t the fastest to boil in testing, it was only seconds behind the Dualit below. It clicked off at boiling point, and the water was still a toasty 78C 30 minutes later. At the hour point, it was 66C, and two hours 52C, meaning you’ll spend less time and energy reboiling.

', + elementId: 'df571922-33b1-416a-8b3d-ee756b638cc1', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

It’s a shame that … its premium look ends at the handle, which seems cheap and plasticky next to the sleek aesthetic of the rest of it.

', + elementId: 'd98fc724-8908-46e2-acc6-4739ad4d5719', + }, + ], +} satisfies ProductBlockElement; + +const meta = { + component: ProductCarouselCard, + title: 'Components/ProductCarouselCard', + args: { + product, + format: { + design: ArticleDesign.Standard, + display: ArticleDisplay.Standard, + theme: Pillar.Lifestyle, + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default = {} satisfies Story; diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx new file mode 100644 index 00000000000..9ed2f74fca0 --- /dev/null +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -0,0 +1,121 @@ +import { css } from '@emotion/react'; +import { + headlineBold20, + headlineMedium17, + lifestyle, + space, + textSansBold15, + textSansBold17, +} from '@guardian/source/foundations'; +import { ProductCardButtons } from './ProductCardButtons'; +import { ProductBlockElement } from '../types/content'; +import { Picture } from './Picture'; +import { ArticleFormat } from '../lib/articleFormat'; + +export type ProductCarouselCardProps = { + product: ProductBlockElement; + format: ArticleFormat; +}; + +const baseCard = css` + display: flex; + width: 280px; + flex-direction: column; + align-items: flex-start; + padding: 12px 10px 16px 10px; +`; + +const productCarouselCardHeading = css` + ${headlineBold20}; + color: ${lifestyle[300]}; +`; + +const brandAndProductName = css` + ${headlineMedium17}; +`; + +const readMoreCta = css` + ${textSansBold15}; + text-decoration-line: underline; + text-decoration-color: #dcdcdc; //TODO update this to use var(--Link-Pillar-color-link-underline-pillar, #DCDCDC); + color: ${lifestyle[400]}; + padding-bottom: ${space[2]}px; + text-underline-offset: 20%; /* 3px */ +`; + +const priceStyle = css` + ${textSansBold17}; + padding-top: ${space[1]}px; + padding-bottom: ${space[2]}px; +`; + +const buttonWrapper = css` + grid-area: buttons; + display: flex; + flex-direction: column; + gap: ${space[1]}px; + justify-content: center; + align-items: center; + align-self: stretch; +`; + +const imageArea = css` + display: flex; + flex-direction: column; + align-items: flex-start; + align-self: stretch; + aspect-ratio: 1 / 1; + height: 280px; + + img { + width: 100%; + height: 280px; + object-fit: contain; + } +`; + +export const ProductCarouselCard = ({ + product, + format, +}: ProductCarouselCardProps) => { + return ( +
+
+ {product.primaryHeadingHtml} +
+
+ {product.brandName} {product.productName} +
+
Read more
+
+ +
+
+ {product.productCtas && product.productCtas.length > 0 + ? product.productCtas[0]?.price ?? 'Price unavailable' + : 'Price unavailable'} +
+
+ 0 + ? `Buy at ${ + product.productCtas[0]?.retailer ?? + 'retailer' + }` + : 'Buy' + } + /> +
+
+ ); +}; From b393942d902fbacb9ede7857d4a080bb1a7c4727 Mon Sep 17 00:00:00 2001 From: Charley_Campbell Date: Mon, 1 Dec 2025 16:03:17 +0000 Subject: [PATCH 02/10] - Adds optional Read More which will anchor to the product element on the page when wired up - Additional tweaks so the card is more aligned with the Figma designs - Added logic when there is no heading to put the product and brand name under the image on seperate lines - Added logic to handle when the product/brand name is longer than one line and needs to wrap - Using the ProductCardImage instead of Picture for consistency across these elements but happy to change it back again or discuss further - Added more storybooks --- .../ProductCarouselCard.stories.tsx | 36 ++++++++++ .../src/components/ProductCarouselCard.tsx | 67 +++++++++++++------ 2 files changed, 84 insertions(+), 19 deletions(-) diff --git a/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx b/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx index fcf285ec9fe..0ee3c28c85a 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx @@ -254,6 +254,7 @@ const meta = { display: ArticleDisplay.Standard, theme: Pillar.Lifestyle, }, + showReadMore: true, }, } satisfies Meta; @@ -262,3 +263,38 @@ export default meta; type Story = StoryObj; export const Default = {} satisfies Story; + +export const WithoutReadMore = { + args: { + showReadMore: false, + }, +} satisfies Story; + +export const WithoutHeadingDisclaimerOrReadMore = { + args: { + product: { + ...product, + primaryHeadingHtml: '', + }, + showReadMore: false, + }, +} satisfies Story; + +export const WithLongHeadingProductNameAndCTA = { + args: { + product: { + ...product, + primaryHeadingHtml: 'Super long product category review name', + productName: + 'Sky Kettle with a super duper long name that goes on and on', + productCtas: [ + { + url: 'https://www.johnlewis.com/bosch-twk7203gb-sky-variable-temperature-kettle-1-7l-black/p3228625', + text: '', + retailer: 'John Lewis with a very long name', + price: '£45.99', + }, + ], + }, + }, +}; diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index 9ed2f74fca0..40b79aeb43a 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -4,17 +4,19 @@ import { headlineMedium17, lifestyle, space, + textSans17, textSansBold15, textSansBold17, } from '@guardian/source/foundations'; import { ProductCardButtons } from './ProductCardButtons'; import { ProductBlockElement } from '../types/content'; -import { Picture } from './Picture'; import { ArticleFormat } from '../lib/articleFormat'; +import { ProductCardImage } from './ProductCardImage'; export type ProductCarouselCardProps = { product: ProductBlockElement; format: ArticleFormat; + showReadMore?: boolean; }; const baseCard = css` @@ -22,7 +24,7 @@ const baseCard = css` width: 280px; flex-direction: column; align-items: flex-start; - padding: 12px 10px 16px 10px; + padding: ${space[3]}px 10px ${space[4]}px 10px; `; const productCarouselCardHeading = css` @@ -39,8 +41,8 @@ const readMoreCta = css` text-decoration-line: underline; text-decoration-color: #dcdcdc; //TODO update this to use var(--Link-Pillar-color-link-underline-pillar, #DCDCDC); color: ${lifestyle[400]}; + text-underline-offset: 20%; padding-bottom: ${space[2]}px; - text-underline-offset: 20%; /* 3px */ `; const priceStyle = css` @@ -70,34 +72,61 @@ const imageArea = css` img { width: 100%; height: 280px; - object-fit: contain; + object-fit: cover; } `; +const brandAndProductNameRow = css` + display: block; + line-height: 1.3; +`; + +const brandAndProductNameInline = css` + ${headlineMedium17}; + display: inline; +`; + +const productNameStyle = css` + ${textSans17}; +`; + export const ProductCarouselCard = ({ product, format, + showReadMore, }: ProductCarouselCardProps) => { + const hasHeading = !!product.primaryHeadingHtml; return (
-
- {product.primaryHeadingHtml} -
-
- {product.brandName} {product.productName} -
-
Read more
+ {hasHeading && ( + <> +
+ {product.primaryHeadingHtml} +
+
+ + {product.brandName}{' '} + + + {product.productName} + +
+ + )} + {showReadMore &&
Read more
}
-
+ {!hasHeading && ( +
+
{product.brandName}
+
{product.productName}
+
+ )}
{product.productCtas && product.productCtas.length > 0 ? product.productCtas[0]?.price ?? 'Price unavailable' @@ -112,7 +141,7 @@ export const ProductCarouselCard = ({ product.productCtas[0]?.retailer ?? 'retailer' }` - : 'Buy' + : 'Buy' //TODO better fallback? } />
From c9f60231f75b8dedd996a509525a4e6c62d88bce Mon Sep 17 00:00:00 2001 From: Charley_Campbell Date: Mon, 1 Dec 2025 16:41:53 +0000 Subject: [PATCH 03/10] fixing linting errors which failed the build --- .../src/components/ProductCardButtons.tsx | 2 +- .../ProductCarouselCard.stories.tsx | 4 ++-- .../src/components/ProductCarouselCard.tsx | 23 ++++++++----------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/dotcom-rendering/src/components/ProductCardButtons.tsx b/dotcom-rendering/src/components/ProductCardButtons.tsx index 02ab212fc8c..a627fadba0a 100644 --- a/dotcom-rendering/src/components/ProductCardButtons.tsx +++ b/dotcom-rendering/src/components/ProductCardButtons.tsx @@ -15,7 +15,7 @@ export const ProductCardButtons = ({ }) => ( <> {productCtas.map((productCta, index) => { - const label = buttonLabelOverride || getLabel(productCta); + const label = buttonLabelOverride ?? getLabel(productCta); return ( { const hasHeading = !!product.primaryHeadingHtml; + + const firstCta = product.productCtas[0]; + return (
{hasHeading && ( @@ -127,21 +130,13 @@ export const ProductCarouselCard = ({
{product.productName}
)} -
- {product.productCtas && product.productCtas.length > 0 - ? product.productCtas[0]?.price ?? 'Price unavailable' - : 'Price unavailable'} -
+
{firstCta?.price ?? 'Price unavailable'}
+
0 - ? `Buy at ${ - product.productCtas[0]?.retailer ?? - 'retailer' - }` - : 'Buy' //TODO better fallback? + firstCta ? `Buy at ${firstCta.retailer}` : 'Buy' } />
From b5a46fa8b25516cd69697cd688a3540eb1fe0bf1 Mon Sep 17 00:00:00 2001 From: Charley_Campbell Date: Mon, 1 Dec 2025 16:53:56 +0000 Subject: [PATCH 04/10] fixing style lint build --- dotcom-rendering/src/components/ProductCarouselCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index 3d7842e32fa..378c1fac391 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -39,7 +39,7 @@ const brandAndProductName = css` const readMoreCta = css` ${textSansBold15}; text-decoration-line: underline; - text-decoration-color: #dcdcdc; //TODO update this to use var(--Link-Pillar-color-link-underline-pillar, #DCDCDC); + text-decoration-color: #dcdcdc; /* stylelint-disable-line */ color: ${lifestyle[400]}; text-underline-offset: 20%; padding-bottom: ${space[2]}px; From 69f98eba95b9fca38038640c628d9f1a57b0a05a Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 10:59:56 +0000 Subject: [PATCH 05/10] WIP add carousel --- .../ProductCarouselCard.stories.tsx | 10 + .../src/components/ProductCarouselCard.tsx | 35 +-- .../src/components/ScrollableCarousel.tsx | 106 +++---- .../ScrollableProduct.importable.tsx | 35 +++ .../components/ScrollableProducts.stories.tsx | 286 ++++++++++++++++++ 5 files changed, 394 insertions(+), 78 deletions(-) create mode 100644 dotcom-rendering/src/components/ScrollableProduct.importable.tsx create mode 100644 dotcom-rendering/src/components/ScrollableProducts.stories.tsx diff --git a/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx b/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx index 9a00802db7c..983c8686e0d 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.stories.tsx @@ -1,3 +1,4 @@ +import { css } from '@emotion/react'; import type { Meta, StoryObj } from '@storybook/react-webpack5'; import { productImage } from '../../fixtures/manual/productImage'; import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat'; @@ -256,6 +257,15 @@ const meta = { }, showReadMore: true, }, + render: (args) => ( +
+ , +
+ ), } satisfies Meta; export default meta; diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index 378c1fac391..4c2f3a2c984 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -1,4 +1,5 @@ import { css } from '@emotion/react'; +import { isUndefined } from '@guardian/libs'; import { headlineBold20, headlineMedium17, @@ -21,10 +22,7 @@ export type ProductCarouselCardProps = { const baseCard = css` display: flex; - width: 280px; flex-direction: column; - align-items: flex-start; - padding: ${space[3]}px 10px ${space[4]}px 10px; `; const productCarouselCardHeading = css` @@ -52,38 +50,24 @@ const priceStyle = css` `; const buttonWrapper = css` - grid-area: buttons; display: flex; flex-direction: column; gap: ${space[1]}px; - justify-content: center; - align-items: center; - align-self: stretch; `; const imageArea = css` - display: flex; - flex-direction: column; - align-items: flex-start; - align-self: stretch; - aspect-ratio: 1 / 1; - height: 280px; - img { width: 100%; - height: 280px; - object-fit: cover; + height: auto; } `; const brandAndProductNameRow = css` - display: block; line-height: 1.3; `; const brandAndProductNameInline = css` ${headlineMedium17}; - display: inline; `; const productNameStyle = css` @@ -103,9 +87,12 @@ export const ProductCarouselCard = ({
{hasHeading && ( <> -
- {product.primaryHeadingHtml} -
+
{product.brandName}{' '} @@ -116,7 +103,11 @@ export const ProductCarouselCard = ({
)} - {showReadMore &&
Read more
} + {showReadMore && !isUndefined(product.h2Id) && ( + + Read more + + )}
{ @@ -157,13 +131,15 @@ const stackedCardRowsStyles = ({ * @param {number} totalCards - The total number of cards in the carousel. * @param {number} visibleCarouselSlidesOnMobile - Number of cards to show at once on mobile. * @param {number} visibleCarouselSlidesOnTablet - Number of cards to show at once on tablet. + * @param fixedCardWidthOverrides - An alternative method for deciding the width of cards at various breakpoints * @returns {string} - The CSS styles for the grid layout. */ const generateCarouselColumnStyles = ( totalCards: number, visibleCarouselSlidesOnMobile: number, visibleCarouselSlidesOnTablet: number, -) => { + fixedCardWidthOverrides?: FixedWidthOverride[], +): SerializedStyles[] => { const peepingCardWidth = space[8]; const cardGap = 20; const offsetPeepingCardWidth = @@ -171,9 +147,24 @@ const generateCarouselColumnStyles = ( const offsetCardGap = (cardGap * (visibleCarouselSlidesOnTablet - 1)) / visibleCarouselSlidesOnTablet; + const fixedWidths: SerializedStyles[] = []; + if (!isUndefined(fixedCardWidthOverrides)) { + for (const fixedCardWidthOverride of fixedCardWidthOverrides) { + fixedWidths.push(css` + ${from[fixedCardWidthOverride.breakpoint]} { + grid-template-columns: repeat( + ${totalCards}, + ${fixedCardWidthOverride.width}px + ); + } + `); + } + return fixedWidths; + } - return css` - /** + return [ + css` + /** * On mobile a 32px slice of the next card is shown to indicate there * are more cards that can be scrolled to. Extra padding is also added * to the left and right to align cards with the page grid as the @@ -182,34 +173,35 @@ const generateCarouselColumnStyles = ( * These values are divided by the number of visible cards and * subtracted from their width so they are shown at the correct size. */ - grid-template-columns: repeat( - ${totalCards}, - calc( - (100% / ${visibleCarouselSlidesOnMobile}) - - ${offsetPeepingCardWidth}px + - ${gridGapMobile / visibleCarouselSlidesOnMobile}px - ) - ); - ${from.mobileLandscape} { grid-template-columns: repeat( ${totalCards}, calc( (100% / ${visibleCarouselSlidesOnMobile}) - ${offsetPeepingCardWidth}px + - ${gridGap / visibleCarouselSlidesOnMobile}px - ) - ); - } - ${from.tablet} { - grid-template-columns: repeat( - ${totalCards}, - calc( - (${100 / visibleCarouselSlidesOnTablet}%) - - ${offsetCardGap}px + ${gridGapMobile / visibleCarouselSlidesOnMobile}px ) ); - } - `; + ${from.mobileLandscape} { + grid-template-columns: repeat( + ${totalCards}, + calc( + (100% / ${visibleCarouselSlidesOnMobile}) - + ${offsetPeepingCardWidth}px + + ${gridGap / visibleCarouselSlidesOnMobile}px + ) + ); + } + ${from.tablet} { + grid-template-columns: repeat( + ${totalCards}, + calc( + (${100 / visibleCarouselSlidesOnTablet}%) - + ${offsetCardGap}px + ) + ); + } + `, + ]; }; const getGapSize = (gap: GapSize) => { @@ -231,6 +223,7 @@ export const ScrollableCarousel = ({ carouselLength, visibleCarouselSlidesOnMobile, visibleCarouselSlidesOnTablet, + fixedCardWidthOverrides, sectionId, shouldStackCards = { desktop: false, mobile: false }, gapSizes = { column: 'large', row: 'large' }, @@ -374,10 +367,11 @@ export const ScrollableCarousel = ({ css={[ carouselStyles, carouselGapStyles(columnGap, rowGap), - generateCarouselColumnStyles( + ...generateCarouselColumnStyles( carouselLength, visibleCarouselSlidesOnMobile, visibleCarouselSlidesOnTablet, + fixedCardWidthOverrides, ), stackedCardRowsStyles(shouldStackCards), ]} diff --git a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx new file mode 100644 index 00000000000..a299abe6359 --- /dev/null +++ b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx @@ -0,0 +1,35 @@ +import type { ArticleFormat } from '../lib/articleFormat'; +import type { ProductBlockElement } from '../types/content'; +import { ProductCarouselCard } from './ProductCarouselCard'; +import type { FixedWidthOverride } from './ScrollableCarousel'; +import { ScrollableCarousel } from './ScrollableCarousel'; + +export const ScrollableProduct = ({ + products, + format, +}: { + products: ProductBlockElement[]; + format: ArticleFormat; +}) => { + const fixedWidthOverrides: FixedWidthOverride[] = [ + { breakpoint: 'mobile', width: 240 }, + { breakpoint: 'mobileMedium', width: 280 }, + { breakpoint: 'tablet', width: 220 }, + ]; + return ( + + {products.map((product: ProductBlockElement) => ( + + + + ))} + + ); +}; diff --git a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx new file mode 100644 index 00000000000..5a384ba2f93 --- /dev/null +++ b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx @@ -0,0 +1,286 @@ +import { breakpoints } from '@guardian/source/foundations'; +import type { Meta, StoryObj } from '@storybook/react-webpack5'; +import { centreColumnDecorator } from '../../.storybook/decorators/gridDecorators'; +import { productImage } from '../../fixtures/manual/productImage'; +import { ArticleDesign, ArticleDisplay, Pillar } from '../lib/articleFormat'; +import type { ProductBlockElement } from '../types/content'; +import { ScrollableProduct } from './ScrollableProduct.importable'; + +const product = { + _type: 'model.dotcomrendering.pageElements.ProductBlockElement', + elementId: 'b1f6e8e2-3f3a-4f0c-8d1e-5f3e3e3e3e3e', + primaryHeadingHtml: 'Best Kettle overall', + secondaryHeadingHtml: 'Bosch Sky Kettle', + brandName: 'Bosch', + productName: 'Sky Kettle', + image: productImage, + displayType: 'InlineWithProductCard', + lowestPrice: '£39.99', + customAttributes: [ + { name: 'What we love', value: 'It pours well and looks great' }, + { + name: "What we don't love", + value: 'The handle feels a bit cheap compared to the rest of it', + }, + ], + productCtas: [ + { + url: 'https://www.johnlewis.com/bosch-twk7203gb-sky-variable-temperature-kettle-1-7l-black/p3228625', + text: '', + retailer: 'John Lewis', + price: '£45.99', + }, + { + url: 'https://www.amazon.co.uk/Bosch-TWK7203GB-Sky-Variable-Temperature/dp/B07Z8VQ2V6', + text: '', + retailer: 'Amazon', + price: '£39.99', + }, + ], + starRating: 'none-selected', + content: [ + { + displayCredit: true, + _type: 'model.dotcomrendering.pageElements.ImageBlockElement', + role: 'inline', + media: { + allImages: [ + { + index: 0, + fields: { + height: '3213', + width: '3213', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/3213.jpg', + }, + { + index: 1, + fields: { + isMaster: 'true', + height: '3213', + width: '3213', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + }, + { + index: 2, + fields: { + height: '2000', + width: '2000', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/2000.jpg', + }, + { + index: 3, + fields: { + height: '1000', + width: '1000', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/1000.jpg', + }, + { + index: 4, + fields: { + height: '500', + width: '500', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/500.jpg', + }, + { + index: 5, + fields: { + height: '140', + width: '140', + }, + mediaType: 'Image', + mimeType: 'image/jpeg', + url: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/140.jpg', + }, + ], + }, + elementId: '76686aa1-2e47-4616-b4ed-a88d0afe07ed', + imageSources: [ + { + weighting: 'inline', + srcSet: [ + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 620, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 1240, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 605, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 1210, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 445, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 890, + }, + ], + }, + { + weighting: 'thumbnail', + srcSet: [ + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 140, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 280, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 120, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 240, + }, + ], + }, + { + weighting: 'supporting', + srcSet: [ + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 380, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 760, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 300, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 600, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 620, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 1240, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 605, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 1210, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 445, + }, + { + src: 'https://media.guimcode.co.uk/bacede2d976c26d6a224ede074d5634a3f1d304f/0_0_3213_3213/master/3213.jpg', + width: 890, + }, + ], + }, + ], + data: { + alt: 'Testing Bosch Sky Kettle', + credit: 'Photograph: Rachel Ogden/The Guardian', + }, + }, + { + _type: 'model.dotcomrendering.pageElements.LinkBlockElement', + url: 'https://www.johnlewis.com/bosch-twk7203gb-sky-variable-temperature-kettle-1-7l-black/p3228625', + label: '£79.99 at John Lewis', + linkType: 'ProductButton', + }, + { + _type: 'model.dotcomrendering.pageElements.LinkBlockElement', + url: 'https://www.amazon.co.uk/Bosch-TWK7203GB-Sky-Variable-Temperature/dp/B07Z8VQ2V6', + label: '£79.99 at Amazon', + linkType: 'ProductButton', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

Offering variable temperatures and a double-walled stainless-steel housing, the 3kW Sky is a brilliant blend of robust form and function. It boasts a low minimum boil (300ml), a keep-warm setting and touch controls.

', + elementId: '4a27eb68-6a03-4e82-a7d0-e4f1ef3ccb6f', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

Why we love it
I found it difficult to select a best kettle from so many that performed well, but the Bosch Sky clinched it because it’s such a good all-rounder that will suit most people. It pours well, has a button that’s within easy reach of the handle so it’s simple to open the lid without touching it, and it’s insulated so the exterior doesn’t become too hot to touch. From a design perspective, it has a more industrial feel than many others – no frippery here – but not too modern that it wouldn’t fit into most kitchens. Its display is thoughtfully designed, easy to keep clean and lights up as it heats.

', + elementId: 'f48f03d4-bece-4763-874b-4027a311643e', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

The exterior doesn’t get too hot (up to 40C), and while it wasn’t the fastest to boil in testing, it was only seconds behind the Dualit below. It clicked off at boiling point, and the water was still a toasty 78C 30 minutes later. At the hour point, it was 66C, and two hours 52C, meaning you’ll spend less time and energy reboiling.

', + elementId: 'df571922-33b1-416a-8b3d-ee756b638cc1', + }, + { + _type: 'model.dotcomrendering.pageElements.TextBlockElement', + html: '

It’s a shame that … its premium look ends at the handle, which seems cheap and plasticky next to the sleek aesthetic of the rest of it.

', + elementId: 'd98fc724-8908-46e2-acc6-4739ad4d5719', + }, + ], +} satisfies ProductBlockElement; + +const meta = { + title: 'Article Carousel/Scrollable Products', + component: ScrollableProduct, + parameters: { + chromatic: { + viewports: [ + breakpoints.mobile, + breakpoints.tablet, + breakpoints.wide, + ], + }, + }, + args: { + products: [ + product, + { + ...product, + productName: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', + }, + product, + product, + product, + ], + format: { + design: ArticleDesign.Review, + display: ArticleDisplay.Standard, + theme: Pillar.Lifestyle, + }, + }, + decorators: [centreColumnDecorator], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const With5Cards = {} satisfies Story; From e6a7d6f4098e68f1705a846c56d9e2d2e35ed3f4 Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 16:10:43 +0000 Subject: [PATCH 06/10] add subgrid functionality --- .../src/components/ProductCarouselCard.tsx | 100 ++++---- .../src/components/ScrollableCarousel.tsx | 34 ++- .../ScrollableProduct.importable.tsx | 12 +- .../components/ScrollableProducts.stories.tsx | 241 ++++++++++++++++++ 4 files changed, 340 insertions(+), 47 deletions(-) diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index 4c2f3a2c984..be3ff507111 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -20,11 +20,6 @@ export type ProductCarouselCardProps = { showReadMore?: boolean; }; -const baseCard = css` - display: flex; - flex-direction: column; -`; - const productCarouselCardHeading = css` ${headlineBold20}; color: ${lifestyle[300]}; @@ -56,6 +51,7 @@ const buttonWrapper = css` `; const imageArea = css` + grid-row: 2; img { width: 100%; height: auto; @@ -84,30 +80,40 @@ export const ProductCarouselCard = ({ const firstCta = product.productCtas[0]; return ( -
- {hasHeading && ( - <> -
-
- - {product.brandName}{' '} - - - {product.productName} - -
- - )} - {showReadMore && !isUndefined(product.h2Id) && ( - - Read more - - )} + <> +
+ {hasHeading && ( + <> +
+
+ + {product.brandName}{' '} + + + {product.productName} + +
+ + )} + {showReadMore && !isUndefined(product.h2Id) && ( + event.stopPropagation()} + css={readMoreCta} + > + Read more + + )} +
- {!hasHeading && ( -
-
{product.brandName}
-
{product.productName}
+
+ {!hasHeading && ( +
+
{product.brandName}
+
{product.productName}
+
+ )} +
+ {firstCta?.price ?? 'Price unavailable'}
- )} -
{firstCta?.price ?? 'Price unavailable'}
-
- +
+ +
-
+ ); }; diff --git a/dotcom-rendering/src/components/ScrollableCarousel.tsx b/dotcom-rendering/src/components/ScrollableCarousel.tsx index 914ddb34f86..dc65ffcab94 100644 --- a/dotcom-rendering/src/components/ScrollableCarousel.tsx +++ b/dotcom-rendering/src/components/ScrollableCarousel.tsx @@ -8,7 +8,7 @@ import { nestedOphanComponents } from '../lib/ophan-helpers'; import { palette } from '../palette'; import { CarouselNavigationButtons } from './CarouselNavigationButtons'; -type GapSize = 'small' | 'medium' | 'large'; +type GapSize = 'small' | 'medium' | 'large' | 'none'; type GapSizes = { row: GapSize; column: GapSize }; export type FixedWidthOverride = { breakpoint: Breakpoint; width: number }; @@ -71,6 +71,18 @@ const carouselGapStyles = (column: number, row: number) => { `; }; +const subgridStyles = ({ subgridRows }: { subgridRows: number }) => css` + scroll-snap-align: start; + position: relative; + display: grid; + @supports (grid-template-rows: subgrid) { + grid-column: span 1; + grid-row: span ${subgridRows}; + grid-template-rows: subgrid; + grid-template-columns: subgrid; + } +`; + const itemStyles = css` display: flex; scroll-snap-align: start; @@ -212,6 +224,8 @@ const getGapSize = (gap: GapSize) => { return space[4]; case 'large': return space[5]; + case 'none': + return 0; } }; @@ -420,3 +434,21 @@ ScrollableCarousel.Item = ({ {children} ); + +ScrollableCarousel.SubgridItem = ({ + subgridRows, + children, +}: { + subgridRows: number; + children: React.ReactNode; +}) => ( +
  • + {children} +
  • +); diff --git a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx index a299abe6359..6b023af2373 100644 --- a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx +++ b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx @@ -22,13 +22,19 @@ export const ScrollableProduct = ({ visibleCarouselSlidesOnMobile={1.2} visibleCarouselSlidesOnTablet={2.666666} fixedCardWidthOverrides={fixedWidthOverrides} + gapSizes={{ row: 'none', column: 'large' }} > {products.map((product: ProductBlockElement) => ( - - - + + ))} ); diff --git a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx index 5a384ba2f93..80d6d6b7712 100644 --- a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx +++ b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx @@ -263,6 +263,7 @@ const meta = { product, { ...product, + h2Id: 'product-1', productName: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', }, @@ -277,6 +278,246 @@ const meta = { }, }, decorators: [centreColumnDecorator], + render: (args) => ( + <> + , +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +

    Product 1

    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    +
    + The standard Lorem Ipsum passage, used since the 1500s "Lorem + ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut + enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor + in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, + sunt in culpa qui officia deserunt mollit anim id est laborum." + Section 1.10.32 of "de Finibus Bonorum et Malorum", written by + Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error + sit voluptatem accusantium doloremque laudantium, totam rem + aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam + voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed + quia consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" +
    + + ), } satisfies Meta; export default meta; From 30978584271094522160c6244a495258b84294b2 Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 16:22:20 +0000 Subject: [PATCH 07/10] undo some un needed changes --- .../src/components/ScrollableCarousel.tsx | 84 +++++++++++++------ 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/dotcom-rendering/src/components/ScrollableCarousel.tsx b/dotcom-rendering/src/components/ScrollableCarousel.tsx index dc65ffcab94..49ee294675e 100644 --- a/dotcom-rendering/src/components/ScrollableCarousel.tsx +++ b/dotcom-rendering/src/components/ScrollableCarousel.tsx @@ -42,6 +42,19 @@ const gridGapMobile = 10; */ const containerStyles = css` position: relative; + margin-left: -${gridGapMobile}px; + margin-right: -${gridGapMobile}px; + ${from.mobileLandscape} { + margin-left: -${gridGap}px; + margin-right: -${gridGap}px; + } + ${from.tablet} { + margin-left: ${gridGap / 2}px; + margin-right: ${gridGap / 2}px; + } + ${from.leftCol} { + margin-left: 0; + } `; const carouselStyles = css` @@ -62,6 +75,24 @@ const carouselStyles = css` display: none; /* Safari and Chrome */ } scrollbar-width: none; /* Firefox */ + + padding-left: ${gridGapMobile}px; + padding-right: ${gridGapMobile}px; + scroll-padding-left: ${gridGapMobile}px; + ${from.mobileLandscape} { + padding-left: ${gridGap}px; + padding-right: ${gridGap}px; + scroll-padding-left: ${gridGap}px; + } + ${from.tablet} { + padding-left: 0; + padding-right: 0; + scroll-padding-left: 0; + } + ${from.leftCol} { + padding-left: ${gridGap / 2}px; + scroll-padding-left: ${gridGap / 2}px; + } `; const carouselGapStyles = (column: number, row: number) => { @@ -151,7 +182,7 @@ const generateCarouselColumnStyles = ( visibleCarouselSlidesOnMobile: number, visibleCarouselSlidesOnTablet: number, fixedCardWidthOverrides?: FixedWidthOverride[], -): SerializedStyles[] => { +): SerializedStyles[] | SerializedStyles => { const peepingCardWidth = space[8]; const cardGap = 20; const offsetPeepingCardWidth = @@ -160,6 +191,7 @@ const generateCarouselColumnStyles = ( (cardGap * (visibleCarouselSlidesOnTablet - 1)) / visibleCarouselSlidesOnTablet; const fixedWidths: SerializedStyles[] = []; + if (!isUndefined(fixedCardWidthOverrides)) { for (const fixedCardWidthOverride of fixedCardWidthOverrides) { fixedWidths.push(css` @@ -174,9 +206,8 @@ const generateCarouselColumnStyles = ( return fixedWidths; } - return [ - css` - /** + return css` + /** * On mobile a 32px slice of the next card is shown to indicate there * are more cards that can be scrolled to. Extra padding is also added * to the left and right to align cards with the page grid as the @@ -185,35 +216,34 @@ const generateCarouselColumnStyles = ( * These values are divided by the number of visible cards and * subtracted from their width so they are shown at the correct size. */ + grid-template-columns: repeat( + ${totalCards}, + calc( + (100% / ${visibleCarouselSlidesOnMobile}) - + ${offsetPeepingCardWidth}px + + ${gridGapMobile / visibleCarouselSlidesOnMobile}px + ) + ); + ${from.mobileLandscape} { grid-template-columns: repeat( ${totalCards}, calc( (100% / ${visibleCarouselSlidesOnMobile}) - ${offsetPeepingCardWidth}px + - ${gridGapMobile / visibleCarouselSlidesOnMobile}px + ${gridGap / visibleCarouselSlidesOnMobile}px ) ); - ${from.mobileLandscape} { - grid-template-columns: repeat( - ${totalCards}, - calc( - (100% / ${visibleCarouselSlidesOnMobile}) - - ${offsetPeepingCardWidth}px + - ${gridGap / visibleCarouselSlidesOnMobile}px - ) - ); - } - ${from.tablet} { - grid-template-columns: repeat( - ${totalCards}, - calc( - (${100 / visibleCarouselSlidesOnTablet}%) - - ${offsetCardGap}px - ) - ); - } - `, - ]; + } + ${from.tablet} { + grid-template-columns: repeat( + ${totalCards}, + calc( + (${100 / visibleCarouselSlidesOnTablet}%) - + ${offsetCardGap}px + ) + ); + } + `; }; const getGapSize = (gap: GapSize) => { @@ -381,7 +411,7 @@ export const ScrollableCarousel = ({ css={[ carouselStyles, carouselGapStyles(columnGap, rowGap), - ...generateCarouselColumnStyles( + generateCarouselColumnStyles( carouselLength, visibleCarouselSlidesOnMobile, visibleCarouselSlidesOnTablet, From f2ba8632708fb4b8f136135260eeb1388a356ea3 Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 16:33:16 +0000 Subject: [PATCH 08/10] improve padding --- dotcom-rendering/src/components/ProductCarouselCard.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index be3ff507111..49d9772d019 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -48,9 +48,12 @@ const buttonWrapper = css` display: flex; flex-direction: column; gap: ${space[1]}px; + padding-bottom: ${space[4]}px; `; const imageArea = css` + padding-top: ${space[2]}px; + padding-bottom: ${space[1]}px; grid-row: 2; img { width: 100%; From 95e00e49f26a520982b2d528684168378b90354c Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 16:40:26 +0000 Subject: [PATCH 09/10] add headlines to story --- .../components/ScrollableProducts.stories.tsx | 781 ++++++++++++++++-- 1 file changed, 720 insertions(+), 61 deletions(-) diff --git a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx index 80d6d6b7712..53691b809ba 100644 --- a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx +++ b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx @@ -260,16 +260,16 @@ const meta = { }, args: { products: [ - product, + { ...product, h2Id: 'product' }, { ...product, h2Id: 'product-1', productName: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', + 'Lorem ipsum dolor sit amet, consectetur adipiscing aliqua', }, - product, - product, - product, + { ...product, h2Id: 'product-2' }, + { ...product, h2Id: 'product-3' }, + { ...product, h2Id: 'product-4' }, ], format: { design: ArticleDesign.Review, @@ -280,7 +280,10 @@ const meta = { decorators: [centreColumnDecorator], render: (args) => ( <> - , + +

    + Product 0 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -305,24 +308,22 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo - voluptas nulla pariatur?" -
    -
    - The standard Lorem Ipsum passage, used since the 1500s "Lorem - ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor - in reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum." - Section 1.10.32 of "de Finibus Bonorum et Malorum", written by - Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error - sit voluptatem accusantium doloremque laudantium, totam rem - aperiam, eaque ipsa quae ab illo inventore veritatis et quasi - architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam - voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed - quia consequuntur magni dolores eos qui ratione voluptatem sequi + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat @@ -331,24 +332,22 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo - voluptas nulla pariatur?" -
    -
    - The standard Lorem Ipsum passage, used since the 1500s "Lorem - ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor - in reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum." - Section 1.10.32 of "de Finibus Bonorum et Malorum", written by - Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error - sit voluptatem accusantium doloremque laudantium, totam rem - aperiam, eaque ipsa quae ab illo inventore veritatis et quasi - architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam - voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed - quia consequuntur magni dolores eos qui ratione voluptatem sequi + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat @@ -357,25 +356,70 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo - voluptas nulla pariatur?" -
    -

    Product 1

    -
    - The standard Lorem Ipsum passage, used since the 1500s "Lorem - ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor - in reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum." - Section 1.10.32 of "de Finibus Bonorum et Malorum", written by - Cicero in 45 BC "Sed ut perspiciatis unde omnis iste natus error - sit voluptatem accusantium doloremque laudantium, totam rem - aperiam, eaque ipsa quae ab illo inventore veritatis et quasi - architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam - voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed - quia consequuntur magni dolores eos qui ratione voluptatem sequi + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat @@ -386,6 +430,9 @@ const meta = { molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    +

    + Product 1 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -410,8 +457,131 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    +

    + Product 2 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -436,8 +606,131 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    +

    + Product 3 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -462,8 +755,131 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    +

    + Product 4 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -488,8 +904,131 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    +

    + Product 5 +

    The standard Lorem Ipsum passage, used since the 1500s "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do @@ -514,6 +1053,126 @@ const meta = { aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo + voluptas nulla pariatur?" The standard Lorem Ipsum passage, used + since the 1500s "Lorem ipsum dolor sit amet, consectetur + adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate + velit esse cillum dolore eu fugiat nulla pariatur. Excepteur + sint occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum." Section 1.10.32 of "de + Finibus Bonorum et Malorum", written by Cicero in 45 BC "Sed ut + perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae + vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia + voluptas sit aspernatur aut odit aut fugit, sed quia + consequuntur magni dolores eos qui ratione voluptatem sequi + nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor + sit amet, consectetur, adipisci velit, sed quia non numquam eius + modi tempora incidunt ut labore et dolore magnam aliquam quaerat + voluptatem. Ut enim ad minima veniam, quis nostrum + exercitationem ullam corporis suscipit laboriosam, nisi ut + aliquid ex ea commodi consequatur? Quis autem vel eum iure + reprehenderit qui in ea voluptate velit esse quam nihil + molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"
    From 5032596c2182be152a479e6b1e3c244f59f97453 Mon Sep 17 00:00:00 2001 From: ollie_abrahams Date: Thu, 4 Dec 2025 16:44:55 +0000 Subject: [PATCH 10/10] align read mores --- .../src/components/ProductCarouselCard.tsx | 24 +++++++++---------- .../ScrollableProduct.importable.tsx | 2 +- .../components/ScrollableProducts.stories.tsx | 3 +-- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/dotcom-rendering/src/components/ProductCarouselCard.tsx b/dotcom-rendering/src/components/ProductCarouselCard.tsx index 49d9772d019..07ed36c8b49 100644 --- a/dotcom-rendering/src/components/ProductCarouselCard.tsx +++ b/dotcom-rendering/src/components/ProductCarouselCard.tsx @@ -30,6 +30,7 @@ const brandAndProductName = css` `; const readMoreCta = css` + grid-row: 2; ${textSansBold15}; text-decoration-line: underline; text-decoration-color: #dcdcdc; /* stylelint-disable-line */ @@ -52,9 +53,8 @@ const buttonWrapper = css` `; const imageArea = css` - padding-top: ${space[2]}px; padding-bottom: ${space[1]}px; - grid-row: 2; + grid-row: 3; img { width: 100%; height: auto; @@ -107,16 +107,16 @@ export const ProductCarouselCard = ({
    )} - {showReadMore && !isUndefined(product.h2Id) && ( - event.stopPropagation()} - css={readMoreCta} - > - Read more - - )}
    + {showReadMore && !isUndefined(product.h2Id) && ( + event.stopPropagation()} + css={readMoreCta} + > + Read more + + )}
    {!hasHeading && ( diff --git a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx index 6b023af2373..1ed35cbfa56 100644 --- a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx +++ b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx @@ -27,7 +27,7 @@ export const ScrollableProduct = ({ {products.map((product: ProductBlockElement) => (