Kesko’s iconography shares the same rounded, curved language as our typography and other UI elements. They are designed to work together as one cohesive system.

Installation #

To install Kesko Design System icons as a dependency in your project, run:

npm install @kesko/iconography

Then import an icon:

// Plain JavaScript
import iconArrowDown from "@kesko/iconography/arrow-down.js";

// React
import { IconArrowDown } from "@kesko/iconography/react";

React usage #

Import individual icon components for optimal tree-shaking. Each component accepts size, color, and label props:

import { IconArrowDown, IconSearch } from "@kesko/iconography/react";

// Decorative icon (aria-hidden, no label needed)
<IconArrowDown size="lg" color="var(--k-color-text-primary)" />

// Accessible icon (sets role="img" and aria-label)
<IconSearch size="sm" label="Search" />

You can also import by component name directly:

import IconArrowDown from "@kesko/iconography/react/IconArrowDown";

<IconArrowDown size="md" label="Navigate down" />;

When the icon name is dynamic (e.g. from data or props), use the Icon container component. Note that this imports all ~360 icons into your bundle:

import { Icon } from "@kesko/iconography/react";

<Icon name="arrow-down" size="md" label="Navigate down" />;

React Props #

All individual React icon components accept the following props:

PropTypeDefaultDescription
size"xs" | "sm" | "md" | "lg" | "xl" | number | string"md"Size or a custom value. xs = 16 px, sm = 20 px, md = 24 px, lg = 32 px, xl = 48 px. Pass a number or CSS string (e.g. "2rem") for custom sizing.
labelstringSets aria-label and role="img". Omitting this will make the SVG hidden for assistive technologies. This is the correct behavior when an icon accompanies visible text.
colorstringAny CSS color value, including design tokens (e.g. "var(--k-color-accent)"). When omitted, the icon inherits color via the CSS cascade.

The React Icon container component additionally requires a name prop typed as KeskoIconName:

PropTypeDescription
nameKeskoIconNameIcon identifier, e.g. "arrow-down". Provides autocomplete via the KeskoIconName union type.

All React components work with React 17, 18, 19, and Next.js (including App Router and React Server Components).


JavaScript usage #

Each icon is also available as an individual ES module. The SVG string is the default export:

import svg, { title, tags } from "@kesko/iconography/arrow-down.js";

// Inject into the DOM
const el = document.createElement("span");
el.innerHTML = svg;
document.body.appendChild(el);

Or use in any string-based template engine (Lit, Nunjucks, etc.):

const html = `<button class="k-button">Download ${svg}</button>`;

SVG usage #

Each icon is also available as a raw .svg file. Use these when you need the actual SVG asset. For example in <img> tags or build tools that process SVG files directly:

<!-- Reference from node_modules -->
<img src="node_modules/@kesko/iconography/arrow-down.svg" alt="Arrow down" />

You can also copy or import them in bundlers that support SVG file loading:

// Webpack, Vite, etc. (with appropriate loader/plugin)
import arrowDown from "@kesko/iconography/arrow-down.svg";

Or read them on the server side:

import { readFileSync } from "node:fs";
import { createRequire } from "node:module";

const require = createRequire(import.meta.url);
const svgPath = require.resolve("@kesko/iconography/arrow-down.svg");
const svg = readFileSync(svgPath, "utf-8");

Figma usage #


Accessibility #

Icons are decorative by default. This means that they render with aria-hidden="true" and are invisible to assistive technology. This is the correct behavior when an icon accompanies visible text (e.g. an icon inside a button with a label).

When an icon conveys meaning on its own (e.g. a standalone icon button with no visible text), pass the label prop to make it accessible:

// Decorative: button has visible text
<button>
  <IconDownload /> Download
</button>

// Meaningful: icon is the only content
<button>
  <IconDownload label="Download" />
</button>

TypeScript #

Type definitions are included. Import IconProps and IconNameProps from the package.

import type { IconProps, IconNameProps } from "@kesko/iconography/react";

