diff --git a/.storybook/main.ts b/.storybook/main.ts index e6fba25d90c..07e102e0ee5 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -43,6 +43,7 @@ const storybookConfig: StorybookConfig = { '../src/app/legacy/psammead/psammead-locales/**/*.stories.@(t|j)sx', '../src/app/legacy/psammead/index.stories.tsx', '../src/app/components/**/*.stories.@(t|j)sx', + '../src/app/components-webcore/**/*.stories.@(t|j)sx', '../src/app/pages/**/*.stories.@(t|j)sx', './DocsDecorator/**/*.stories.@(t|j)sx', './StorybookComponents/**/*.stories.@(t|j)sx', diff --git a/data/afrique/live/c7gk1vjglxn1t.json b/data/afrique/live/c7gk1vjglxn1t.json new file mode 100644 index 00000000000..995da3f9f67 --- /dev/null +++ b/data/afrique/live/c7gk1vjglxn1t.json @@ -0,0 +1,421 @@ +{ + "data": { + "title": "Testing Flourish, Riddle embeds + contributor's byline", + "description": "Some summary", + "visibility": true, + "language": "fr", + "headerImage": null, + "promoImage": null, + "syndicationPromoImage": { + "url": "https://static.test.files.bbci.co.uk/core/website/assets/static/bbc/images/metadata/poster-1024x576.efe9db7f43.png", + "brandedUrl": "https://static.test.files.bbci.co.uk/core/website/assets/static/bbc/images/metadata/poster-1024x576.efe9db7f43.png", + "altText": "BBC logo", + "copyright": "BBC", + "suitableForSyndication": true, + "isPlaceholder": true, + "width": 1024, + "height": 576 + }, + "home": "afrique", + "section": null, + "commercialInfo": { + "adCategory": null, + "adSubCategory": null, + "hasAdvertising": true + }, + "sportDataEvent": { + "id": "urn:bbc:sportsdata:football:event:s-2f01ug9ijcjd3uj26q8fe3bbo" + }, + "sportDataEventContent": { + "id": "urn:bbc:sportsdata:football:event:s-2f01ug9ijcjd3uj26q8fe3bbo", + "content": { + "data": { + "title": "Villa gain upper hand with gritty Europa League win at Bologna", + "live": true, + "startDateTime": "2026-04-09T19:00:00.000Z", + "uasActivityData": { + "action": "heartbeat", + "resourceDomain": "bbc-live", + "resourceId": "urn:bbc:tipo:topic:ce847pmy2e7t", + "resourceType": "asset", + "environment": "live", + "apiKey": "km5ifdffcjdoc" + }, + "countingServiceDataAverage": 0, + "sportDataEvent": { + "urn": "urn:bbc:sportsdata:football:event:s-3y91hnyfjh24yxjhm77a7hy50", + "home": { + "id": "ej5er0oyngdw138yuumwqbyqt", + "fullName": "Bologna", + "shortName": "Bologna", + "urn": "urn:bbc:sportsdata:football:team:bologna", + "runningScores": { + "halftime": "0", + "fulltime": "1", + "aggregate": "1" + }, + "scoreUnconfirmed": "1", + "actions": [ + { + "playerUrn": "urn:bbc:sportsdata:football:player:s-2bmeynv0dhsc8sjfuaprkexre", + "playerName": "J. Rowe", + "actionType": "goal", + "actions": [ + { + "type": "Goal", + "typeLabel": { "value": "Goal", "accessible": "Goal" }, + "timeLabel": { + "value": "90'", + "accessible": "90 minutes" + } + } + ] + } + ], + "score": "1" + }, + "away": { + "id": "b496gs285it6bheuikox6z9mj", + "fullName": "Aston Villa", + "shortName": "Aston Villa", + "urn": "urn:bbc:sportsdata:football:team:aston-villa", + "runningScores": { + "halftime": "1", + "fulltime": "3", + "aggregate": "3" + }, + "scoreUnconfirmed": "3", + "actions": [ + { + "playerUrn": "urn:bbc:sportsdata:football:player:s-8qys6qtdwgsycxducl062zld5", + "playerName": "E. Konsa", + "actionType": "goal", + "actions": [ + { + "type": "Goal", + "typeLabel": { "value": "Goal", "accessible": "Goal" }, + "timeLabel": { + "value": "44'", + "accessible": "44 minutes" + } + } + ] + }, + { + "playerUrn": "urn:bbc:sportsdata:football:player:s-5m0j33eoa5c8pqlr0tdf7undh", + "playerName": "O. Watkins", + "actionType": "goal", + "actions": [ + { + "type": "Goal", + "typeLabel": { "value": "Goal", "accessible": "Goal" }, + "timeLabel": { + "value": "51'", + "accessible": "51 minutes" + } + }, + { + "type": "Goal", + "typeLabel": { "value": "Goal", "accessible": "Goal" }, + "timeLabel": { + "value": "90'+4", + "accessible": "90 minutes plus 4" + } + } + ] + } + ], + "score": "3" + }, + "time": { + "accessibleTime": "20:00", + "displayTimeUK": "20:00", + "timeCertainty": true + }, + "date": "Thu 9 Apr 2026", + "tournament": { + "id": "4c1nfi2j1m731hcay25fcgndq", + "name": "UEFA Europa League", + "disambiguatedName": "UEFA Europa League", + "urn": "urn:bbc:sportsdata:football:tournament:europa-league", + "thingsGuid": "2afbdda7-71d4-544d-bcc6-d9ff50314b2a" + }, + "stage": { + "id": "7wxuj38kqm8bz3cmi15vu4w7o", + "name": "Quarter-finals", + "urn": "" + }, + "multiLeg": { + "leg": 1, + "relatedMatchId": "s-9ur6e6w5f4ahyxph7ef4rks2c" + }, + "period": "ft", + "venue": { + "id": "2nrn0y55nz9ee7p9adzbb7fta", + "urn": "urn:bbc:sportsdata:football:venue:s-2nrn0y55nz9ee7p9adzbb7fta", + "name": "Stadio Renato Dall'Ara", + "shortName": "Stadio Renato Dall'Ara" + }, + "attendance": { "value": 31142 }, + "status": "PostEvent", + "periodLabel": { "value": "FT", "accessible": "Full time" }, + "winner": "away", + "tournamentDescriptionLabel": "UEFA Europa League - Quarter-finals", + "groupedActions": [ + { + "groupName": { "fullName": "Assists", "shortName": "Assists" }, + "homeTeamActions": ["J. Lucumí (90')"], + "awayTeamActions": [ + "Y. Tielemans (44', 90'+4)", + "E. Buendía (51')" + ] + } + ], + "accessibleEventSummary": "Bologna 1 , Aston Villa 3 at Full time", + "sportDiscipline": "football" + }, + "staticLinksData": { + "staticLinks": [ + { + "url": "/sport/football/live/clygly9z1j9t", + "text": "Relive Thursday's Europa League and Conference League action" + } + ] + }, + "type": "oppm", + "headerImage": null, + "seoTimestamps": { + "firstPublished": "2026-04-08T03:00:55.128Z", + "lastModified": "2026-04-10T08:37:45.000Z" + }, + "lastUpdatedString": "Updated 6 days ago" + } + } + }, + "eavisEvent": { "id": null }, + "article": { "id": null }, + "mediaCollections": null, + "keyHighlight": null, + "electionBanner": { "id": null }, + "supportingLinks": { "id": null }, + "riddle": { "id": null, "isPredictor": false }, + "ugcCampaign": { "id": null }, + "comments": { "id": null }, + "relatedStories": { "id": null }, + "seo": { + "seoTitle": "Testing Flourish, Riddle embeds + contributor's byline", + "seoDescription": "Some summary", + "datePublished": "2024-10-08T09:20:00.000Z", + "dateModified": "2026-03-16T16:17:28.000Z" + }, + "endDateTime": "2026-10-19T09:17:00.000Z", + "startDateTime": "2024-10-08T09:20:00.000Z", + "firstPublishedDateTime": "2025-12-18T15:07:59.650Z", + "type": "live-coverage", + "analytics": { + "page": { + "name": "live_coverage.c7gk1vjglxn1t.page", + "contentId": "urn:bbc:tipo:topic:c7gk1vjglxn1t" + } + }, + "dataSource": "TIPO", + "isLive": true, + "summaryPoints": { "id": null, "content": null }, + "liveTextStream": { + "id": "3861CC0A9EA7434981EEE3FCE9880391", + "contributors": null, + "content": { + "data": { + "results": [ + { + "typeCode": null, + "header": { + "model": { + "blocks": [ + { + "type": "headline", + "model": { + "blocks": [ + { + "type": "text", + "model": { + "blocks": [ + { + "type": "paragraph", + "model": { + "text": "A post with contributors", + "blocks": [ + { + "type": "fragment", + "model": { + "text": "A post with contributors", + "attributes": [] + } + } + ] + } + } + ] + } + } + ] + } + }, + { + "type": "subheadline", + "model": { + "blocks": [ + { + "type": "text", + "model": { + "blocks": [ + { + "type": "paragraph", + "model": { + "text": "This is the sub-headline", + "blocks": [ + { + "type": "fragment", + "model": { + "text": "This is the sub-headline", + "attributes": [] + } + } + ] + } + } + ] + } + } + ] + } + }, + { + "type": "contributor", + "model": { + "name": "Gahuza contributor", + "link": null, + "subtitle": "gahuza contributor", + "external": "false", + "blocks": [ + { + "type": "image", + "model": { + "blocks": [ + { + "type": "rawImage", + "model": { + "width": 100, + "height": 100, + "locator": "/vivo/test/images/2016/12/12/977af52a-6eaf-481f-9a06-094860d56760.jpg", + "originCode": "cpsdevpb", + "copyrightHolder": "BBC" + } + }, + { + "type": "altText", + "model": { + "blocks": [ + { + "type": "text", + "model": { + "blocks": [ + { + "type": "paragraph", + "model": { + "text": "", + "blocks": [ + { + "type": "fragment", + "model": { + "text": "", + "attributes": [] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + } + ] + } + }, + "content": { + "model": { + "blocks": [ + { + "type": "fragment", + "model": { "text": "\n ", "attributes": [] } + }, + { + "type": "paragraph", + "model": { + "text": "This is the post's body text", + "blocks": [ + { + "type": "fragment", + "model": { + "text": "This is the post's body text", + "attributes": [] + } + } + ] + } + }, + { + "type": "fragment", + "model": { "text": "\n ", "attributes": [] } + } + ] + } + }, + "link": null, + "urn": "asset:d69557ee-183e-4c79-b69a-5a04c00de8ac", + "type": "POST", + "options": { "isBreakingNews": false, "includeComments": false }, + "dates": { + "firstPublished": "2026-01-12T09:00:01.000Z", + "lastPublished": "2026-01-12T09:00:01.000Z", + "time": null, + "curated": "2026-01-12T09:00:02.378Z" + }, + "titles": [{ "title": null, "source": "primary" }], + "descriptions": [{ "text": null, "source": "summary" }], + "images": [ + { + "originalUrl": null, + "altText": null, + "copyright": null, + "urlTemplate": null, + "url": null + } + ] + } + ], + "page": { "index": 1, "total": 1 } + } + } + }, + "metadata": { + "atiAnalytics": { + "contentId": "urn:bbc:tipo:topic:c7gk1vjglxn1t", + "contentType": "live-coverage", + "pageIdentifier": "live_coverage.c7gk1vjglxn1t.page", + "pageTitle": "Testing Flourish, Riddle embeds + contributor's byline", + "timePublished": "2024-10-08T09:20:00.000Z", + "timeUpdated": "2026-03-16T16:17:28.000Z" + } + } + }, + "contentType": "application/json; charset=utf-8" +} diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/README.md b/src/app/components-webcore/SportDataHeader/head-to-head-v2/README.md new file mode 100644 index 00000000000..168418d9cff --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/README.md @@ -0,0 +1,110 @@ +## Lift and Shift component + +This component was lifted and shifted from Public Service. Some of the files do not meet our component standards. + +## Props + +| Argument | Type | Required | Description | +| :------------- | :--------------------: | :------: | :---------------------------------------------------------------- | +| `participants` | Array of `Participant` | yes | The participants in the order they appear in the the head to head | +| `date` | Object of `Date` | yes | Date elements to identify when the event takes place | +| `status` | Enum | yes | The status of the event. `PreEvent`, `MidEvent` or `PostEvent` | +| `comment` | Object of `Comment` | no | A comment to provide additional context for the event | + +### Object types + +#### Date + +| Key | Type | Required | Description | +| :----------- | :----: | :------: | :------------------------------------------------ | +| `time` | String | yes | Time of the event in 24h format | +| `iso` | String | yes | Machine readable ISO datetime string | +| `dayOfWeek` | String | no | The day of week to show in the stacked variant | +| `day` | String | no | The numerical date to show in the stacked variant | +| `shortMonth` | String | no | The month to show in the stacked variant | + +#### Participant + +| Key | Type | Required | Description | +| :------ | :----: | :------: | :--------------------------------------------------------------------------------- | +| `id` | String | yes | Used to identify badges | +| `name` | String | yes | Name of the participant | +| `score` | Number | no | Score for the participant, used in a `MidEvent` or `PostEvent` status head to head | + +#### Comment + +| Key | Type | Required | Description | +| :--------------- | :----: | :------: | :------------------------------------------- | +| `text` | String | yes | The text that is presented visually | +| `accessibleText` | String | no | Text that is used for assistive technologies | + +## Usage + +To be used within content displaying event information between 2 participants such as Sport Data pages, Live pages and Topic pages for example. + +## Capabilities + +- A badge can be rendered for a participant using their provided ID. (Currently only supports basketball badges). +- Mid event styling is configurable through the `Live` (background) and `Accent contrast` (foreground) brand colours +- Post event styling is configurable through the `Masthead` (background) and `Masthead contrast` (foreground) brand colours +- A comment can be rendered with an accessible alternative to ensure the quality of the experience for users with assistive technology, when using acronyms or abbreviations in the visual text for example + +### Example + +**Pre event** + +```jsx +import React from 'react'; +import HeadToHeadV2 from '@bbc/web-components/head-to-head-v2'; + +const figure = () => ( + +); +``` + +**Mid event** + +```jsx +import React from 'react'; +import HeadToHeadV2 from '@bbc/web-components/head-to-head-v2'; + +const figure = () => ( + +); +``` + +**Post event** + +```jsx +import React from 'react'; +import HeadToHeadV2 from '@bbc/web-components/head-to-head-v2'; + +const figure = () => ( + +); +``` + +## Accessibility notes + +- Badge images are decorative only. +- Accessible text announced by screen readers can be changed from `... at {period}` to `... on the {period}` by setting `periodLabel.labelType` to `'date'` + - This should be set when passing a date (e.g., `1st of January 2023`) to `periodLabel.accessible` to give an improved screen reader experience diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action-grid.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action-grid.jsx new file mode 100644 index 00000000000..09a47f5bf29 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action-grid.jsx @@ -0,0 +1,26 @@ +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; + +// import { GROUP_3, createSize } from '@bbc/web-gel-foundations'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +export const GRID_AREAS = { + homeText: 'home_text', + awayText: 'away_text', + centreText: 'centre_text', +}; + +export const ActionGrid = styled.div` + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: + '${GRID_AREAS.centreText} ${GRID_AREAS.centreText}' + '${GRID_AREAS.homeText} ${GRID_AREAS.awayText}'; + + @media (min-width: ${pixelsToRem(600)}rem) { + grid-template-columns: 1fr ${pixelsToRem(150)}rem 1fr; + grid-template-areas: '${GRID_AREAS.homeText} ${GRID_AREAS.centreText} ${GRID_AREAS.awayText}'; + } +`; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action.jsx new file mode 100644 index 00000000000..f54ea760605 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/action.jsx @@ -0,0 +1,67 @@ +/* eslint-disable jsx-a11y/aria-role */ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; + +// import { +// fontEmphasised, +// fontScaleBody, +// fontScaleDescription, +// GROUP_3, +// SPACING_1, +// SPACING_2, +// SPACING_3 +// } from '@bbc/web-gel-foundations'; +import ActionsTime from './actions-time'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const StyledAction = styled.li` + ${'' /* ${fontEmphasised} */} + font-family: ReithSans, Helvetica, Arial, freesans, sans-serif; + font-weight: 700; + font-feature-settings: 'ss01' off; + + ${'' /* ${fontScaleDescription} */} + font-size: 14px; + line-height: 1.2857142857142858; + + padding-bottom: 8px; + @media (min-width: ${pixelsToRem(600)}rem) { + ${'' /* ${fontScaleBody} */} + font-size: 1rem; + line-height: 1.375; + padding-bottom: 8px; + ${({ alignment }) => + `padding-${alignment === 'home' ? 'left' : 'right'}: 12px`}; + } +`; + +const StyledUl = styled.ul` + list-style: none; + padding: 0; // reset + margin: 0; // reset + + @media (min-width: ${pixelsToRem(600)}rem) { + display: flex; + flex-wrap: wrap; + padding-top: 4px; + justify-content: ${({ alignment }) => + alignment === 'home' ? `flex-end` : `flex-start`}; + } +`; + +const Action = ({ contestantActions, alignment }) => ( + + {contestantActions.map((player, index) => ( + // eslint-disable-next-line react/no-array-index-key + + {player.playerName} + + + ))} + +); + +export default Action; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions-time.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions-time.jsx new file mode 100644 index 00000000000..116a6ce0891 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions-time.jsx @@ -0,0 +1,52 @@ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; + +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; + +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +import Card from './card'; + +const goalTypesHandled = { + Penalty: 'pen', + 'Own Goal': 'og', +}; + +const TextBlock = styled.span` + white-space: nowrap; +`; + +const displayGoalType = goalType => + goalTypesHandled[goalType] ? ` ${goalTypesHandled[goalType]}` : ''; + +const ActionsTime = ({ player }) => { + const times = player.actions.map( + action => `${action.timeLabel.value}${displayGoalType(action.type)}`, + ); + const timesAccessible = player.actions + .map( + action => `${action.typeLabel.accessible} ${action.timeLabel.accessible}`, + ) + .join(', '); + return ( + <> + {times.map((time, index) => ( + // eslint-disable-next-line react/no-array-index-key + + + {index === 0 && '('} + {player.actionType === 'card' && } + {time} + {index === times.length - 1 && ')'} + + {index !== times.length - 1 && ', '} + + ))} + {timesAccessible} + + ); +}; + +export default ActionsTime; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions.jsx new file mode 100644 index 00000000000..d916ccec38f --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/actions.jsx @@ -0,0 +1,44 @@ +// import React from 'react'; + +import { GroupedEvents } from './grouped-events'; +import { ActionGrid } from './action-grid'; +import ScoreDetails from './score-details'; +import { KeyEvents } from './key-events'; + +// eslint-disable-next-line import/prefer-default-export +export const Actions = ({ data }) => { + const homeKeyEvents = data.home?.actions || []; + const awayKeyEvents = data.away?.actions || []; + + const hasGroupedEvents = + data.groupedActions && data.groupedActions.length > 0; + const hasKeyEvents = homeKeyEvents.length > 0 || awayKeyEvents.length > 0; + + return ( + <> + + + {hasKeyEvents && ( + + )} + + {hasGroupedEvents && ( + + )} + + ); +}; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/card.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/card.jsx new file mode 100644 index 00000000000..a6837d63383 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/card.jsx @@ -0,0 +1,50 @@ +/* eslint-disable jsx-a11y/aria-role */ +// import React from 'react'; +// import styled from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +import { RedCardSVG, SecondYellowCardSVG } from '#app/components/icons'; + +// import { createSize } from '@bbc/web-gel-foundations'; +// import redcard from '@bbc/web-assets/static/sport/football/red-card.svg'; +// import secondyellowcard from '@bbc/web-assets/static/sport/football/second-yellow-card.svg'; + +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +// in the original implementation, this is an img element with empty alt text and accepts a URL to the svg as an src. +const CardWrapper = styled.span` + padding: 0 ${pixelsToRem(3.2)}rem; + display: inline-block; // keeps styling in line with PS + vertical-align: bottom; // keeps styling in line with PS +`; + +const StyledRedCard = styled(CardWrapper)` + width: ${pixelsToRem(11.2)}rem; + margin-bottom: ${pixelsToRem(-3.2)}rem; +`; + +const StyledYellowCard = styled(CardWrapper)` + margin-bottom: ${pixelsToRem(-6.4)}rem; + width: ${pixelsToRem(16)}rem; +`; + +const CardContainer = styled.div` + display: inline-block; + box-sizing: content-box; +`; + +const Card = ({ player }) => ( + + {player.actions[0].type === 'Red Card' ? ( + + + + ) : ( + + + + )} + +); + +export default Card; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/centre.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/centre.jsx new file mode 100644 index 00000000000..95d67e591ea --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/centre.jsx @@ -0,0 +1,74 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +// import { createSize, GROUP_3 } from '@bbc/web-gel-foundations'; +// import { +// isCalledOffStatus, +// isInProgressStatus, +// isResultStatus, +// } from '@bbc/web-sport-utils'; +import { + isCalledOffStatus, + isInProgressStatus, + isResultStatus, +} from '../helpers/event-status-groups'; + +import Time from './fixture-time'; +import Score from './score'; + +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +// ensures team names / badges line up down the page across "HH:mm", "TBC", single-digit and double-digit scores +// it is acceptable for the badges/team names to be spaced more widely for triple-digit+ scores, as these are very rare +const getCentreMinWidthPx = maxScoreLength => + maxScoreLength && maxScoreLength > 1 + ? { desktop: 106, mobile: 90 } + : { desktop: 85, mobile: 77 }; + +const StyledCentre = styled.div` + display: flex; + flex-direction: column; + align-self: space-evenly; + + ${({ maxScoreLength }) => css` + min-width: ${pixelsToRem(getCentreMinWidthPx(maxScoreLength).mobile)}rem; + @media (min-width: ${pixelsToRem(600)}rem) { + min-width: ${pixelsToRem(getCentreMinWidthPx(maxScoreLength).desktop)}rem; + } + `} +`; + +export const shouldShowScores = statusGroup => + isInProgressStatus(statusGroup) || + isResultStatus(statusGroup) || + isCalledOffStatus(statusGroup) || + statusGroup === 'Postponed'; + +const Played = ({ data, isConciseView }) => ( + +); + +const Centre = ({ data, isConciseView, maxScoreLength }) => { + const { status } = data; + + return ( + + {shouldShowScores(status) ? ( + + ) : ( + + ); +}; + +export default Centre; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/conditional-onward-journey-link.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/conditional-onward-journey-link.jsx new file mode 100644 index 00000000000..7628e5df188 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/conditional-onward-journey-link.jsx @@ -0,0 +1,58 @@ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +// import { Track } from '@bbc/web-click-view-tracker'; +// import { GridContainer, TeamHome, TeamAway } from './head-to-head-banner.jsx'; +// import { Name as ParticipantsName } from '../../head-to-head/components/participant.jsx'; + +// const OnwardJourneyLink = styled.a` +// cursor: pointer; + +// &:link { +// text-decoration: none; +// color: ${({ theme }) => theme.colourPalette.primary}; +// } + +// &:visited { +// color: ${({ theme }) => theme.colourPalette.primary}; +// } + +// &:hover, +// &:focus > ${GridContainer} { +// ${TeamHome}, ${TeamAway}, ${ParticipantsName} { +// color: ${({ theme }) => theme.colourPalette.hyperlink}; +// text-decoration-line: underline; +// } +// } +// `; + +// eslint-disable-next-line import/prefer-default-export +export const ConditionalOnwardJourneyLink = ({ + // isConciseView, + // onwardJourneyLink, + children, + // tipoTopicId, + // trackingEvent, +}) => { + // if (isConciseView && onwardJourneyLink) { + // return trackingEvent ? ( + // + // {({ trackRef }) => ( + //
+ // + // {children} + // + //
+ // )} + // + // ) : ( + // + // {children} + // + // ); + // } + + return children; +}; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/fixture-time.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/fixture-time.jsx new file mode 100644 index 00000000000..9a423b93c4a --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/fixture-time.jsx @@ -0,0 +1,74 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; +import styled from '@emotion/styled'; +// import { css } from '@emotion/react'; + +// import { +// GROUP_3, +// SPACING_1, +// SPACING_3, +// SPACING_4, +// SPACING_7, +// createSize, +// fontScaleBody, +// fontScaleIndexHeadlineMedium, +// fontScaleSectionHeading, +// fontStandard, +// // eslint-disable-next-line no-restricted-imports +// fontWeights +// } from '@bbc/web-gel-foundations'; +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; +// import { fixedHeightConciseView } from '../helpers/concise-styles.jsx'; + +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const StyledTime = styled.time` + display: flex; + align-items: center; + justify-content: center; + ${'' /* ${fontScaleBody} */} + font-size: 16px; + line-height: 1.375; + + font-size: ${pixelsToRem(40)}rem; + line-height: 1.125; + font-weight: 500; + padding: 0 4px; + + @media (min-width: ${pixelsToRem(600)}rem) { + font-size: ${pixelsToRem(50)}rem; + line-height: 1.08; + padding: 0 32px; + } + + ${ + '' /* ${({ theme, isConciseView }) => + isConciseView && + css` + ${fontStandard({ theme })} + ${fixedHeightConciseView} + ${fontScaleIndexHeadlineMedium} + padding: 0 12px; + + @media (min-width: '${pixelsToRem(600)}rem') { + padding: 0 16px; + ${fontScaleSectionHeading} + } + `} */ + } +`; + +const Time = ({ time, isConciseView }) => ( + <> + + {time.accessibleTime} + +); + +export default Time; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/footer.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/footer.jsx new file mode 100644 index 00000000000..7c35f076193 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/footer.jsx @@ -0,0 +1,99 @@ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; +// import { +// SPACING_1, +// SPACING_2, +// GROUP_3, +// SPACING_4, +// fontScaleDescription, +// fontScaleBody, +// createSize, +// } from '@bbc/web-gel-foundations'; +// import { getStyledLineColour } from '../helpers/colour-styles.js'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const StyledFooter = styled.div` + font-size: 14px; + line-height: 1.2857142857142858; + padding-bottom: 16px; + text-align: center; + + @media (min-width: ${pixelsToRem(600)}rem) { + font-size: 1rem; + line-height: 1.375; + padding-bottom: 8px; + } +`; + +const FooterTextWrapper = styled.div` + display: inline-block; + font-size: ${pixelsToRem(13)}rem; + + &:not(:first-child) { + margin-left: 8px; + } +`; + +const Venue = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + padding-bottom: 4px; +`; + +const AttendanceValue = styled.div` + display: flex; + flex-direction: row; + justify-content: center; + flex-wrap: wrap; +`; + +const VenueLabel = styled.span` + color: #a8a8a8; + padding-right: 4px; +`; + +const AttendanceLabel = styled.span` + color: #a8a8a8; + padding-right: 4px; +`; + +const HorizontalRule = styled.hr` + width: ${pixelsToRem(12)}rem; + border: none; + ${ + '' /* border-top: 1px solid ${({ theme, status, isConciseView }) => getStyledLineColour({ theme, status, isConciseView })}; + */ + } + border-top: 1px solid #FFD230; + padding-bottom: 4px; +`; + +const Footer = ({ venue, status, attendanceValue, attendanceInfo }) => { + const formattedAttendanceValue = attendanceValue?.toLocaleString(); + + return ( + + + + + Venue: + {attendanceInfo ? `${venue} (${attendanceInfo})` : venue} + + + + {attendanceValue && ( + + Attendance: + {formattedAttendanceValue} + + )} + + + ); +}; + +export default Footer; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/grouped-events.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/grouped-events.jsx new file mode 100644 index 00000000000..69898726790 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/grouped-events.jsx @@ -0,0 +1,155 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +// import { css } from '@emotion/react'; + +// import { +// GROUP_3, +// SPACING_2, +// SPACING_5, +// SPACING_6, +// fontEmphasised, +// SPACING_1, +// SPACING_4, +// SPACING_3, +// fontScaleBody, +// fontScaleDescription, +// createSize +// } from '@bbc/web-gel-foundations'; +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; +import { ActionGrid, GRID_AREAS } from './action-grid'; + +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const GroupedEventsWrapper = styled.div` + margin: 8px 24px 0; +`; + +const ActionWrapper = styled.div` + ${ + '' /* ${({ theme }) => css` + border-top: ${createSize(1)} solid ${theme.colourPalette.border.decorativeSubtle}; + `}; */ + } + + border-top: ${pixelsToRem(1)}rem solid #505050; +`; + +const GroupLabel = styled.div` + grid-area: ${GRID_AREAS.centreText}; + ${'' /* ${fontEmphasised} */} + font-family: ReithSans, Helvetica, Arial, freesans, sans-serif; + font-weight: 700; + font-feature-settings: 'ss01' off; + + text-align: center; + ${'' /* ${fontScaleBody} */} + font-size: 1rem; + line-height: 1.375; + + padding: 8px 0 4px; + + @media (min-width: ${pixelsToRem(600)}rem) { + padding: 8px 0 20px; + } +`; + +const GroupedHomeEvent = styled.div` + grid-area: ${GRID_AREAS.homeText}; + text-align: right; + + ${'' /* ${fontScaleDescription} */} + font-size: 14px; + line-height: 1.2857142857142858; + + padding: 0 16px 12px 0; + + @media (min-width: ${pixelsToRem(600)}rem) { + ${'' /* ${fontScaleBody} */} + font-size: 1rem; + line-height: 1.375; + + padding: 8px 0 20px; + } +`; + +const GroupedAwayEvent = styled.div` + grid-area: ${GRID_AREAS.awayText}; + text-align: left; + + ${'' /* ${fontScaleDescription} */} + font-size: 14px; + line-height: 1.2857142857142858; + + padding: 0 0 12px 16px; + + @media (min-width: ${pixelsToRem(600)}rem) { + ${'' /* ${fontScaleBody} */} + font-size: 1rem; + line-height: 1.375; + padding: 8px 0 20px; + } +`; + +const Actions = ({ teamActions, teamAccessibleActions }) => { + if (teamAccessibleActions?.length) { + return ( + <> + {teamActions.join(', ')} + + {teamAccessibleActions.join(', ')} + + + ); + } + + return teamActions.join(', '); +}; + +// eslint-disable-next-line import/prefer-default-export +export const GroupedEvents = ({ groupedEvents, homeName, awayName }) => ( + + {groupedEvents.map( + ({ + groupName, + homeTeamActions, + homeTeamAccessibleActions, + awayTeamActions, + awayTeamAccessibleActions, + }) => ( + + + {groupName.fullName} + + {homeTeamActions.length > 0 && ( + <> + {`${homeName},`} + + + )} + + + {awayTeamActions.length > 0 && ( + <> + {`${awayName},`} + + + )} + + + + ), + )} + +); diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-banner.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-banner.jsx new file mode 100644 index 00000000000..171d59aa4c8 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-banner.jsx @@ -0,0 +1,148 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; +// import { GROUP_3, createSize } from '@bbc/web-gel-foundations'; + +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; +import Team from './team'; +import Centre from './centre'; +import MatchProgress from './match-progress'; +import PenaltyScores from './penalty-scores'; +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +export const GridContainer = styled.div` + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: ${({ isConciseView }) => (isConciseView ? 'center' : 'none')}; + grid-template-areas: + 'home_team scores away_team' + 'progress progress progress'; + ${({ isConciseView, shouldHideBadges }) => + !isConciseView && + !shouldHideBadges && + css` + @media (max-width: calc(${pixelsToRem(600)}rem - ${pixelsToRem(1)}rem)) { + grid-template-columns: 1fr auto auto 1fr; + grid-template-areas: + 'home_team scores scores away_team' + 'home_team progress progress away_team'; + } + `} +`; + +const WithInlineFallback = styled.div` + @supports not (display: grid) { + display: inline-block; + width: 33%; + } +`; + +export const TeamHome = styled(WithInlineFallback)` + grid-area: home_team; + display: flex; + align-items: stretch; +`; + +export const TeamAway = styled(WithInlineFallback)` + grid-area: away_team; + display: flex; + align-items: stretch; +`; + +const Scores = styled(WithInlineFallback)` + grid-area: scores; + margin: auto; +`; + +const MatchProgressContainer = styled.div` + grid-area: progress; +`; + +const ItemWrapper = ({ + data, + isConciseView, + shouldHideBadges, + maxScoreLength, + teamBadgePlaceholderFallbackType, +}) => { + const shouldDisplayPenScores = + data.home.runningScores?.penaltyShootout && + data.away.runningScores?.penaltyShootout; + return ( + <> + + + + + + + {data.status === 'PreEvent' && ( + plays + )} + + + + + + + + + {shouldDisplayPenScores && ( + + )} + + ); +}; + +export const HeadToHeadBanner = ({ + data, + isConciseView, + eventSummary, + shouldHideBadges, + maxScoreLength, + teamBadgePlaceholderFallbackType, +}) => ( + <> + {eventSummary} + + +); + +export default HeadToHeadBanner; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-header.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-header.jsx new file mode 100644 index 00000000000..276ebe366a2 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/head-to-head-header.jsx @@ -0,0 +1,125 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; +// import { +// GROUP_3, +// SPACING_6, +// SPACING_4, +// SPACING_2, +// SPACING_1, +// fontScaleBody, +// fontScaleDescription +// } from '@bbc/web-gel-foundations'; +import { isLiveStatus } from '../helpers/event-status-groups'; +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const HeaderWrapper = styled.div` + display: flex; + justify-content: center; + flex-direction: column; + font-size: 14px; + line-height: 1.2857142857142858; + padding-bottom: 16px; + + ${({ status }) => css` + padding-top: ${isLiveStatus(status) ? 0 : '16px'}; + `} + @media (min-width: ${pixelsToRem(600)}rem) { + flex-direction: row; + font-size: 1rem; + line-height: 1.375; + ${({ status }) => css` + padding-top: ${isLiveStatus(status) ? '8px' : '24px'}; + `} + } +`; + +const DateWrapper = styled.div` + display: flex; + justify-content: flex-end; + + flex-direction: column; + @media (min-width: ${pixelsToRem(600)}rem) { + flex-direction: row; + } +`; + +const DateHeader = styled.div` + display: flex; + justify-content: center; + + padding-bottom: 4px; + @media (min-width: ${pixelsToRem(600)}rem) { + padding-bottom: 0; + } +`; + +const Interpunct = styled.div` + color: #a8a8a8; + + display: none; + @media (min-width: ${pixelsToRem(600)}rem) { + display: inline; + padding: 0 8px; + } +`; + +const TournamentHeader = styled.div` + display: flex; + justify-content: center; + flex-wrap: wrap; +`; + +const Date = styled.time` + color: #a8a8a8; + flex-shrink: 0; +`; + +const CompetitionFormatter = styled.div` + white-space: pre; + overflow: hidden; + text-overflow: ellipsis; + padding: 0px; + flex-shrink: 1; +`; + +const formatTournamentDescriptionLabel = tournamentDescriptionLabel => { + const tournamentGroupsArray = tournamentDescriptionLabel.split(' - '); + + return tournamentGroupsArray.map((element, i) => { + if (tournamentGroupsArray.length === i + 1) { + return ( + // eslint-disable-next-line react/no-array-index-key + + {element} + + ); + } + return ( + // eslint-disable-next-line react/no-array-index-key + + {element} -{' '} + + ); + }); +}; + +const HeadToHeadHeader = ({ date, tournamentDescriptionLabel, status }) => ( + + {!isLiveStatus(status) && ( + + + {date} + + + + )} + + {formatTournamentDescriptionLabel(tournamentDescriptionLabel)} + + +); + +export default HeadToHeadHeader; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/key-events.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/key-events.jsx new file mode 100644 index 00000000000..7569e727083 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/key-events.jsx @@ -0,0 +1,58 @@ +/* eslint-disable import/prefer-default-export */ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; +import VisuallyHiddenText from '#app/components/VisuallyHiddenText'; +// import { GROUP_3, SPACING_4 } from '@bbc/web-gel-foundations'; +// import Heading from '@bbc/web-components/heading/index.js'; +import Action from './action'; +import { GRID_AREAS } from './action-grid'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const KeyEventsStyles = css` + padding: 0 16px; + @media (min-width: ${pixelsToRem(600)}rem) { + padding: 0; + } + + @supports not (display: grid) { + display: inline-flex; + width: 50%; + padding: 0 16px; + box-sizing: border-box; + } +`; + +const KeyEventsHome = styled.div` + ${KeyEventsStyles} + text-align: right; + grid-area: ${GRID_AREAS.homeText}; +`; + +const KeyEventsAway = styled.div` + ${KeyEventsStyles} + grid-area: ${GRID_AREAS.awayText}; +`; + +export const KeyEvents = ({ + homeKeyEvents, + awayKeyEvents, + homeName, + awayName, +}) => ( + <> + Key Events + + {homeName} + + + + {awayName} + + + +); diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/match-progress.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/match-progress.jsx new file mode 100644 index 00000000000..89346b42527 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/match-progress.jsx @@ -0,0 +1,112 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; +// import { +// fontScaleDescription, +// SPACING_1, +// SPACING_2, +// } from '@bbc/web-gel-foundations'; +import { getFallbackFootballPeriodLabel } from '../helpers/event-summary'; +import { isInProgressStatus } from '../helpers/event-status-groups'; +import { shouldShowScores } from './centre'; +import Period from './period'; + +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +const MatchProgressWrapper = styled.div` + display: flex; + flex-direction: column; + + ${({ isConciseView }) => + !isConciseView && + css` + padding: 8px 0 4px; + gap: 8px; + `} +`; + +const AggregateScore = styled.div` + font-size: 14px; + line-height: 1.2857142857142858; + text-align: center; + ${ + '' /* ${({ theme, isConciseView }) => + isConciseView && + css` + padding: '4px 0'; + color: ${theme.colourPalette.secondary}; + `} */ + } +`; + +const MatchProgress = ({ data, isConciseView }) => { + const { home, away, periodLabel, status, multiLeg } = data; + + const shouldDisplayAggScore = + multiLeg && + multiLeg.leg > 1 && + home.runningScores?.aggregate && + away.runningScores?.aggregate; + + const fallbackPeriod = + periodLabel && + getFallbackFootballPeriodLabel( + periodLabel, + status, + home.runningScores, + away.runningScores, + home.fullName, + away.fullName, + ); + + const shouldDisplayPeriod = + periodLabel && fallbackPeriod && shouldShowScores(status); + + if (!shouldDisplayAggScore && !shouldDisplayPeriod) { + return null; + } + + return ( + + {shouldDisplayAggScore && ( + <> + + {`Aggregate score ${home.fullName} ${home.runningScores.aggregate} , ${away.fullName} ${away.runningScores.aggregate}`} + + + + )} + {shouldDisplayPeriod && ( + <> + + {`${fallbackPeriod.accessible}${ + isInProgressStatus(status) && periodLabel.value !== 'PENS' + ? ' , in progress' + : '' + }`} + + + + )} + + ); +}; + +export default MatchProgress; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/penalty-scores.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/penalty-scores.jsx new file mode 100644 index 00000000000..1db17211f30 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/penalty-scores.jsx @@ -0,0 +1,98 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +// import { css } from '@emotion/react'; + +// import { +// GROUP_3, +// SPACING_1, +// SPACING_2, +// fontEmphasised, +// fontScaleBody, +// fontScaleDescription, +// } from '@bbc/web-gel-foundations'; +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; + +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const PenaltyScoresContainer = styled.div` + font-size: 1rem; + line-height: 1.375; + text-align: center; + padding: 4px 0; + + @media (min-width: ${pixelsToRem(600)}rem) { + padding-bottom: 8px; + } + + ${ + '' /* ${({ isConciseView }) => + isConciseView && + css` + ${fontScaleDescription} + `} */ + } +`; + +const WinningTeamName = styled.span` + ${'' /* ${fontEmphasised} */} + font-family: ReithSans, Helvetica, Arial, freesans, sans-serif; + font-weight: 700; + font-feature-settings: 'ss01' off; + ${ + '' /* color: ${({ theme, isConciseView }) => + isConciseView ? theme.colourPalette.primary : theme.colourPalette.accent}; */ + } + color: #FFD230; +`; + +const PenaltiesText = styled.div` + ${'' /* color: ${({ theme }) => theme.colourPalette.secondary}; */} + color: #A8A8A8; +`; + +const PenaltyScores = ({ data, isConciseView }) => { + const { winner, seriesWinner, multiLeg, status } = data; + + const isPostEvent = status?.toLowerCase() === 'postevent'; + const hasWinner = winner !== undefined; + const isDrawWithNoSeriesWinner = winner === 'draw' && !seriesWinner; + const isMultiLegWithNoSeriesWinner = multiLeg?.leg > 1 && !seriesWinner; + + if ( + !isPostEvent || + !hasWinner || + isDrawWithNoSeriesWinner || + isMultiLegWithNoSeriesWinner + ) { + return null; + } + + const winnerOnPenalties = seriesWinner ?? winner; + const loserOnPenalties = + winnerOnPenalties.toLowerCase() === 'home' ? 'away' : 'home'; + const winnerOnPenaltiesName = data[winnerOnPenalties].fullName; + const winnerOnPenaltiesScore = + data[winnerOnPenalties].runningScores.penaltyShootout; + const loserOnPenaltiesScore = + data[loserOnPenalties].runningScores.penaltyShootout; + + return ( + + + {`${winnerOnPenaltiesName} win ${winnerOnPenaltiesScore} - ${loserOnPenaltiesScore} on penalties`} + + + + ); +}; + +export default PenaltyScores; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/period.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/period.jsx new file mode 100644 index 00000000000..59931337627 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/period.jsx @@ -0,0 +1,63 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +// import { css } from '@emotion/react'; + +// import { +// SPACING_1, +// fontScaleBody, +// fontScaleDescription, +// } from '@bbc/web-gel-foundations'; +// import { getFallbackFootballPeriodLabel } from '@bbc/web-sport-utils'; +// import { getStyledMatchProgress } from '../helpers/colour-styles.js'; + +import { getFallbackFootballPeriodLabel } from '../helpers/event-summary'; + +const StyledPeriod = styled.div` + display: flex; + justify-content: center; + ${ + '' /* color: ${({ status, theme, isConciseView }) => + getStyledMatchProgress({ status, theme, isConciseView })}; */ + } + ${'' /* ${fontScaleBody} */} + color: #FFD230; + font-size: 1rem; + line-height: 1.375; + + ${ + '' /* ${({ isConciseView }) => + isConciseView && + css` + padding-top: ${SPACING_1}; + ${fontScaleDescription} + `} */ + } +`; + +const Period = ({ + labels, + status, + homeRunningScores, + awayRunningScores, + isConciseView, +}) => { + const period = getFallbackFootballPeriodLabel( + labels, + status, + homeRunningScores, + awayRunningScores, + ); + return ( + + ); +}; + +export default Period; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score-details.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score-details.jsx new file mode 100644 index 00000000000..0be137cb12b --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score-details.jsx @@ -0,0 +1,99 @@ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; + +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; + +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +// import { +// fontScaleDescription, +// SPACING_1, +// GROUP_3, +// SPACING_2, +// SPACING_3, +// } from '@bbc/web-gel-foundations'; +import { GRID_AREAS } from './action-grid'; + +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const ScoreDetailsWrapper = styled.div` + grid-area: ${GRID_AREAS.centreText}; + display: flex; + row-gap: 8px; + ${'' /* ${fontScaleDescription} */} + font-size: 14px; + line-height: 1.2857142857142858; + + text-align: center; + ${'' /* color: ${({ theme }) => theme.colourPalette.primary}; */} + color: #F8F8F8; + + padding: 4px 0 12px; + + flex-direction: row; + justify-content: center; + @media (min-width: ${pixelsToRem(600)}rem) { + padding: 4px 0 8px; + flex-direction: column; + justify-content: flex-start; + } +`; + +const Score = styled.div` + ${'' /* color: ${({ theme }) => theme.colourPalette.secondary}; */} + color: #A8A8A8; +`; + +const Comma = styled.span` + ${'' /* color: ${({ theme }) => theme.colourPalette.secondary}; */} + color: #A8A8A8; + + padding-right: 4px; + @media (min-width: ${pixelsToRem(600)}rem) { + display: none; + } +`; + +const ScoreDetails = ({ + homeName, + awayName, + homeRunningScores, + awayRunningScores, +}) => { + const shouldDisplayHT = Boolean( + homeRunningScores?.halftime && awayRunningScores?.halftime, + ); + const shouldDisplayFT = Boolean( + homeRunningScores?.fulltime && + awayRunningScores?.fulltime && + homeRunningScores?.extratime && + awayRunningScores?.extratime, + ); + + if (!shouldDisplayFT && !shouldDisplayHT) { + return null; + } + + return ( + + {shouldDisplayFT && ( + <> + {`Full Time ${homeName} ${homeRunningScores.fulltime} , ${awayName} ${awayRunningScores.fulltime}`} + + + + , + + )} + {shouldDisplayHT && ( + <> + {`Half Time ${homeName} ${homeRunningScores.halftime} , ${awayName} ${awayRunningScores.halftime}`}{' '} + + + )} + + ); +}; + +export default ScoreDetails; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score.jsx new file mode 100644 index 00000000000..ae0838746ea --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/score.jsx @@ -0,0 +1,149 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +// import { css } from '@emotion/react'; + +// import { +// createSize, +// fontEmphasised, +// GROUP_3, +// SPACING_1, +// SPACING_2, +// SPACING_3, +// SPACING_4, +// SPACING_6, +// // eslint-disable-next-line no-restricted-imports +// fontWeights, +// } from '@bbc/web-gel-foundations'; +// import { +// getScoreColourStyle, +// getStyledLineColour, +// } from '../helpers/colour-styles.js'; +// import { fixedHeightConciseView } from '../helpers/concise-styles.jsx'; + +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const HOME_SCORE = 'home_score'; +const VERTICAL_LINE = 'vertical_line'; +const AWAY_SCORE = 'away_score'; + +const MATCH_STATUS_LETTERS = { + Postponed: 'P', + Cancelled: 'C', +}; + +const StyledScore = styled.div` + display: grid; + grid-template-columns: 1fr auto 1fr; + grid-template-areas: '${HOME_SCORE} ${VERTICAL_LINE} ${AWAY_SCORE}'; + font-weight: 500; + align-items: center; + ${ + '' /* color: ${({ theme, status, isConciseView }) => + getScoreColourStyle({ theme, status, isConciseView })}; */ + } + color: #F8F8F8; + + font-size: ${pixelsToRem(40)}rem; + line-height: 1.1; + padding-left: 4px; + padding-right: 4px; + + @media (min-width: ${pixelsToRem(600)}rem) { + font-size: ${pixelsToRem(50)}rem; + line-height: 1.08; + padding-left: 24px; + padding-right: 24px; + } + + ${ + '' /* ${({ isConciseView, theme }) => + isConciseView && + css` + ${fontEmphasised({ theme })} + + ${fixedHeightConciseView} + font-size: ${createSize(20)}; + line-height: 1.2; + padding-left: ${SPACING_3}; + padding-right: ${SPACING_3}; + + @media (min-width: ${GROUP_3}) { + font-size: ${createSize(20)}; + line-height: 1.2; + padding-left: ${SPACING_4}; + padding-right: ${SPACING_4}; + } + `} */ + } +`; + +const HomeScore = styled.div` + grid-area: ${HOME_SCORE}; + text-align: right; +`; + +const AwayScore = styled.div` + grid-area: ${AWAY_SCORE}; + text-align: left; +`; + +export const VerticalLine = styled.div` + ${ + '' /* ${({ theme, status, isConciseView }) => css` + border-left: ${createSize(2)} solid + ${getStyledLineColour({ theme, status, isConciseView })}; + `}; */ + } + border-left: ${pixelsToRem(2)}rem solid #FFD230; + display: inline-block; + margin: 0 16px; + grid-area: ${VERTICAL_LINE}; + + height: ${pixelsToRem(38)}rem; + @media (min-width: ${pixelsToRem(600)}rem) { + height: ${pixelsToRem(44)}rem; + } + + ${ + '' /* ${({ isConciseView }) => + isConciseView && + css` + height: ${createSize(24)}; + margin: 0 ${SPACING_2}; + @media (min-width: ${GROUP_3}) { + height: ${createSize(28)}; + margin: 0 ${SPACING_3}; + } + `} */ + } +`; + +const Score = ({ + status, + home, + homeScoreUnconfirmed, + away, + awayScoreUnconfirmed, + isConciseView, +}) => { + const matchStatusLetter = MATCH_STATUS_LETTERS[status]; + const homeScore = homeScoreUnconfirmed || home; + const awayScore = awayScoreUnconfirmed || away; + + return ( + + ); +}; + +export default Score; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/badges-map.js b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/badges-map.js new file mode 100644 index 00000000000..fb60e745cfb --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/badges-map.js @@ -0,0 +1,67 @@ +// import placeholder from '@bbc/web-assets/static/sport/placeholders/placeholder-badge.svg'; +// import flagPlaceholder from '@bbc/web-assets/static/sport/placeholders/placeholder-flag.svg'; + +// import { americanFootball } from './mappings/american-football.js'; +// import basketball from './mappings/basketball.js'; +// import { getBaseCountryFlagsMapping } from './mappings/country-flags.js'; +// import netball from './mappings/netball.js'; +// import englishFootball from './mappings/football-english-domestic.js'; +// import europeanFootball from './mappings/football-european-domestic.js'; +// import footballWorldwideDomestic from './mappings/football-worldwide-domestic.js'; +// import scottishFootball from './mappings/football-scottish-domestic.js'; +// import internationalFootball from './mappings/international-football.js'; +// import olympics from './mappings/olympics.js'; +// import paralympics from './mappings/paralympics.js'; +// import rugbyUnion from './mappings/rugby-union.js'; +// import iceHockey from './mappings/ice-hockey.js'; + +const badgesMap = { + // 0: placeholder, + // ...americanFootball, + // ...basketball, + // ...netball, + // ...englishFootball, + // ...europeanFootball, + // ...footballWorldwideDomestic, + // ...scottishFootball, + // ...internationalFootball, + // ...olympics, + // ...paralympics, + // ...rugbyUnion, + // ...iceHockey, + // ...getBaseCountryFlagsMapping('formula1'), + // ...getBaseCountryFlagsMapping('athletics'), + // ...getBaseCountryFlagsMapping('cycling'), + // ...getBaseCountryFlagsMapping('golf'), + // ...getBaseCountryFlagsMapping('darts'), + // ...getBaseCountryFlagsMapping('snooker'), + // ...getBaseCountryFlagsMapping('tennis'), +}; + +export const getImage = ({ + id, + usePlaceholderFallback, + placeholderFallbackType, +}) => { + const image = badgesMap[id]; + + if (!image && usePlaceholderFallback) { + switch (placeholderFallbackType) { + case 'badge': + return null; // TODO - add badge placeholder asset and return it here + case 'flag': + return null; // TODO - add flag placeholder asset and return it here + default: + throw new Error( + `Invalid placeholder fallback type '${placeholderFallbackType}'`, + ); + } + } + + return image; +}; + +export const hasMapping = id => + Boolean(getImage({ id, usePlaceholderFallback: false })); + +export default badgesMap; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/index.js b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/index.js new file mode 100644 index 00000000000..32f26554631 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/index.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line no-restricted-exports +export { default } from './sport-badge'; +export { hasMapping as hasTeamBadgeMapping } from './badges-map'; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.jsx new file mode 100644 index 00000000000..a6a107c3be8 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.jsx @@ -0,0 +1,67 @@ +// import React from 'react'; +// import { createSize, GROUP_3, GROUP_4 } from '@bbc/web-gel-foundations'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; + +import { getImage } from './badges-map'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../../utilities/pixelsToRem'; + +const BadgeContainer = styled.div` + display: flex; + justify-content: center; + flex-shrink: 0; + + width: ${({ size = 20 }) => pixelsToRem(size.small || size)}rem; + height: ${({ size = 20 }) => pixelsToRem(size.small || size)}rem; + + @media (min-width: ${pixelsToRem(600)}rem) { + width: ${({ size = 20 }) => pixelsToRem(size.medium || size)}rem; + height: ${({ size = 20 }) => pixelsToRem(size.medium || size)}rem; + } + + @media (min-width: ${pixelsToRem(900)}rem) { + width: ${({ size = 27 }) => pixelsToRem(size.large || size)}rem; + height: ${({ size = 27 }) => pixelsToRem(size.large || size)}rem; + } +`; + +const BadgeImage = styled.img` + max-width: 100%; + max-height: 100%; + object-fit: contain; +`; + +const getTestId = id => { + const urnId = + String(id)?.match(/urn:bbc:sportsdata:football:team:(.+)/) || []; + + return urnId[1] || id; +}; + +const SportBadge = ({ + size, + id, + alt = '', + usePlaceholderFallback = true, + placeholderFallbackType = 'badge', +}) => { + const testId = getTestId(id); + const src = getImage({ id, usePlaceholderFallback, placeholderFallbackType }); + + if (!src) return null; + + return ( + + {/* Empty alt string should hide images from assistive technology, but won't hide certain SVG contents in some browsers - e.g. Safari */} + + + ); +}; +export default SportBadge; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.mdx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.mdx new file mode 100644 index 00000000000..aca7982a6f7 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/sport-badge.mdx @@ -0,0 +1,27 @@ +import { Meta } from '@storybook/addon-docs/blocks'; + + + +## Props + +| Argument | Type | Required | Default | Description | +| :--------------------- | :-------------: | :------: | :-----: | :----------------------------------------------------------------------------------- | +| id | string | Yes | | URN or Opta ID listed in mappings | +| alt | string | No | '' | Alternative text for the image | +| size | number / object | No | 27 | Image size in px; you can also specify small, medium and/or large sizes in an object | +| usePlaceholderFallback | boolean | No | true | Render a placeholder badge where mapping does not exist | + +## Usage + +### Basic Example + +``` + +``` + +## Accessibility Notes + +A major screen reader navigation bug is present in some browsers (e.g., Safari) for certain SVGs when `alt` is an empty string. +This has been mitigated by manually setting `aria-hidden` to `true`. + +This bug would result in multiple elements with the text "image" being announced for specific SVG nodes. diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/index.test.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/index.test.jsx new file mode 100644 index 00000000000..44d018bc818 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/index.test.jsx @@ -0,0 +1,94 @@ +// import React from 'react'; +import { + render, + screen, + act, +} from '#app/components/react-testing-library-with-providers'; +// import { createSize } from '@bbc/web-gel-foundations'; +import SportBadge from '../index'; + +test.skip('can render a badge for a urn identifier', async () => { + await act(async () => { + render( + , + ); + }); + const element = screen.getByRole('img'); + + expect(element).toBeInTheDocument(); + expect(element).toHaveAttribute('alt', 'Liverpool FC'); + expect(element).toHaveAttribute('data-testid', 'badge-img-liverpool'); +}); + +test.skip('can render a badge for a numeric identifier', async () => { + await act(async () => { + render(); + }); + const element = screen.getByRole('presentation', { hidden: true }); // img role does not work here, most likely due to missing alt text + + expect(element).toBeInTheDocument(); + expect(element).toHaveAttribute('data-testid', 'badge-img-58510'); +}); + +test.skip('can render a badge with an empty alt attribute', async () => { + await act(async () => { + render(); + }); + const element = screen.getByRole('presentation', { hidden: true }); // img role does not work here, most likely due to missing alt text + + expect(element).toHaveAttribute('alt', ''); +}); + +test.skip('can render a placeholder where a mapping does not exist', async () => { + await act(async () => { + render(); + }); + const element = screen.getByRole('presentation', { hidden: true }); // img role does not work here, most likely due to missing alt text + + expect(element).toHaveAttribute('alt', ''); +}); + +test.skip('does not render an image where a mapping does not exist and a placeholder fallback should be not be rendered', async () => { + await act(async () => { + render(); + }); + + expect(screen.queryByRole('img')).not.toBeInTheDocument(); +}); + +test('does not render an image where an id is not provided and a placeholder fallback should not be rendered', async () => { + await act(async () => { + render(); + }); + + expect(screen.queryByRole('img')).not.toBeInTheDocument(); +}); + +test.skip('sets aria-hidden to true when no alt text given to mitigate screen reader navigation bug', async () => { + await act(async () => { + render(); + }); + + expect(screen.getByRole('presentation', { hidden: true })).toHaveAttribute( + 'aria-hidden', + 'true', + ); // img role does not work here, most likely due to missing alt text +}); + +// test('is the correct width when a single size is specified', () => { +// render(); +// expect(getComputedStyle(screen.getByTestId('badge-container-1')).width).toBe( +// createSize(24), +// ); +// }); + +// test('is the correct width when a range of sizes is specified', () => { +// const sizeRanges = { small: 24, medium: 32, large: 64 }; +// render(); +// expect(getComputedStyle(screen.getByTestId('badge-container-1')).width).toBe( +// createSize(24), +// ); +// }); diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/mapping.test.js b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/mapping.test.js new file mode 100644 index 00000000000..433499a9146 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/sport-badge/tests/mapping.test.js @@ -0,0 +1,53 @@ +import { getImage, hasMapping } from '../badges-map'; + +describe('get image', () => { + test.each(['badge', 'flag'])( + 'returns fallback if URN or ID is not mapped, use placeholder fallback is true and placeholder fallback type is "%s"', + placeholderFallbackType => { + const src = getImage({ + id: 'urn:bbc:sportsdata:blitzball:team:super-team', + usePlaceholderFallback: true, + placeholderFallbackType, + }); + + expect(src).not.toBeUndefined(); + }, + ); + + test('returns undefined if URN or ID is not mapped and use placeholder fallback is falsy', () => { + expect(getImage({ id: 'invalid-mapping' })).toBeUndefined(); + expect( + getImage({ id: 'invalid-mapping', usePlaceholderFallback: null }), + ).toBeUndefined(); + expect( + getImage({ id: 'invalid-mapping', usePlaceholderFallback: false }), + ).toBeUndefined(); + }); + + test('throws error when invalid fallback type given', () => { + const placeholderFallbackType = 'invalid-fallback-type'; + + expect(() => + getImage({ + id: 'some-unmapped-id', + usePlaceholderFallback: true, + placeholderFallbackType, + }), + ).toThrow( + new Error( + `Invalid placeholder fallback type '${placeholderFallbackType}'`, + ), + ); + }); +}); + +describe('has mapping', () => { + // mapping logic might be removed since URLS should should provided + test.skip('returns true if a given is has a mapping', () => { + expect(hasMapping('urn:bbc:sportsdata:football:team:chelsea')).toBe(true); + }); + + test('returns false if a given is has a mapping', () => { + expect(hasMapping('invalid-mapping')).toBe(false); + }); +}); diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team-name.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team-name.jsx new file mode 100644 index 00000000000..077ff430e65 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team-name.jsx @@ -0,0 +1,92 @@ +// import React from 'react'; +// import { +// createSize, +// fontScaleBody, +// fontScaleDescription, +// fontScaleIndexHeadlineMedium, +// GROUP_3, +// GROUP_4, +// SPACING_2 +// } from '@bbc/web-gel-foundations'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +// import VisuallyHidden from '@bbc/web-components/visually-hidden/index.js'; +// eslint-disable-next-line import/no-relative-packages +import VisuallyHiddenText from '../../../../components/VisuallyHiddenText'; + +// import { fixedHeightConciseView } from '../helpers/concise-styles.jsx'; + +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const TeamNameWrapper = styled.div` + display: flex; + gap: 8px; + align-items: center; + ${ + '' /* ${({ shouldHideBadges }) => + shouldHideBadges ? fontScaleIndexHeadlineMedium : fontScaleBody} */ + } + font-size: 1rem; + line-height: 1.375; + padding: ${({ shouldHideBadges }) => + shouldHideBadges ? '0 8px' : '0 0 8px'}; + + @media (min-width: ${pixelsToRem(600)}rem) { + padding: 0; + ${'' /* ${fontScaleIndexHeadlineMedium} */} + font-size: 1.25rem; + line-height: 1.2; + + @media (min-width: ${pixelsToRem(600)}rem) { + font-size: 1.5rem; + line-height: 1.1666666666666667; + } + } + + ${({ isConciseView }) => + isConciseView && + css` + ${'' /* ${fixedHeightConciseView} */} + ${'' /* ${fontScaleDescription} */} + font-size: 14px; + line-height: 1.2857142857142858; + padding: 0; + + @media (min-width: ${pixelsToRem(600)}rem) { + font-size: ${pixelsToRem(16)}rem; + line-height: 1.375; + } + `} +`; + +const MobileValue = styled.span` + @media (min-width: ${pixelsToRem(900)}rem) { + display: none; + } +`; + +const DesktopValue = styled.span` + display: none; + @media (min-width: ${pixelsToRem(900)}rem) { + display: inline; + } +`; + +const TeamName = ({ fullName, shortName, isConciseView, shouldHideBadges }) => ( + + + + + {fullName === 'TBC' ? 'Team to be confirmed' : fullName} + + +); + +export default TeamName; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team.jsx new file mode 100644 index 00000000000..502fe264415 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/components/team.jsx @@ -0,0 +1,130 @@ +// import React from 'react'; +// import styled, { css } from '@bbc/web-styled'; + +import styled from '@emotion/styled'; +import { css } from '@emotion/react'; + +// import { +// /GROUP_3, +// fontScaleBody, +// createSize, +// SPACING_3, +// SPACING_2, +// SPACING_5, +// } from '@bbc/web-gel-foundations'; +import SportBadge from './sport-badge/index'; +import TeamName from './team-name'; +// eslint-disable-next-line import/no-relative-packages +import pixelsToRem from '../../../../utilities/pixelsToRem'; + +const StyledTeam = styled.div` + display: flex; + gap: 8px; + align-items: center; + justify-content: flex-start; + flex-grow: 2; + font-size: 1rem; + line-height: 1.375; + + flex-direction: ${({ isConciseView, shouldHideBadges }) => + isConciseView || shouldHideBadges ? 'row' : 'column'}; + + @media (min-width: ${pixelsToRem(600)}rem) { + gap: 20px; + flex-direction: row; + } + + ${({ isConciseView }) => + isConciseView && + css` + @media (min-width: ${pixelsToRem(600)}rem) { + gap: 12px; + } + `} +`; + +const HomeTeam = styled(StyledTeam)` + justify-content: flex-end; + text-align: right; + ${({ isConciseView, shouldHideBadges }) => + !isConciseView && + !shouldHideBadges && + css` + @media (max-width: calc(${pixelsToRem(600)}rem - ${pixelsToRem(1)}rem)) { + justify-content: flex-end; + flex-direction: column-reverse; + text-align: center; + } + `} +`; + +const AwayTeam = styled(StyledTeam)` + justify-content: flex-start; + text-align: left; + + ${({ isConciseView, shouldHideBadges }) => + !isConciseView && + !shouldHideBadges && + css` + @media (max-width: calc(${pixelsToRem(600)}rem - ${pixelsToRem(1)}rem)) { + text-align: center; + } + `} +`; + +const Team = ({ + alignment, + name, + shortName, + urn, + isConciseView, + shouldHideBadges, + badgePlaceholderFallbackType, +}) => { + const size = isConciseView + ? { small: 20, medium: 24, large: 24 } + : { small: 40, medium: 44, large: 44 }; + if (alignment === 'home') { + return ( + + + {!shouldHideBadges && ( + + )} + + ); + } + return ( + + {!shouldHideBadges && ( + + )} + + + ); +}; + +export default Team; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-mid-events.stories.tsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-mid-events.stories.tsx new file mode 100644 index 00000000000..c558508803b --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-mid-events.stories.tsx @@ -0,0 +1,485 @@ +import { + firstHalf90Data, + secondHalf90Data, + firstHalfAggData, + etFirstHalfData, + inPensAetData, + beforePensData, + beforePensAetData, + beforeEtData, + inPens90Data, + secondLegETData, + secondLegAETInPensData, +} from './static-data/event/transformed/mid-event'; +import { HeadToHeadV2 } from './head-to-head-v2'; +import { shortNamesMap } from './storybook/helpers/short-name-map'; +import { + HeadToHeadV2Component, + HeadToHeadV2ConciseComponent, +} from './storybook/helpers/base-component'; + +import venuesData from './static-data/premier-league-venues.json'; + +const { venues } = venuesData; + +const getBaseDataWithEuropaLeagueTournament = baseData => ({ + ...baseData, + tournamentDescriptionLabel: 'UEFA Europa Conference League', +}); + +// OPTIONAL - KEEP STORY ARGS SIMPLE +// export default { +// title: 'Components/Live Page Sport Data Header/Head To Head V2 - Mid event', +// component: HeadToHeadV2, +// }; + +// OPTIONAL - MORE COMPLEX STORY ARGS - USES SHORT NAMES MAP ETC, REDUCED FROM PS ORIGINAL +export default { + title: 'Components/Live Page Sport Data Header/Head To Head V2 - Mid event', + component: HeadToHeadV2, + parameters: { chromatic: { disable: true } }, + argTypes: { + home: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + away: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + venue: { + options: venues, + control: { type: 'select' }, + }, + status: { + table: { disable: true }, + }, + date: { control: 'date' }, + }, +}; + +export const FirstHalfOf90Mins = HeadToHeadV2Component.bind({}); +export const FirstHalfOf90MinsWithHomeScoreUnconfirmed = + HeadToHeadV2Component.bind({}); +export const SecondHalfOf90Mins = HeadToHeadV2Component.bind({}); +export const InPenaltiesAfter90Mins = HeadToHeadV2Component.bind({}); +export const ExtraTime = HeadToHeadV2Component.bind({}); +export const InPenaltiesAfterExtraTime = HeadToHeadV2Component.bind({}); +export const BeforePensAfterExtraTime = HeadToHeadV2Component.bind({}); +export const BeforeEt = HeadToHeadV2Component.bind({}); +export const FirstHalfOf90MinsSecondLeg = HeadToHeadV2Component.bind({}); +export const ExtraTimeSecondLeg = HeadToHeadV2Component.bind({}); +export const InPenaltiesAfterExtraTimeSecondLeg = HeadToHeadV2Component.bind( + {}, +); +export const BeforePens = HeadToHeadV2Component.bind({}); +export const FirstHalfOf90MinsConcise = HeadToHeadV2ConciseComponent.bind({}); +export const SecondHalfOf90MinsConcise = HeadToHeadV2ConciseComponent.bind({}); +export const InPenaltiesAfter90MinsConcise = HeadToHeadV2ConciseComponent.bind( + {}, +); +export const ExtraTimeConcise = HeadToHeadV2ConciseComponent.bind({}); +export const InPenaltiesAfterExtraTimeConcise = + HeadToHeadV2ConciseComponent.bind({}); +export const BeforePensConcise = HeadToHeadV2ConciseComponent.bind({}); +export const BeforePensAfterExtraTimeConcise = + HeadToHeadV2ConciseComponent.bind({}); +export const BeforeEtConcise = HeadToHeadV2ConciseComponent.bind({}); +export const FirstHalfOf90MinsSecondLegConcise = + HeadToHeadV2ConciseComponent.bind({}); +export const ExtraTimeSecondLegConcise = HeadToHeadV2ConciseComponent.bind({}); +export const InPenaltiesAfterExtraTimeSecondLegConcise = + HeadToHeadV2ConciseComponent.bind({}); + +// @ts-expect-error - PS copy and paste +FirstHalfOf90Mins.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: getBaseDataWithEuropaLeagueTournament(firstHalf90Data), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: firstHalf90Data.home.actions, + awayActions: firstHalf90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FirstHalfOf90MinsWithHomeScoreUnconfirmed.args = { + home: 'Arsenal', + homeScore: '3', + homeScoreUnconfirmed: '4', + away: 'Aston Villa', + awayScore: '0', + awayScoreUnconfirmed: '0', + baseData: getBaseDataWithEuropaLeagueTournament(firstHalf90Data), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: firstHalf90Data.home.actions, + awayActions: firstHalf90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +SecondHalfOf90Mins.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: getBaseDataWithEuropaLeagueTournament(secondHalf90Data), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: secondHalf90Data.home.actions, + awayActions: secondHalf90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfter90Mins.args = { + home: 'Arsenal', + homeScore: '3', + away: 'Aston Villa', + awayScore: '3', + baseData: getBaseDataWithEuropaLeagueTournament(inPens90Data), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: inPens90Data.home.actions, + awayActions: inPens90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforePens.args = { + home: 'Arsenal', + homeScore: '3', + away: 'Aston Villa', + awayScore: '3', + baseData: beforePensData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: beforePensData.home.actions, + awayActions: beforePensData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforeEt.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: beforeEtData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup - 3rd Round', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: beforeEtData.home.actions, + awayActions: beforeEtData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +ExtraTime.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: etFirstHalfData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup - 3rd Round', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: etFirstHalfData.home.actions, + awayActions: etFirstHalfData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfterExtraTime.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: getBaseDataWithEuropaLeagueTournament(inPensAetData), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: inPensAetData.home.actions, + awayActions: inPensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforePensAfterExtraTime.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: beforePensAetData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: beforePensAetData.home.actions, + awayActions: beforePensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FirstHalfOf90MinsSecondLeg.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: getBaseDataWithEuropaLeagueTournament(firstHalfAggData), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Champions League', + urn: 'urn:bbc:sportsdata:football:tournament:champions-league', + }, + homeActions: firstHalfAggData.home.actions, + awayActions: firstHalfAggData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +ExtraTimeSecondLeg.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: getBaseDataWithEuropaLeagueTournament(secondLegETData), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: secondLegETData.home.actions, + awayActions: secondLegETData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfterExtraTimeSecondLeg.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: getBaseDataWithEuropaLeagueTournament(secondLegAETInPensData), + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: secondLegAETInPensData.home.actions, + awayActions: secondLegAETInPensData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FirstHalfOf90MinsConcise.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: firstHalf90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: firstHalf90Data.home.actions, + awayActions: firstHalf90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +SecondHalfOf90MinsConcise.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: secondHalf90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: secondHalf90Data.home.actions, + awayActions: secondHalf90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfter90MinsConcise.args = { + home: 'Arsenal', + homeScore: '3', + away: 'Aston Villa', + awayScore: '3', + baseData: inPens90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: inPens90Data.home.actions, + awayActions: inPens90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +ExtraTimeConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: etFirstHalfData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup - 3rd Round', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: etFirstHalfData.home.actions, + awayActions: etFirstHalfData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforeEtConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: beforeEtData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup - 3rd Round', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: beforeEtData.home.actions, + awayActions: beforeEtData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforePensConcise.args = { + home: 'Arsenal', + homeScore: '3', + away: 'Aston Villa', + awayScore: '3', + baseData: beforePensData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: beforePensData.home.actions, + awayActions: beforePensData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfterExtraTimeConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: inPensAetData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: inPensAetData.home.actions, + awayActions: inPensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +BeforePensAfterExtraTimeConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: beforePensAetData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: beforePensAetData.home.actions, + awayActions: beforePensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FirstHalfOf90MinsSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '0', + away: 'Aston Villa', + awayScore: '0', + baseData: firstHalfAggData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Champions League', + urn: 'urn:bbc:sportsdata:football:tournament:champions-league', + }, + homeActions: firstHalfAggData.home.actions, + awayActions: firstHalfAggData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +ExtraTimeSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: secondLegETData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: secondLegETData.home.actions, + awayActions: secondLegETData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +InPenaltiesAfterExtraTimeSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: secondLegAETInPensData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: secondLegAETInPensData.home.actions, + awayActions: secondLegAETInPensData.away.actions, +}; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-post-events.stories.tsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-post-events.stories.tsx new file mode 100644 index 00000000000..6472424b02e --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-post-events.stories.tsx @@ -0,0 +1,334 @@ +// import { BREAKPOINT_VIEWPORTS } from '@bbc/web-gel-foundations'; +// import { INITIAL_VIEWPORTS } from 'storybook/viewport'; +import { + postEventData, + postEventAETData, + postEventAgg90Data, + postEventPens90Data, + postEventPensAetData, + postEventPensAetAggData, + finishedAetAggData, +} from './static-data/event/transformed/post-event'; + +// import mdx from './head-to-head-v2.mdx'; +// import metadata from './metadata.json'; +import { HeadToHeadV2 } from './head-to-head-v2'; +import { shortNamesMap } from './storybook/helpers/short-name-map'; +import { + HeadToHeadV2Component, + HeadToHeadV2ConciseComponent, +} from './storybook/helpers/base-component'; + +import venuesData from './static-data/premier-league-venues.json'; + +const { venues } = venuesData; + +export default { + title: 'Components/Live Page Sport Data Header/Head To Head V2 - Post event', + component: HeadToHeadV2, + parameters: { chromatic: { disable: true } }, + // tags: ['autodocs'], + // parameters: { + // metadata, + // docs: { + // description: { + // component: + // 'The `Head to Head V2` component is used to render event data.', + // }, + // page: mdx, + // }, + // chromatic: { + // viewports: [375, ...BREAKPOINT_VIEWPORTS], + // }, + // viewport: { + // viewports: INITIAL_VIEWPORTS, + // }, + // }, + // globals: { + // corePalette: 'lightAlternative', + // servicePalette: 'sportLight', + // fontPalette: 'sansSimple', + // }, + argTypes: { + home: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + away: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + venue: { + options: venues, + control: { type: 'select' }, + }, + status: { + table: { disable: true }, + }, + date: { control: 'date' }, + }, + args: { + isView: false, + }, +}; + +export const FullTimeAfter90Mins = HeadToHeadV2Component.bind({}); +export const AfterExtraTime = HeadToHeadV2Component.bind({}); +export const FullTimeAfter90MinsSecondLeg = HeadToHeadV2Component.bind({}); +export const PenaltiesAfter90Mins = HeadToHeadV2Component.bind({}); +export const PenaltiesAfterExtraTime = HeadToHeadV2Component.bind({}); +export const PenaltiesAfterExtraTimeSecondLeg = HeadToHeadV2Component.bind({}); +export const AfterExtraTimeSecondLeg = HeadToHeadV2Component.bind({}); +export const FullTimeAfter90MinsConcise = HeadToHeadV2ConciseComponent.bind({}); +export const AfterExtraTimeConcise = HeadToHeadV2ConciseComponent.bind({}); +export const FullTimeAfter90MinsSecondLegConcise = + HeadToHeadV2ConciseComponent.bind({}); +export const PenaltiesAfter90MinsConcise = HeadToHeadV2ConciseComponent.bind( + {}, +); +export const PenaltiesAfterExtraTimeConcise = HeadToHeadV2ConciseComponent.bind( + {}, +); +export const PenaltiesAfterExtraTimeSecondLegConcise = + HeadToHeadV2ConciseComponent.bind({}); +export const AfterExtraTimeSecondLegConcise = HeadToHeadV2ConciseComponent.bind( + {}, +); + +// @ts-expect-error - PS copy and paste +FullTimeAfter90Mins.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: postEventData.home.actions, + awayActions: postEventData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +AfterExtraTime.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventAETData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: postEventAETData.home.actions, + awayActions: postEventAETData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FullTimeAfter90MinsSecondLeg.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventAgg90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: postEventAgg90Data.home.actions, + awayActions: postEventAgg90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfter90Mins.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventPens90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: postEventPens90Data.home.actions, + awayActions: postEventPens90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfterExtraTime.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventPensAetData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: postEventPensAetData.home.actions, + awayActions: postEventPensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfterExtraTimeSecondLeg.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventPensAetAggData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: postEventPensAetAggData.home.actions, + awayActions: postEventPensAetAggData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +AfterExtraTimeSecondLeg.args = { + home: 'Arsenal', + homeScore: '4', + away: 'Aston Villa', + awayScore: '2', + baseData: finishedAetAggData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: finishedAetAggData.home.actions, + awayActions: finishedAetAggData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FullTimeAfter90MinsConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, + homeActions: postEventData.home.actions, + awayActions: postEventData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +AfterExtraTimeConcise.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventAETData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: postEventAETData.home.actions, + awayActions: postEventAETData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +FullTimeAfter90MinsSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventAgg90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: postEventAgg90Data.home.actions, + awayActions: postEventAgg90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfter90MinsConcise.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventPens90Data, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'League Cup', + urn: 'urn:bbc:sportsdata:football:tournament:league-cup', + }, + homeActions: postEventPens90Data.home.actions, + awayActions: postEventPens90Data.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfterExtraTimeConcise.args = { + home: 'Arsenal', + homeScore: '1', + away: 'Aston Villa', + awayScore: '1', + baseData: postEventPensAetData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'FA Cup', + urn: 'urn:bbc:sportsdata:football:tournament:fa-cup', + }, + homeActions: postEventPensAetData.home.actions, + awayActions: postEventPensAetData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +PenaltiesAfterExtraTimeSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '2', + away: 'Aston Villa', + awayScore: '2', + baseData: postEventPensAetAggData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: postEventPensAetAggData.home.actions, + awayActions: postEventPensAetAggData.away.actions, +}; + +// @ts-expect-error - PS copy and paste +AfterExtraTimeSecondLegConcise.args = { + home: 'Arsenal', + homeScore: '4', + away: 'Aston Villa', + awayScore: '2', + baseData: finishedAetAggData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'UEFA Europa League', + urn: 'urn:bbc:sportsdata:football:tournament:europa-league', + }, + homeActions: finishedAetAggData.home.actions, + awayActions: finishedAetAggData.away.actions, +}; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-pre-events.stories.tsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-pre-events.stories.tsx new file mode 100644 index 00000000000..c13b36e7070 --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2-pre-events.stories.tsx @@ -0,0 +1,149 @@ +// import { BREAKPOINT_VIEWPORTS } from '@bbc/web-gel-foundations'; +// import { INITIAL_VIEWPORTS } from 'storybook/viewport'; +import { preEventData } from './static-data/event/transformed/pre-event/index'; + +// import mdx from './head-to-head-v2.mdx'; +// import metadata from './metadata.json'; +import { HeadToHeadV2 } from './head-to-head-v2'; +import { shortNamesMap } from './storybook/helpers/short-name-map'; + +import { + HeadToHeadV2Component, + HeadToHeadV2ConciseComponent, +} from './storybook/helpers/base-component'; + +import venuesData from './static-data/premier-league-venues.json'; + +const { venues } = venuesData; + +export default { + title: 'Components/Live Page Sport Data Header/Head To Head V2 - Pre Events', + component: HeadToHeadV2, + parameters: { chromatic: { disable: true } }, + // tags: ['autodocs'], + // parameters: { + // metadata, + // docs: { + // description: { + // component: + // 'The `Head to Head V2` container is used to render event data.', + // }, + // page: mdx, + // }, + // chromatic: { + // viewports: [375, ...BREAKPOINT_VIEWPORTS], + // }, + // viewport: { + // viewports: INITIAL_VIEWPORTS, + // }, + // }, + globals: { + corePalette: 'lightAlternative', + servicePalette: 'sportLight', + fontPalette: 'sansSimple', + }, + argTypes: { + home: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + away: { + options: Object.keys(shortNamesMap()), + control: { type: 'select' }, + }, + venue: { + options: venues, + control: { type: 'select' }, + }, + status: { + table: { disable: true }, + }, + date: { control: 'date' }, + }, +}; + +export const PreEventConcise = HeadToHeadV2ConciseComponent.bind({}); +export const PreEventConciseOneTeam = HeadToHeadV2ConciseComponent.bind({}); +export const PreEventConciseNoTeams = HeadToHeadV2ConciseComponent.bind({}); + +// @ts-expect-error - PS copy and paste +PreEventConcise.args = { + home: 'Arsenal', + away: 'Aston Villa', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; + +// @ts-expect-error - PS copy and paste +PreEventConciseOneTeam.args = { + home: 'TBC', + away: 'Aston Villa', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'To be confirmed', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; + +// @ts-expect-error - PS copy and paste +PreEventConciseNoTeams.args = { + home: 'TBC', + away: 'TBC', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'To be confirmed', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; + +export const PreEvent = HeadToHeadV2Component.bind({}); +export const PreEventOneTeam = HeadToHeadV2Component.bind({}); +export const PreEventNoTeams = HeadToHeadV2Component.bind({}); + +// @ts-expect-error - PS copy and paste +PreEvent.args = { + home: 'Arsenal', + away: 'Aston Villa', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'Emirates Stadium', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; + +// @ts-expect-error - PS copy and paste +PreEventOneTeam.args = { + home: 'TBC', + away: 'Aston Villa', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'To be confirmed', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; + +// @ts-expect-error - PS copy and paste +PreEventNoTeams.args = { + home: 'TBC', + away: 'TBC', + baseData: preEventData, + date: new Date('2023-01-01T13:00:00Z'), + venue: 'To be confirmed', + tournament: { + name: 'Premier League', + urn: 'urn:bbc:sportsdata:football:tournament:premier-league', + }, +}; diff --git a/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2.jsx b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2.jsx new file mode 100644 index 00000000000..0e1ae8e853b --- /dev/null +++ b/src/app/components-webcore/SportDataHeader/head-to-head-v2/head-to-head-v2.jsx @@ -0,0 +1,100 @@ +// import React from 'react'; +// import styled from '@bbc/web-styled'; +import styled from '@emotion/styled'; +// import { fontStandard, GROUP_3, SPACING_2 } from '@bbc/web-gel-foundations'; +// import { shouldShowTeamBadges } from '@bbc/web-sport-utils'; +// import shouldShowTeamBadges from './helpers/badges/should-show-team-badges'; + +import Footer from './components/footer'; +import HeadToHeadHeader from './components/head-to-head-header'; +// import { getStatusBorderStyles } from './helpers/colour-styles.js'; +import { HeadToHeadBanner } from './components/head-to-head-banner'; +import { ConditionalOnwardJourneyLink } from './components/conditional-onward-journey-link'; +import { Actions } from './components/actions'; +import pixelsToRem from '../../../utilities/pixelsToRem'; + +const StyledHeadToHeadWrapper = styled.div` + background: ${({ isConciseView }) => + isConciseView ? '#202020' : '#181818'}; // GREY_15 : GREY_16 + ${ + '' /* border-left: ${({ status, isConciseView }) => + getStatusBorderStyles({ status, isConciseView })}; */ + } + border-left: medium none #009E9E; +`; + +const StyledHeadToHead = styled.div` + font-family: ReithSans, Helvetica, Arial, freesans, sans-serif; + font-weight: 400; + font-feature-settings: 'ss01' off; + color: #f8f8f8; + padding: ${({ isConciseView }) => (isConciseView ? `8px` : `0`)}; + padding-bottom: ${({ isConciseView }) => + !isConciseView && + `${pixelsToRem(24)}rem`}; // TODO - decide if we want to move these styles to live page layout + + @media (max-width: ${pixelsToRem(600)}rem) { + padding-top: ${({ isConciseView }) => (isConciseView ? `8px` : `0`)}; + padding-bottom: ${({ isConciseView }) => + !isConciseView && + `${pixelsToRem(8)}rem`}; // TODO - decide if we want to move these styles to live page layout + } +`; + +/** + * @type {typeof import('./types.ts').HeadToHeadV2} + */ +export const HeadToHeadV2 = ({ + data, + isConciseView, + shouldShowActions, + maximumContainerScoreDigits, + teamBadgePlaceholderFallbackType = 'badge', +}) => { + const hasActions = + data?.home?.actions?.length > 0 || data?.away?.actions?.length > 0; + // const shouldHideBadges = !shouldShowTeamBadges(data.tournament?.urn); + const shouldHideBadges = true; // TODO: Re-enable badge visibility logic once we have the necessary badge mappings in place + + return ( + + + + {!isConciseView && ( + + )} + + {hasActions && shouldShowActions && } + {!isConciseView && } + {!isConciseView && ( +