From 37810172408c1472b766e5eb24b6ed9a0c9d088c Mon Sep 17 00:00:00 2001 From: James Mockett <1166188+jamesmockett@users.noreply.github.com> Date: Wed, 18 Dec 2024 11:01:14 +0000 Subject: [PATCH] Media Cards: Update palette (#12980) * Update media card light and dark mode palettes * Palette entry for media card backgrounds * Palette entry for media icons * Special palette overrides for media cards * Apply extra padding to all media cards * Remove media card kicker colour variations * Update `cardHasDarkBackground` for media cards * Adjust content padding when in flexible container --- dotcom-rendering/src/components/Card/Card.tsx | 19 ++-- .../Card/components/ContentWrapper.tsx | 38 ++++++-- .../src/components/ContainerOverrides.tsx | 18 ++++ dotcom-rendering/src/components/MediaMeta.tsx | 2 +- dotcom-rendering/src/lib/cardHelpers.test.ts | 2 +- dotcom-rendering/src/lib/cardHelpers.ts | 2 +- dotcom-rendering/src/paletteDeclarations.ts | 88 ++++++++----------- 7 files changed, 103 insertions(+), 66 deletions(-) diff --git a/dotcom-rendering/src/components/Card/Card.tsx b/dotcom-rendering/src/components/Card/Card.tsx index 27a39eea5d3..568562a1b4b 100644 --- a/dotcom-rendering/src/components/Card/Card.tsx +++ b/dotcom-rendering/src/components/Card/Card.tsx @@ -447,10 +447,14 @@ export const Card = ({ isOpinion && !isOnwardContent && media?.type === 'avatar'; /** - * Some cards in standard containers have contrasting background colours. - * We need to add additional padding to these cards to keep the text readable. - */ - const hasBackgroundColour = !containerPalette && isMediaCard(format); +- * Media cards have contrasting background colours. We add additional + * padding to these cards to keep the text readable. +- */ + const hasBackgroundColour = isMediaCard(format); + + const backgroundColour = hasBackgroundColour + ? palette('--card-media-background') + : palette('--card-background'); /* Whilst we migrate to the new container types, we need to check which container we are in. */ const isFlexibleContainer = @@ -494,7 +498,7 @@ export const Card = ({ /** Determines the gap of between card components based on card properties */ const getGapSize = (): GapSize => { if (isOnwardContent) return 'none'; - if (hasBackgroundColour) return 'tiny'; + if (hasBackgroundColour && !isFlexibleContainer) return 'tiny'; if (!!isFlexSplash || (isFlexibleContainer && imageSize === 'jumbo')) { return 'small'; } @@ -580,7 +584,7 @@ export const Card = ({ css={css` padding-bottom: ${space[5]}px; `} - style={{ backgroundColor: palette('--card-background') }} + style={{ backgroundColor: backgroundColour }} > {/* This div is needed to keep the headline and trail text justified at the start */}
{ + /** + * If we're in a flexible container there is a 20px gap between the image + * and content. We don't apply padding to the content on the same edge as + * the image so the content is aligned with the grid. + */ + if (isFlexibleContainer && imagePosition === 'left') { + return css` + padding: ${space[1]}px ${space[1]}px ${space[1]}px 0; + `; + } + + if (isFlexibleContainer && imagePosition === 'right') { + return css` + padding: ${space[1]}px 0 ${space[1]}px ${space[1]}px; + `; + } + + return css` + padding: ${space[1]}px; + `; +}; + type Props = { children: React.ReactNode; imageType?: CardImageType; @@ -68,6 +94,7 @@ type Props = { imagePositionOnDesktop: ImagePositionType; hasBackgroundColour?: boolean; isOnwardContent?: boolean; + isFlexibleContainer?: boolean; }; export const ContentWrapper = ({ @@ -77,6 +104,7 @@ export const ContentWrapper = ({ imagePositionOnDesktop, hasBackgroundColour, isOnwardContent, + isFlexibleContainer = false, }: Props) => { const isHorizontalOnDesktop = imagePositionOnDesktop === 'left' || imagePositionOnDesktop === 'right'; @@ -85,14 +113,10 @@ export const ContentWrapper = ({
{children} diff --git a/dotcom-rendering/src/components/ContainerOverrides.tsx b/dotcom-rendering/src/components/ContainerOverrides.tsx index 32b0517178b..2d81685ac19 100644 --- a/dotcom-rendering/src/components/ContainerOverrides.tsx +++ b/dotcom-rendering/src/components/ContainerOverrides.tsx @@ -580,6 +580,16 @@ const cardBackgroundDark: ContainerFunction = (containerPalette) => { } }; +const cardMediaBackgroundLight: ContainerFunction = (containerPalette) => + transparentColour(cardHeadlineLight(containerPalette), 0.1); +const cardMediaBackgroundDark: ContainerFunction = (containerPalette) => + transparentColour(cardHeadlineDark(containerPalette), 0.1); + +const cardMediaIconLight: ContainerFunction = (containerPalette) => + cardBackgroundLight(containerPalette); +const cardMediaIconDark: ContainerFunction = (containerPalette) => + cardBackgroundDark(containerPalette); + const sectionBackgroundLight: ContainerFunction = (containerPalette) => { switch (containerPalette) { case 'InvestigationPalette': @@ -1069,6 +1079,14 @@ const containerColours = { light: cardKickerTextLight, dark: cardKickerTextDark, }, + '--card-media-background': { + light: cardMediaBackgroundLight, + dark: cardMediaBackgroundDark, + }, + '--card-media-icon': { + light: cardMediaIconLight, + dark: cardMediaIconDark, + }, '--card-sublinks-background': { light: cardSublinksBackgroundLight, dark: cardSublinksBackgroundDark, diff --git a/dotcom-rendering/src/components/MediaMeta.tsx b/dotcom-rendering/src/components/MediaMeta.tsx index de5554f6a77..41e68063479 100644 --- a/dotcom-rendering/src/components/MediaMeta.tsx +++ b/dotcom-rendering/src/components/MediaMeta.tsx @@ -29,7 +29,7 @@ const iconWrapperStyles = (hasKicker: boolean) => css` margin-right: auto; margin-top: 2px; display: block; - fill: ${themePalette('--card-background')}; + fill: ${themePalette('--card-media-icon')}; } `; diff --git a/dotcom-rendering/src/lib/cardHelpers.test.ts b/dotcom-rendering/src/lib/cardHelpers.test.ts index c0f8339dcfb..aee50798179 100644 --- a/dotcom-rendering/src/lib/cardHelpers.test.ts +++ b/dotcom-rendering/src/lib/cardHelpers.test.ts @@ -33,7 +33,7 @@ describe('cardHasDarkBackground', () => { { format: galleryFormat, containerPalette: undefined, - expectedResult: true, + expectedResult: false, }, { format: pictureFormat, diff --git a/dotcom-rendering/src/lib/cardHelpers.ts b/dotcom-rendering/src/lib/cardHelpers.ts index 9f204ae3577..0bc491e6a29 100644 --- a/dotcom-rendering/src/lib/cardHelpers.ts +++ b/dotcom-rendering/src/lib/cardHelpers.ts @@ -40,7 +40,7 @@ export const cardHasDarkBackground = ( case 'PodcastPalette': // If no containerPalette provided, card is in a standard container case undefined: { - return isMediaCard(format); + return false; } } }; diff --git a/dotcom-rendering/src/paletteDeclarations.ts b/dotcom-rendering/src/paletteDeclarations.ts index 5d095e4ff2e..30c15bcd8c6 100644 --- a/dotcom-rendering/src/paletteDeclarations.ts +++ b/dotcom-rendering/src/paletteDeclarations.ts @@ -22,7 +22,6 @@ import { type ArticleTheme, Pillar, } from './lib/articleFormat'; -import { isMediaCard } from './lib/cardHelpers'; import { transparentColour } from './lib/transparentColour'; // ----- Palette Functions ----- // @@ -2479,21 +2478,28 @@ const cardBorderSupportingLight: PaletteFunction = () => const cardBorderSupportingDark: PaletteFunction = () => sourcePalette.neutral[46]; -const cardMetaTextLight: PaletteFunction = (format) => - isMediaCard(format) ? sourcePalette.neutral[86] : sourcePalette.neutral[46]; +const cardMetaTextLight: PaletteFunction = () => sourcePalette.neutral[46]; const cardMetaTextDark: PaletteFunction = () => sourcePalette.neutral[60]; -const cardBackground: PaletteFunction = (format) => - isMediaCard(format) ? sourcePalette.neutral[20] : 'transparent'; +const cardBackgroundLight: PaletteFunction = () => 'transparent'; +const cardBackgroundDark: PaletteFunction = () => 'transparent'; -const cardHeadlineTextLight: PaletteFunction = (format) => - isMediaCard(format) ? sourcePalette.neutral[100] : sourcePalette.neutral[7]; +const cardMediaBackgroundLight: PaletteFunction = () => + sourcePalette.neutral[97]; +const cardMediaBackgroundDark: PaletteFunction = () => + sourcePalette.neutral[20]; + +const cardMediaIconLight: PaletteFunction = (format) => + cardMediaBackgroundLight(format); +const cardMediaIconDark: PaletteFunction = (format) => + cardMediaBackgroundDark(format); + +const cardHeadlineTextLight: PaletteFunction = () => sourcePalette.neutral[7]; const cardTextDark: PaletteFunction = () => sourcePalette.neutral[86]; -const cardTrailTextLight: PaletteFunction = (format) => - isMediaCard(format) ? sourcePalette.neutral[86] : sourcePalette.neutral[38]; +const cardTrailTextLight: PaletteFunction = () => sourcePalette.neutral[38]; const cardTrailTextDark: PaletteFunction = () => sourcePalette.neutral[73]; const liveKickerBackgroundLight: PaletteFunction = (format) => { @@ -2539,44 +2545,20 @@ const liveKickerPulsingDot: PaletteFunction = () => transparentColour(sourcePalette.neutral[97], 0.75); const cardKickerTextLight: PaletteFunction = (format) => { - switch (format.design) { - case ArticleDesign.Gallery: - case ArticleDesign.Audio: - case ArticleDesign.Video: - switch (format.theme) { - case Pillar.News: - return sourcePalette.news[550]; - case Pillar.Sport: - return sourcePalette.sport[600]; - case Pillar.Opinion: - return sourcePalette.opinion[550]; - case Pillar.Lifestyle: - return sourcePalette.lifestyle[500]; - case Pillar.Culture: - return sourcePalette.culture[500]; - case ArticleSpecial.Labs: - return sourcePalette.labs[400]; - case ArticleSpecial.SpecialReport: - return sourcePalette.news[400]; - case ArticleSpecial.SpecialReportAlt: - return sourcePalette.specialReportAlt[200]; - } - default: - switch (format.theme) { - case Pillar.Opinion: - return pillarPalette(format.theme, 300); - case Pillar.Sport: - case Pillar.Culture: - case Pillar.Lifestyle: - case Pillar.News: - return pillarPalette(format.theme, 400); - case ArticleSpecial.Labs: - return sourcePalette.labs[200]; - case ArticleSpecial.SpecialReport: - return sourcePalette.news[400]; - case ArticleSpecial.SpecialReportAlt: - return sourcePalette.specialReportAlt[200]; - } + switch (format.theme) { + case Pillar.Opinion: + return pillarPalette(format.theme, 300); + case Pillar.Sport: + case Pillar.Culture: + case Pillar.Lifestyle: + case Pillar.News: + return pillarPalette(format.theme, 400); + case ArticleSpecial.Labs: + return sourcePalette.labs[200]; + case ArticleSpecial.SpecialReport: + return sourcePalette.news[400]; + case ArticleSpecial.SpecialReportAlt: + return sourcePalette.specialReportAlt[200]; } }; @@ -6061,8 +6043,8 @@ const paletteColours = { dark: captionTextDark, }, '--card-background': { - light: cardBackground, - dark: cardBackground, + light: cardBackgroundLight, + dark: cardBackgroundDark, }, '--card-background-hover': { light: cardBackgroundHover, @@ -6088,6 +6070,14 @@ const paletteColours = { light: cardKickerTextLight, dark: cardKickerTextDark, }, + '--card-media-background': { + light: cardMediaBackgroundLight, + dark: cardMediaBackgroundDark, + }, + '--card-media-icon': { + light: cardMediaIconLight, + dark: cardMediaIconDark, + }, '--card-sublinks-background': { light: cardSublinksBackgroundLight, dark: cardSublinksBackgroundDark,