// IconProps: extends SVGProps<SVGSVGElement>, so all SVG/HTML attributes are accepted
interface IconProps extends Omit<SVGProps<SVGSVGElement>, "ref"> {
  /** xs = 16px, sm = 20px, md = 24px (default), lg = 32px, xl = 48px, or a custom number/string */
  size?: "xs" | "sm" | "md" | "lg" | "xl" | number | string;
  /** Sets aria-label and role="img". Omit for decorative (aria-hidden) icons */
  label?: string;
  /** Any CSS color value or design token. When omitted, inherits via CSS cascade */
  color?: string;
}

// IconNameProps: used by the <Icon> container component
interface IconNameProps extends IconProps {
  /** Icon identifier, e.g. "arrow-down". Typed as a union of all ~360 icon names */
  name: KeskoIconName;
}

The main @kesko/iconography entry point exports types for working with icon metadata directly:

import type { KeskoIcon, KeskoIconName, KeskoIcons } from "@kesko/iconography";

// A single icon's metadata and SVG markup
type KeskoIcon = {
  title: KeskoIconName;
  category: string;
  tags: string;
  svg: string;
};

// Union of all ~360 icon name strings, e.g. "arrow-down" | "arrow-left" | ...
type KeskoIconName = "arrow-down" | "arrow-left" | /* … */;

// The full icon map: Record<KeskoIconName, KeskoIcon>
type KeskoIcons = Record<KeskoIconName, KeskoIcon>;

Metadata #

Each icon in the package includes the following metadata:

FieldTypeDescription
titlestringFilename of the SVG asset (e.g. "arrow-down").
categorystringOne of the valid category values defined in icons-schema.json (see categories).
tagsstringSpace-separated keywords for search and filtering.

Categories #

All icons are grouped under the following categories:

  • Action: Generic UI actions: edit, delete, download, search.
  • Attention: Feedback states: info, warning, notice, availability.
  • Car: Car trade: vehicles, fuel types, EV charging.
  • Common: General-purpose icons used across multiple contexts.
  • Communication: Messaging, mail, phone, news, FAQ.
  • Grocery: Grocery trade: food, beverages, clothing, household and seasonal.
  • Hardware: Hardware trade: hardware, tools, home improvement.
  • Kesko: Kesko brand marks and store format identifiers.
  • Location: Map and place icons: location pin, world, building.
  • Navigation: Directional and wayfinding: arrows, chevrons, menu.
  • People: User and group representations.
  • Shopping: Commerce and checkout: cart, payment, delivery.
  • Social: Social media brand logos.
  • Sustainability: Eco labels, dietary markers, environmental icons.
  • Time: Clock, calendar, history, timer.

Known issues #

Import error with moduleResolution: "node" #

The shorthand import paths like @kesko/iconography/react use the exports field in package.json, which requires moduleResolution set to "bundler", "node16", or "nodenext" in your tsconfig.json.

If your project uses "moduleResolution": "node" and you cannot change it, use the full dist/ paths instead:

// Individual components (tree-shakeable)
import IconArrowDown from "@kesko/iconography/dist/react/IconArrowDown.js";

// Container component (imports all icons)
import { Icon } from "@kesko/iconography/dist/react/index.js";

// Types
import type { IconProps } from "@kesko/iconography/dist/react/index.js";
// Plain JavaScript
import svg from "@kesko/iconography/dist/assets/arrow-down.js";

// Raw SVG file
import arrowDown from "@kesko/iconography/dist/assets/arrow-down.svg";

// Full metadata
import icons from "@kesko/iconography/dist/icons.js";

These paths resolve to actual files in node_modules and work with any moduleResolution setting.

Sizing raw SVG imports #

The SVG files in @kesko/iconography do not include width or height attributes, they only define a viewBox. This is intentional and allows the icons to be scaled to any size via CSS without having to override the hardcoded dimensions. This applies to both raw .svg file imports and the SVG strings from the ES module imports (.js).

When using SVG imports outside of the React components, you need to set the size yourself in CSS:

.icon {
  inline-size: 24px;
  block-size: 24px;
}

The React components handle this automatically via the size prop.


Requesting icon #

All Kesko shared icons should be added and used through this library. Please see our support page for more information on how to contact us.