Kesko Design System’s color palette is a selection of colors that work together to create consistency in digital products.
The palette #
Neutral
Beige
Red
Orange
Yellow
Green
Teal
Blue
Purple
Dark mode Experimental #
Our color system includes a dedicated neutral-dark ramp alongside the standard light neutral ramp. Together they provide the surface and text colors needed to support both light and dark modes without manual color picking. Each step in the dark neutral ramp is the semantic counterpart of the same step in the light neutral ramp:
Choosing colors for dark mode #
Saturated colors can be converted from a light theme to a dark theme using symmetry. The 12-step palette can be divided in half, and each half becomes a mirror of the other:
- If an element uses step
800in light mode, it uses step500in dark mode. - If a surface uses step
200in light mode, it uses step1100in dark mode. - The midpoint sits between steps
600and700.
Please note: While this approach provides a great starting point, it does not work for every single use case. An example could be e.g. specific brand colors that you want to keep uniform across different theme modes.
Installation #
To install Kesko’s color utilities as a dependency in your project, run:
npm install @kesko/colorpnpm add @kesko/coloryarn add @kesko/colorbun add @kesko/colorUsage #
Import from @kesko/color directly only when you need to create a new color palette family or compose your own theme. The package exposes two helper functions, keskoPalette() and keskoTheme(), for exactly this.
keskoPalette() #
Creates a new Kesko color palette family with built-in defaults. The name is automatically prefixed with --k-color-, and the 12 default contrast ratios match the rest of the Kesko palette so a custom family slots in seamlessly alongside the built-in ones:
import { keskoPalette } from "@kesko/color";
const palette = keskoPalette({
name: "palette",
colorKeys: ["#f86800"],
});Pass two or more colorKeys to interpolate between multiple hues across the scale:
const palette = keskoPalette({
name: "palette",
colorKeys: ["#f86800", "#cb4b00"],
});The full list of provided options includes:
const palette = keskoPalette({
/**
* Color palette name
* @type {string}
*/
name: "palette",
/**
* Source color(s) as hex values
* @type {string[]}
*/
colorKeys: ["#f86800"],
/**
* WCAG contrast ratios for each generated color
* @type {number[]}
*/
ratios: [1.06, 1.12, 1.22, 1.32, 1.45, 1.7, 2.5, 4.6, 6, 9, 16, 18],
/**
* Interpolation colorspace
* @type {"RGB" | "HSL" | "HSV" | "HSLuv" | "LAB" | "LCH" | "OKLAB" | "OKLCH" | "CAM02" | "CAM02p"}
*/
colorspace: "RGB",
/**
* Smooth interpolation between hues
* @type {boolean}
*/
smooth: true,
/**
* Global saturation adjustment (0–100)
* @type {number}
*/
saturation: 100,
});keskoTheme() #
Combines one or more color palette families against a background and resolves them into a full theme. This is the step that actually generates the 12 colors per family. Until a palette is part of a theme, only its source keys and target ratios are defined.
import { keskoTheme, background, neutral, orange } from "@kesko/color";
const theme = keskoTheme({
colors: [neutral, orange],
backgroundColor: background,
});The full list of provided options includes:
const theme = keskoTheme({
/**
* Array of color palettes to include in the theme
* @type {Color[]}
*/
colors: [orange, blue],
/**
* Reference background for contrast calculations
* @type {BackgroundColor}
*/
backgroundColor: background,
/**
* Background lightness (0–100)
* @type {number}
*/
lightness: 100,
/**
* Global contrast multiplier
* @type {number}
*/
contrast: 1,
/**
* Global saturation adjustment (0–100)
* @type {number}
*/
saturation: 100,
/**
* Output color format
* @type {"HEX" | "RGB" | "HSL" | "HSV" | "LAB" | "LCH" | "CAM02" | "CAM02p"}
*/
output: "HEX",
/**
* Contrast formula
* @type {"wcag2" | "wcag3"}
*/
formula: "wcag2",
});Included utilities #
Alongside the two helpers, @kesko/color ships the default Kesko color palette families and fully composed themes as named exports, so you can drop them straight into a custom keskoTheme() call:
keskoPalette(): Helper to create a new color palette familykeskoTheme(): Helper to compose one or more palettes into a themetheme: Fully composed light theme combining all 9 families against a white backgrounddarkTheme: Dark theme with the neutral-dark palette against a dark backgroundbackground: White (#fff) reference background for light-mode contrast mathdarkBackground: Dark reference background for dark-mode contrast mathneutral: Neutral palette, pinned to white/black at extremesneutralDark: Neutral-dark palette, pinned to near-black/white at extremes (inverse of neutral)orange: Orange palettebeige: Beige paletteyellow: Yellow palettepurple: Purple palettegreen: Green paletteteal: Teal paletteblue: Blue palettered: Red palette
Accessibility #
Every step in the light palette is generated by targeting a specific WCAG 2 contrast ratio against #fff. The neutral-dark palette targets the same ratios against its dark background. As a rule of thumb:
Light mode (neutral and saturated palettes):
- Steps 800 and above meet WCAG 2 AA (4.5:1) for normal-size text on white.
- Step 700 meets WCAG 2 AA (3:1) for large text and non-text elements (UI components, graphical objects).
- Steps 100–600 are intended for backgrounds, surfaces, and decorative use, not for text on white.
Dark mode (neutral-dark palette):
- Steps 800 and above meet WCAG 2 AA (4.5:1) for normal-size text on the dark background.
- The same ratio thresholds apply meaning that the palette is generated with identical contrast targets, just inverted.
When pairing colors against backgrounds other than the palette's reference background, always re-verify contrast with a tool such as the WebAIM contrast checker.