diff --git a/dotcom-rendering/src/components/CarouselNavigationButtons.tsx b/dotcom-rendering/src/components/CarouselNavigationButtons.tsx new file mode 100644 index 0000000000..92457cd152 --- /dev/null +++ b/dotcom-rendering/src/components/CarouselNavigationButtons.tsx @@ -0,0 +1,89 @@ +import { css } from '@emotion/react'; +import { from, space } from '@guardian/source/foundations'; +import type { ThemeButton } from '@guardian/source/react-components'; +import { + Button, + SvgChevronLeftSingle, + SvgChevronRightSingle, +} from '@guardian/source/react-components'; +import { palette } from '../palette'; + +type Props = { + previousButtonEnabled: boolean; + nextButtonEnabled: boolean; + onClickPreviousButton: () => void; + onClickNextButton: () => void; + dataLinkNameNextButton: string; + dataLinkNamePreviousButton: string; +}; + +const themeButton: Partial = { + borderTertiary: palette('--carousel-chevron-border'), + textTertiary: palette('--carousel-chevron'), + backgroundTertiaryHover: palette('--carousel-chevron-hover'), +}; + +const themeButtonDisabled: Partial = { + borderTertiary: palette('--carousel-chevron-border-disabled'), + textTertiary: palette('--carousel-chevron-disabled'), + backgroundTertiaryHover: 'transparent', +}; + +const buttonStyles = css` + display: none; + ${from.tablet} { + display: flex; + gap: ${space[1]}px; + margin-left: auto; + } +`; + +/** + * Navigation buttons for use in a carousel-like component + */ +export const CarouselNavigationButtons = ({ + previousButtonEnabled, + nextButtonEnabled, + onClickPreviousButton, + onClickNextButton, + dataLinkNameNextButton, + dataLinkNamePreviousButton, +}: Props) => { + return ( +
+
+ ); +}; diff --git a/dotcom-rendering/src/components/ScrollableCarousel.tsx b/dotcom-rendering/src/components/ScrollableCarousel.tsx index 28b1a55b18..714cabba62 100644 --- a/dotcom-rendering/src/components/ScrollableCarousel.tsx +++ b/dotcom-rendering/src/components/ScrollableCarousel.tsx @@ -6,14 +6,10 @@ import { space, textSansBold17Object, } from '@guardian/source/foundations'; -import type { ThemeButton } from '@guardian/source/react-components'; -import { - Button, - SvgChevronLeftSingle, - SvgChevronRightSingle, -} from '@guardian/source/react-components'; import { useEffect, useRef, useState } from 'react'; +import { nestedOphanComponents } from '../lib/ophan-helpers'; import { palette } from '../palette'; +import { CarouselNavigationButtons } from './CarouselNavigationButtons'; type Props = { children: React.ReactNode; @@ -39,18 +35,6 @@ const gridColumnWidth = 60; const gridGap = 20; const gridGapMobile = 10; -const themeButton: Partial = { - borderTertiary: palette('--carousel-chevron-border'), - textTertiary: palette('--carousel-chevron'), - backgroundTertiaryHover: palette('--carousel-chevron-hover'), -}; - -const themeButtonDisabled: Partial = { - borderTertiary: palette('--carousel-chevron-border-disabled'), - textTertiary: palette('--carousel-chevron-disabled'), - backgroundTertiaryHover: 'transparent', -}; - /** * On mobile the carousel extends into the outer margins to use the full width * of the screen. From tablet onwards the carousel sits within the page grid. @@ -161,15 +145,6 @@ const carouselStyles = css` } `; -const buttonStyles = css` - display: none; - ${from.tablet} { - display: flex; - gap: ${space[1]}px; - margin-left: auto; - } -`; - const itemStyles = css` display: flex; scroll-snap-align: start; @@ -346,44 +321,22 @@ export const ScrollableCarousel = ({ > {children} - {showNavigation && ( -
-
+ {showNavigation && ( + scrollTo('left')} + onClickNextButton={() => scrollTo('right')} + dataLinkNamePreviousButton={nestedOphanComponents( + 'carousel', + 'previous-button', + )} + dataLinkNameNextButton={nestedOphanComponents( + 'carousel', + 'next-button', + )} + /> )} );