From c0aca6436c70f31c1f22dd0eac43944b2bba3f8d Mon Sep 17 00:00:00 2001 From: Alex Sanders Date: Thu, 12 Dec 2024 15:26:04 +0000 Subject: [PATCH] pass grid width to `Layout` component so that consumers can layout custom pages more easily --- .../react-crossword/src/@types/Layout.ts | 1 + .../src/components/Crossword.stories.tsx | 19 ++++++++++++--- .../src/components/Crossword.tsx | 23 +++++++++++++++---- .../src/context/ContextProvider.tsx | 9 ++++---- .../react-crossword/src/context/Theme.tsx | 12 +++------- .../src/layouts/ScreenLayout.tsx | 10 ++------ 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/libs/@guardian/react-crossword/src/@types/Layout.ts b/libs/@guardian/react-crossword/src/@types/Layout.ts index 0d466cf80..25905e43f 100644 --- a/libs/@guardian/react-crossword/src/@types/Layout.ts +++ b/libs/@guardian/react-crossword/src/@types/Layout.ts @@ -10,4 +10,5 @@ export type LayoutProps = { AnagramHelper: typeof AnagramHelper; Clues: typeof Clues; SavedMessage: ComponentType; + gridWidth: number; }; diff --git a/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx b/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx index 268fe09b3..f94b9bb69 100644 --- a/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx +++ b/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx @@ -69,9 +69,16 @@ export const MultiplePlayersRow: StoryFn = () => { }; export const CustomLayoutRaw: StoryFn = () => { - const Layout = ({ Clues, Grid, Controls, SavedMessage }: LayoutProps) => { + const Layout = ({ + Clues, + Grid, + Controls, + SavedMessage, + gridWidth, + }: LayoutProps) => { return ( <> +

gridWidth: {gridWidth}

@@ -103,13 +110,19 @@ export const CustomisedLayout: StoryFn = () => { ); - const Layout = ({ Clues, Grid, Controls, SavedMessage }: LayoutProps) => { + const Layout = ({ + Clues, + Grid, + Controls, + SavedMessage, + gridWidth, + }: LayoutProps) => { return (
-
+
{ ); }; -const layoutProps: LayoutProps = { +const layoutComponents: Omit = { Grid, Controls, AnagramHelper, @@ -47,9 +48,21 @@ export const Crossword = ({ }: CrosswordProps) => { const LayoutComponent = Layout ?? ScreenLayout; + const theme = useMemo( + () => ({ ...defaultTheme, ...userTheme }), + [userTheme], + ); + + const gridWidth = useMemo( + () => + (theme.gridCellSize + theme.gridGutterSize) * data.dimensions.cols + + theme.gridGutterSize, + [theme.gridCellSize, theme.gridGutterSize, data.dimensions.cols], + ); + return ( - {children ?? } + {children ?? ( + + )}
); diff --git a/libs/@guardian/react-crossword/src/context/ContextProvider.tsx b/libs/@guardian/react-crossword/src/context/ContextProvider.tsx index f467f07dc..0ec9b553a 100644 --- a/libs/@guardian/react-crossword/src/context/ContextProvider.tsx +++ b/libs/@guardian/react-crossword/src/context/ContextProvider.tsx @@ -20,9 +20,8 @@ import type { ReactNode } from 'react'; import type { CAPICrossword } from '../@types/CAPI'; -import type { Progress } from '../@types/crossword'; +import type { Progress, Theme } from '../@types/crossword'; import type { EntryID } from '../@types/Entry'; -import type { CrosswordProps } from '../components/Crossword'; import { CurrentCellProvider } from './CurrentCell'; import { CurrentClueProvider } from './CurrentClue'; import { DataProvider } from './Data'; @@ -35,19 +34,19 @@ export const ContextProvider = ({ data, selectedEntryId, userProgress, - userTheme, + theme, children, }: { data: CAPICrossword; selectedEntryId?: EntryID; userProgress?: Progress; - userTheme?: Partial; + theme: Theme; children: ReactNode; }) => { const { entries, dimensions, solutionAvailable, id } = data; return ( - + (undefined); @@ -8,16 +7,11 @@ export const ThemeProvider = ({ theme, children, }: { - theme?: Partial; + theme: Theme; children: ReactNode; }) => { - const finalTheme = useMemo( - () => ({ ...defaultTheme, ...theme }), - [theme], - ); - return ( - {children} + {children} ); }; diff --git a/libs/@guardian/react-crossword/src/layouts/ScreenLayout.tsx b/libs/@guardian/react-crossword/src/layouts/ScreenLayout.tsx index 4264cd6f4..79ccd52dc 100644 --- a/libs/@guardian/react-crossword/src/layouts/ScreenLayout.tsx +++ b/libs/@guardian/react-crossword/src/layouts/ScreenLayout.tsx @@ -4,7 +4,6 @@ import { textSans12, textSans14 } from '@guardian/source/foundations'; import { memo } from 'react'; import type { Direction } from '../@types/Direction'; import type { LayoutProps } from '../@types/Layout'; -import { useData } from '../context/Data'; import { useTheme } from '../context/Theme'; import { useUIState } from '../context/UI'; @@ -32,19 +31,14 @@ const Layout = ({ AnagramHelper, Clues, SavedMessage, + gridWidth: actualGridWidth, }: LayoutProps) => { const { textColor, clueMinWidth, clueMaxWidth } = useTheme(); const { showAnagramHelper } = useUIState(); const theme = useTheme(); - const { gridGutterSize, gridCellSize } = useTheme(); - const { dimensions } = useData(); - - const gridWidth = Math.max( - (gridCellSize + gridGutterSize) * dimensions.cols + gridGutterSize, - 300, - ); + const gridWidth = Math.max(actualGridWidth, 300); const oneColWidth = gridWidth + clueMinWidth; const twoColWidth = gridWidth + clueMinWidth * 2;