88 textSansBold28 ,
99 visuallyHidden ,
1010} from '@guardian/source/foundations' ;
11+ import { getContrast } from '../lib/colour' ;
1112import { palette } from '../palette' ;
1213
1314const containerCss = css `
@@ -44,7 +45,7 @@ const labelCss = css`
4445 ${ textSansBold14 } ;
4546 grid- area: label;
4647 justify- self: center;
47- color : ${ palette ( '--football-match-stat-name ' ) } ;
48+ color : ${ palette ( '--football-match-stat-text ' ) } ;
4849 ${ from . desktop } {
4950 ${ textSansBold15 } ;
5051 }
@@ -62,6 +63,10 @@ const largeNumberCss = css`
6263 }
6364` ;
6465
66+ const numberFixContrastCss = css `
67+ color : ${ palette ( '--football-match-stat-text' ) } ;
68+ ` ;
69+
6570const awayStatCss = css `
6671 grid- area: away- stat;
6772 justify- self: end;
@@ -80,6 +85,10 @@ const barCss = css`
8085 bor der- radius: 8px;
8186` ;
8287
88+ const barFixContrastCss = css `
89+ bor der: 1px solid ${ palette ( '--football-match-stat-text' ) } ;
90+ ` ;
91+
8392type MatchStatistic = {
8493 teamName : string ;
8594 teamColour : string ;
@@ -109,12 +118,33 @@ export const FootballMatchStat = ({
109118 const homePercentage = ( home . value / ( home . value + away . value ) ) * 100 ;
110119 const awayPercentage = ( away . value / ( home . value + away . value ) ) * 100 ;
111120
121+ const minimumContrast = 3.1 ; // https://www.w3.org/TR/WCAG21/#contrast-minimum
122+
123+ const darkMode = window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ;
124+ const backgroundColour = darkMode ? '#1a1a1a' : '#f6f6f6' ;
125+
126+ const homeNeedsContrast =
127+ getContrast ( home . teamColour , backgroundColour ) < minimumContrast ;
128+ const awayNeedsContrast =
129+ getContrast ( away . teamColour , backgroundColour ) < minimumContrast ;
130+
131+ /**
132+ * If either team colour lacks sufficient contrast we adjust both numbers
133+ * so we don't appear to be favouring one team over the other. For the chart
134+ * we keep the team colour and apply a contrasting border colour.
135+ */
136+ const numbersNeedContrast = homeNeedsContrast || awayNeedsContrast ;
137+
112138 return (
113139 < div css = { containerCss } >
114140 < div css = { [ headerCss , raiseLabelOnDesktop && raiseLabelCss ] } >
115141 < span css = { labelCss } > { label } </ span >
116142 < span
117- css = { [ numberCss , largeNumbersOnDesktop && largeNumberCss ] }
143+ css = { [
144+ numberCss ,
145+ largeNumbersOnDesktop && largeNumberCss ,
146+ numbersNeedContrast && numberFixContrastCss ,
147+ ] }
118148 style = { { '--match-stat-team-colour' : home . teamColour } }
119149 >
120150 < span
@@ -131,6 +161,7 @@ export const FootballMatchStat = ({
131161 numberCss ,
132162 awayStatCss ,
133163 largeNumbersOnDesktop && largeNumberCss ,
164+ numbersNeedContrast && numberFixContrastCss ,
134165 ] }
135166 style = { { '--match-stat-team-colour' : away . teamColour } }
136167 >
@@ -146,14 +177,14 @@ export const FootballMatchStat = ({
146177 </ div >
147178 < div aria-hidden = "true" css = { chartCss } >
148179 < div
149- css = { barCss }
180+ css = { [ barCss , homeNeedsContrast && barFixContrastCss ] }
150181 style = { {
151182 '--match-stat-percentage' : `${ homePercentage } %` ,
152183 '--match-stat-team-colour' : home . teamColour ,
153184 } }
154185 > </ div >
155186 < div
156- css = { barCss }
187+ css = { [ barCss , awayNeedsContrast && barFixContrastCss ] }
157188 style = { {
158189 '--match-stat-percentage' : `${ awayPercentage } %` ,
159190 '--match-stat-team-colour' : away . teamColour ,
0 commit comments