diff --git a/dotcom-rendering/src/components/CarouselNavigationButtons.tsx b/dotcom-rendering/src/components/CarouselNavigationButtons.tsx index dcb8809eb87..4450bb52276 100644 --- a/dotcom-rendering/src/components/CarouselNavigationButtons.tsx +++ b/dotcom-rendering/src/components/CarouselNavigationButtons.tsx @@ -7,7 +7,7 @@ import { type ThemeButton, } from '@guardian/source/react-components'; import { useEffect, useState } from 'react'; -import ReactDOM from 'react-dom'; +import { createPortal } from 'react-dom'; import { palette } from '../palette'; type CarouselNavigationProps = { @@ -84,7 +84,7 @@ export const CarouselNavigationButtons = ({ if (!portalNode) return null; - return ReactDOM.createPortal( + return createPortal(
} onClick={onClickNextButton} priority="tertiary" diff --git a/dotcom-rendering/src/components/ScrollableCarousel.tsx b/dotcom-rendering/src/components/ScrollableCarousel.tsx index 8d6d7bead28..d834d2d97a3 100644 --- a/dotcom-rendering/src/components/ScrollableCarousel.tsx +++ b/dotcom-rendering/src/components/ScrollableCarousel.tsx @@ -312,7 +312,7 @@ export const ScrollableCarousel = ({ const showNavigation = kind === CarouselKind.VisibleSlides ? carouselLength > visibleCarouselSlidesOnTablet - : false; + : true; const scrollTo = (direction: 'left' | 'right') => { if (!carouselRef.current) return; diff --git a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx index 66eab420066..47ca8bb02fa 100644 --- a/dotcom-rendering/src/components/ScrollableProduct.importable.tsx +++ b/dotcom-rendering/src/components/ScrollableProduct.importable.tsx @@ -1,8 +1,20 @@ +import { css } from '@emotion/react'; +import { palette, space } from '@guardian/source/foundations'; import type { ArticleFormat } from '../lib/articleFormat'; import type { ProductBlockElement } from '../types/content'; import { ProductCarouselCard } from './ProductCarouselCard'; import type { FixedSlideWidth } from './ScrollableCarousel'; import { CarouselKind, ScrollableCarousel } from './ScrollableCarousel'; +import { Subheading } from './Subheading'; + +const carouselHeader = css` + padding-bottom: 10px; + padding-top: ${space[6]}px; + border-bottom: 1px solid ${palette.neutral[86]}; + margin-bottom: 10px; + display: flex; + justify-content: space-between; +`; export const ScrollableProduct = ({ products, @@ -19,21 +31,37 @@ export const ScrollableProduct = ({ ], }; return ( - - {products.map((product: ProductBlockElement) => ( - +
+ - - - ))} - + At a glance + + +
+ + {products.map((product: ProductBlockElement) => ( + + + + ))} + + ); }; diff --git a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx index 9c43394617f..1efc627a8e9 100644 --- a/dotcom-rendering/src/components/ScrollableProducts.stories.tsx +++ b/dotcom-rendering/src/components/ScrollableProducts.stories.tsx @@ -15,19 +15,39 @@ const meta = { breakpoints.tablet, breakpoints.wide, ], + // Because this component uses react.createPortal + // we delay to give the portals time to hydrate + delay: 500, }, }, args: { products: [ - { ...exampleProduct, h2Id: 'product' }, { ...exampleProduct, + primaryHeadingHtml: 'Product 0', + h2Id: 'product', + }, + { + ...exampleProduct, + primaryHeadingHtml: 'Product 1', h2Id: 'product-1', productName: 'Lorem ipsum dolor sit amet', }, - { ...exampleProduct, h2Id: 'product-2' }, - { ...exampleProduct, h2Id: 'product-3' }, - { ...exampleProduct, h2Id: 'product-4' }, + { + ...exampleProduct, + primaryHeadingHtml: 'Product 2', + h2Id: 'product-2', + }, + { + ...exampleProduct, + primaryHeadingHtml: 'Product 3', + h2Id: 'product-3', + }, + { + ...exampleProduct, + primaryHeadingHtml: 'Product 4', + h2Id: 'product-4', + }, ], format: { design: ArticleDesign.Review, @@ -78,3 +98,20 @@ export default meta; type Story = StoryObj; export const With5Cards = {} satisfies Story; + +export const ClickForwardArrow = { + play: async ({ canvas, userEvent }) => { + await userEvent.click(canvas.getByTestId('carousel-forward-button')); + }, +} satisfies Story; + +export const ClickForwardTwiceAndBackOnce = { + play: async ({ canvas, userEvent }) => { + const user = userEvent.setup({ + delay: 500, // delay between each interaction + }); + await user.click(canvas.getByTestId('carousel-forward-button')); + await user.click(canvas.getByTestId('carousel-forward-button')); + await user.click(canvas.getByTestId('carousel-back-button')); + }, +} satisfies Story;