diff --git a/dotcom-rendering/src/palette.ts b/dotcom-rendering/src/palette.ts new file mode 100644 index 00000000000..342a852f1e2 --- /dev/null +++ b/dotcom-rendering/src/palette.ts @@ -0,0 +1,175 @@ +// ----- Imports ----- // + +import { ArticleDesign, type ArticleFormat } from '@guardian/libs'; +import { palette as sourcePalette } from '@guardian/source-foundations'; + +// ----- Palette Functions ----- // + +const headlineColourLight = ({ design }: ArticleFormat): string => { + switch (design) { + case ArticleDesign.Feature: + return sourcePalette.news[300]; + default: + return sourcePalette.neutral[10]; + } +}; + +const headlineColourDark = ({ design }: ArticleFormat): string => { + switch (design) { + case ArticleDesign.Feature: + return sourcePalette.news[600]; + default: + return sourcePalette.neutral[97]; + } +}; + +const headlineBackgroundColourLight = ({ design }: ArticleFormat): string => { + switch (design) { + case ArticleDesign.LiveBlog: + return sourcePalette.news[400]; + default: + return sourcePalette.neutral[100]; + } +}; + +const headlineBackgroundColourDark = ({ design }: ArticleFormat): string => { + switch (design) { + case ArticleDesign.LiveBlog: + return sourcePalette.news[200]; + default: + return sourcePalette.neutral[7]; + } +}; + +// ----- Palette ----- // + +/** + * A template literal type used to make sure the keys of the palette use the + * correct CSS custom property syntax. + */ +type CSSCustomProperty = `--${string}`; +/** + * Ensures that all palette functions provide the same API, deriving a palette + * colour from an {@linkcode ArticleFormat}. + */ +type PaletteFunction = (f: ArticleFormat) => string; +/** + * Used to validate that the palette object always has the correct shape, + * without changing its type. + */ +type PaletteColours = Record< + CSSCustomProperty, + { + light: PaletteFunction; + dark: PaletteFunction; + } +>; + +/** + * Maps palette colour names (which are also CSS custom property names) to + * a pair of palette functions, which can be used to derive both light and dark + * mode colours from an {@linkcode ArticleFormat}. + * + * This is not accessed directly in components; the {@linkcode palette} function + * is used instead. + */ +const paletteColours = { + '--headline-colour': { + light: headlineColourLight, + dark: headlineColourDark, + }, + '--headline-background-colour': { + light: headlineBackgroundColourLight, + dark: headlineBackgroundColourDark, + }, +} satisfies PaletteColours; + +/** + * A union of all the keys of the palette object. In other words, all the + * possible colours that can be chosen. + */ +type ColourName = keyof typeof paletteColours; + +/** + * Looks up a palette colour by name. Retrieves a CSS value for the specified + * colour, for use in CSS declarations. See the examples for how this is + * commonly used with our Emotion-based styles. + * + * @param a The name of a palette colour; for example `--headline-colour`. + * @returns A CSS `var` function call; for example `var(--headline-colour)`. + * @example + * const styles = css` + * color: ${palette('--headline-colour')}; + * background-color: ${palette('--headline-background-colour')}; + * `; + */ +const palette = (colour: ColourName): string => `var(${colour})`; + +/** + * Builds a list of CSS custom property declarations representing colours. These + * can be used to set up the palette on any element, and then retrieved to apply + * styles via the {@linkcode palette} function. See the examples for ways the + * palette could be set up. + * + * @param format The `ArticleFormat` of the current article. + * @param colourScheme Get declarations for either `light` or `dark` mode. + * @returns A set of CSS custom property declarations for palette colours, + * in string format. For example: + * ``` + * [ '--headline-colour: #1a1a1a;', '--headline-background-colour: #ffffff;' ] + * ``` + * @example + *