Skip to content

Commit

Permalink
Media cards: Show waveform on podcast cards (#13082)
Browse files Browse the repository at this point in the history
* Show podcast waveform in cards

* Add separate waveform component with updated SVG

* Add waveform to palette

* Adjust waveform size depending on viewport and orientation

* Optimise SVG to round paths to whole pixels

* Optimise waveform SVG and use pattern to repeat

* Restrict podcast waveform to beta containers

* Extend waveform to full width of card

* Add comment to SVG

* Remove unnecessary styles
  • Loading branch information
jamesmockett authored Jan 9, 2025
1 parent 5df7716 commit 0693247
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
37 changes: 37 additions & 0 deletions dotcom-rendering/src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import type {
ImageSizeType,
} from './components/ImageWrapper';
import { ImageWrapper } from './components/ImageWrapper';
import { SvgWaveform } from './components/SvgWaveform';
import { TrailText, type TrailTextSize } from './components/TrailText';

export type Position = 'inner' | 'outer' | 'none';
Expand Down Expand Up @@ -176,6 +177,27 @@ const StarRatingComponent = ({
</div>
);

const waveformWrapper = (
imagePositionOnMobile?: ImagePositionType,
imagePositionOnDesktop?: ImagePositionType,
) => css`
position: absolute;
left: 0;
right: 0;
bottom: 0;
svg {
display: block;
width: 100%;
height: ${imagePositionOnMobile === 'top' ? 50 : 29}px;
${from.mobileMedium} {
height: ${imagePositionOnMobile === 'top' ? 50 : 33}px;
}
${from.tablet} {
height: ${imagePositionOnDesktop === 'top' ? 50 : 33}px;
}
}
`;

const HorizontalDivider = () => (
<div
css={css`
Expand Down Expand Up @@ -710,6 +732,20 @@ export const Card = ({
containerType={containerType}
gapSize={getGapSize()}
>
{/**
* Waveform for podcasts is absolutely positioned at bottom of
* card, behind everything else
*/}
{isBetaContainer && mainMedia?.type === 'Audio' && (
<div
css={waveformWrapper(
imagePositionOnMobile,
imagePositionOnDesktop,
)}
>
<SvgWaveform />
</div>
)}
{media && (
<ImageWrapper
imageSize={imageSize}
Expand Down Expand Up @@ -928,6 +964,7 @@ export const Card = ({
{/* This div is needed to keep the headline and trail text justified at the start */}
<div
css={css`
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-start;
Expand Down
42 changes: 42 additions & 0 deletions dotcom-rendering/src/components/Card/components/SvgWaveform.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useId } from 'react';
import { palette } from '../../../palette';

/**
* Static waveform image used as a background on podcast media cards.
* The waveform is a repeating pattern so can be used at any width.
*/

export const SvgWaveform = () => {
const id = useId();

return (
<svg
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="none"
focusable={false}
aria-hidden={true}
>
<pattern
id={`waveform-pattern-${id}`}
viewBox="0 0 300 40"
width="300"
height="100%"
patternUnits="userSpaceOnUse"
preserveAspectRatio="none"
>
<path
stroke={palette('--card-media-waveform')}
stroke-width="2"
d="M1,24V40M4,15V40M7,8V40M10,1V40M13,2V40M16,4V40M19,6V40M22,8V40M25,9V40M28,6V40M31,7V40M34,7V40M37,9V40M40,11V40M43,7V40M46,8V40M49,6V40M52,7V40M55,9V40M58,10V40M61,12V40M64,14V40M67,16V40M70,16V40M73,11V40M76,12V40M79,13V40M82,14V40M85,14V40M88,15V40M91,16V40M94,18V40M97,18V40M100,17V40M103,19V40M106,20V40M109,21V40M112,9V40M115,11V40M118,11V40M121,10V40M124,7V40M127,8V40M130,9V40M133,10V40M136,12V40M139,12V40M142,4V40M145,5V40M148,5V40M151,6V40M154,8V40M157,10V40M160,8V40M163,4V40M166,4V40M169,5V40M172,3V40M175,4V40M178,4V40M181,5V40M184,7V40M187,8V40M190,10V40M193,13V40M196,15V40M199,13V40M202,6V40M205,8V40M208,10V40M211,11V40M214,11V40M217,12V40M220,13V40M223,5V40M226,5V40M229,7V40M232,8V40M235,9V40M238,9V40M241,10V40M244,10V40M247,11V40M250,12V40M253,13V40M256,14V40M259,15V40M262,15V40M265,14V40M268,15V40M271,16V40M274,18V40M277,19V40M280,12V40M283,13V40M286,13V40M289,14V40M292,15V40M295,18V40M298,20V40"
/>
</pattern>
<rect
x="0"
y="0"
width="100%"
height="100%"
fill={`url(#waveform-pattern-${id})`}
></rect>
</svg>
);
};
7 changes: 7 additions & 0 deletions dotcom-rendering/src/paletteDeclarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2495,6 +2495,9 @@ const cardMediaIconLight: PaletteFunction = (format) =>
const cardMediaIconDark: PaletteFunction = (format) =>
cardMediaBackgroundDark(format);

const cardMediaWaveformLight: PaletteFunction = () => sourcePalette.neutral[86];
const cardMediaWaveformDark: PaletteFunction = () => sourcePalette.neutral[38];

const cardHeadlineTextLight: PaletteFunction = () => sourcePalette.neutral[7];

const cardTextDark: PaletteFunction = () => sourcePalette.neutral[86];
Expand Down Expand Up @@ -6073,6 +6076,10 @@ const paletteColours = {
light: cardMediaIconLight,
dark: cardMediaIconDark,
},
'--card-media-waveform': {
light: cardMediaWaveformLight,
dark: cardMediaWaveformDark,
},
'--card-sublinks-background': {
light: cardSublinksBackgroundLight,
dark: cardSublinksBackgroundDark,
Expand Down

0 comments on commit 0693247

Please sign in to comment.