diff --git a/libs/@guardian/react-crossword/src/@types/crossword.ts b/libs/@guardian/react-crossword/src/@types/crossword.ts index 7d1d41deb..af4e44616 100644 --- a/libs/@guardian/react-crossword/src/@types/crossword.ts +++ b/libs/@guardian/react-crossword/src/@types/crossword.ts @@ -68,3 +68,5 @@ export type Dimensions = { }; export type Axis = 'x' | 'y'; + +export type GetID = (arg0: string) => string; diff --git a/libs/@guardian/react-crossword/src/components/Clue.stories.tsx b/libs/@guardian/react-crossword/src/components/Clue.stories.tsx index 36d2ace80..730321aee 100644 --- a/libs/@guardian/react-crossword/src/components/Clue.stories.tsx +++ b/libs/@guardian/react-crossword/src/components/Clue.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { groupedClues as data } from '../../stories/formats/grouped-clues'; +import { GenerateIdProvider } from '../context/GenerateIdContext'; import { ThemeContext } from '../context/ThemeContext'; import { defaultTheme } from '../theme'; import { Clue } from './Clue'; @@ -16,6 +17,11 @@ const meta: Meta = { ), + (Story) => ( + + + + ), ], }; diff --git a/libs/@guardian/react-crossword/src/components/Clue.tsx b/libs/@guardian/react-crossword/src/components/Clue.tsx index b05b0daac..41cf9b326 100644 --- a/libs/@guardian/react-crossword/src/components/Clue.tsx +++ b/libs/@guardian/react-crossword/src/components/Clue.tsx @@ -2,6 +2,7 @@ import { css } from '@emotion/react'; import { textSans14 } from '@guardian/source/foundations'; import { memo, useContext } from 'react'; import type { CAPIEntry } from '../@types/CAPI'; +import { GenerateIdContext } from '../context/GenerateIdContext'; import { ThemeContext } from '../context/ThemeContext'; interface Props { @@ -18,11 +19,13 @@ const ClueComponent = ({ isComplete, }: Props) => { const theme = useContext(ThemeContext); + const generateId = useContext(GenerateIdContext); return (
= { ), + (Story) => ( + + + + ), (Story) => (
diff --git a/libs/@guardian/react-crossword/src/components/Clues.tsx b/libs/@guardian/react-crossword/src/components/Clues.tsx index 6d2ead8cb..d023f2b40 100644 --- a/libs/@guardian/react-crossword/src/components/Clues.tsx +++ b/libs/@guardian/react-crossword/src/components/Clues.tsx @@ -5,12 +5,13 @@ import { useContext } from 'react'; import type { Entries, Progress } from '../@types/crossword'; import type { Direction } from '../@types/Direction'; import type { EntryID } from '../@types/Entry'; +import { GenerateIdContext } from '../context/GenerateIdContext'; import { ThemeContext } from '../context/ThemeContext'; import { Clue } from './Clue'; const title = css` text-transform: capitalize; - ${headlineBold17} + ${headlineBold17}; color: currentColor; `; @@ -27,7 +28,9 @@ export const Clues = ({ currentEntryId, progress, }: Props) => { + const generateId = useContext(GenerateIdContext); const theme = useContext(ThemeContext); + const entriesForClues = []; for (const entry of entries.values()) { @@ -46,18 +49,18 @@ export const Clues = ({ >
{entriesForClues .sort((a, b) => a.number - b.number) diff --git a/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx b/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx index d219e18b6..ecd2e6a76 100644 --- a/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx +++ b/libs/@guardian/react-crossword/src/components/Crossword.stories.tsx @@ -1,6 +1,7 @@ -import type { Meta, StoryObj } from '@storybook/react'; +import type { Meta, StoryFn, StoryObj } from '@storybook/react'; import { groupedClues as data } from '../../stories/formats/grouped-clues'; import { progress } from '../../stories/formats/grouped-clues.progress'; +import { quick as quickData } from '../../stories/formats/quick'; import { Crossword } from './Crossword'; const meta: Meta = { @@ -34,3 +35,12 @@ export const Themed: Story = { clueMaxWidthRem: 30, }, }; + +export const MultiplePlayers: StoryFn = () => { + return ( + <> + + + + ); +}; diff --git a/libs/@guardian/react-crossword/src/components/Crossword.tsx b/libs/@guardian/react-crossword/src/components/Crossword.tsx index 7dc49840b..13f56c958 100644 --- a/libs/@guardian/react-crossword/src/components/Crossword.tsx +++ b/libs/@guardian/react-crossword/src/components/Crossword.tsx @@ -6,6 +6,7 @@ import type { CAPICrossword } from '../@types/CAPI'; import type { Coords, Progress, Theme } from '../@types/crossword'; import type { Direction } from '../@types/Direction'; import type { EntryID } from '../@types/Entry'; +import { GenerateIdProvider } from '../context/GenerateIdContext'; import { ThemeContext } from '../context/ThemeContext'; import { useProgress } from '../hooks/useProgress'; import { defaultTheme } from '../theme'; @@ -286,7 +287,9 @@ export const Crossword = ({ const target = event.target as HTMLElement; const entry = entries.get( - target.closest('[role="option"][id]')?.id as EntryID, + target + .closest('[role="option"][data-entry-id]') + ?.getAttribute('data-entry-id') as EntryID, ); if (entry) { @@ -313,80 +316,83 @@ export const Crossword = ({ return ( -
-
- - -

- {isStored - ? 'Crosswords are saved automatically.' - : 'Crossword will not be saved.'} -

-
+
- - +
+ + +

+ {isStored + ? 'Crosswords are saved automatically.' + : 'Crossword will not be saved.'} +

+
+
+ + +
-
+
); }; diff --git a/libs/@guardian/react-crossword/src/context/GenerateIdContext.tsx b/libs/@guardian/react-crossword/src/context/GenerateIdContext.tsx new file mode 100644 index 000000000..a561c281b --- /dev/null +++ b/libs/@guardian/react-crossword/src/context/GenerateIdContext.tsx @@ -0,0 +1,20 @@ +import { createContext, useCallback } from 'react'; +import type { Crossword } from '../@types/crossword'; + +export const GenerateIdContext = createContext((_: string) => _); + +export const GenerateIdProvider = ({ + id, + children, +}: { + id: Crossword['id']; + children: React.ReactNode; +}) => { + const generateId = useCallback((_: string) => `${_}-${id}`, [id]); + + return ( + + {children} + + ); +};