The following set of principles guide our team when naming things in the system. These principles are loosely based on the guidelines from Brad Frost’s CSS Architecture for Design Systems.

Make it modular #

Modularity reduces complexity and improves our system’s reusability. This applies to our naming as well. Different parts of the design system need to be clearly separated.

Keep it consistent #

Consistency enhances clarity and makes our design system more predictable and easy to use. We use the same language and naming wherever possible.

Prioritize legibility #

Developers and designers should be able to understand the system at a glance and understand the structure and purpose of any given part.

Avoid conflicts #

It’s critical to ensure that the design system’s naming doesn’t conflict with other libraries and systems. This is accomplished by the provided namespacing.

Clarity over succinctness #

The system may seem verbose, but it delivers clarity and resilience in exchange. Keeping naming legible and scalable sometimes means sacrificing a shorter syntax.


Colors #

Semantic colors #

Semantic colors carry meaning and imply how and where they should be used. Each semantic color name contains a role, a modifier, and a theme mode. This accommodates needs such as state, interactivity, and emphasis for different Kesko brands. For example, a component may require color variations for :hover and :focus states.

  • Naming structure: k-color-{role}-{modifier}-{theme}
  • Role: Each color has a specific role in the Kesko Design System such as accent, border, text, status, or bg.
  • Modifier: Modifiers are optional and may include variations such as weak, strong, active, hover, or success.
  • Theme: User interface theme modes, such as light or dark.
  • Usage example:
    • k-color-text-accent
    • k-color-text-on-accent
    • k-color-bg-accent
    • k-color-bg-highlight
    • k-color-status-error
    • k-color-status-info

Primitive colors #

For the Kesko primitive palette, we use numeric scales (100, 200, 300, ..). This provides clear ordering and makes it easy to add values between the existing tokens when necessary.

  • Naming structure:
    • k-color-{name}-{variant}
  • Valid characters: Allowed characters include lowercase ASCII letters (a-z) and hyphens (-). Do not use uppercase characters, symbols, underscores (_), dots (.), or digits (0-9).
  • Usage example:
    • k-color-orange-100
    • k-color-orange-200
    • k-color-red-100
    • k-color-red-200
    • k-color-blue-100
    • k-color-blue-200
  • Categories:
    • Orange
    • Beige
    • Blue
    • Green
    • Purple
    • Red
    • Teal
    • Yellow
    • Neutral
  • Tints and shades:
    • 100
    • 200
    • 300
    • 400
    • 500
    • 600
    • 700
    • 800
    • 900
    • 1000
    • 1100
    • 1200

Components #

Kesko’s component library ship as React components in addition to matching Custom Elements and CSS classes so that consumers without React can reach the same visual styling through @kesko/css.

React components #

  • Format: PascalCase, for example Button, Spinner, Stack, VisuallyHidden.
  • Noun rather than verb: Components are not actions, they are conceptually “things.” Prefer Animation over Animating.
  • Meaningful: Not over specific, not overly abstract.
  • Short: Maximum of 2 words. Prefer 1 word when possible.
  • Pronounceable: We want to be able to talk about them.
  • Usage examples:
    • <Button />
    • <Input />
    • <Spinner />
    • <Stack />
    • <VisuallyHidden />

Custom elements #

  • Naming structure: {prefix}-{name}.
  • Prefix: Component names always start with a prefix and a hyphen. For example k-stack or k-spinner. “K” stands for “Kesko”. Prefixing is critical to ensure that our naming doesn’t conflict with other systems.
  • Noun rather than verb: Components are not actions, they are conceptually “things.” It is better to use nouns instead of verbs, such as <k-animation> instead of <k-animating>.
  • Must contain a hyphen: Must have at least one hyphen (-), such as k-element.
  • Valid characters: Allowed characters include lowercase ASCII letters (a-z) and hyphens (-). Do not use uppercase characters, symbols, underscores (_), dots (.), or digits (0-9). Meaningful: Not over specific, not overly abstract.
  • Short: Maximum of 2 words after k- prefix.
  • Pronounceable: We want to be able talk about them.
  • Custom element spec compliant: Don’t use the following reserved names:
    • annotation-xml
    • color-profile
    • font-face
    • font-face-src
    • font-face-uri
    • font-face-format
    • font-face-name
    • missing-glyph
  • Usage examples:
    • <k-alert>
    • <k-badge>
    • <k-stack>
    • <k-icon>
    • <k-divider>
    • <k-visually-hidden>

CSS Properties #

  • Naming structure: var(--k-{component}-{property}) for public properties.
  • Private properties: var(--_k-{component}-{property}) for private properties.
  • Prefix: --k- prefixes a public custom property, meaning developers can use it to fine tune components. --_k- prefixes a private custom property, which is reserved for internal design system use.
  • Usage examples:
    • var(--k-button-border-radius)
    • var(--k-button-font-size)
    • var(--k-button-background)
    • var(--k-button-border-radius)

Design Tokens #

Designers and developers should be able to understand the purpose of a design token at a glance. To make sure naming stays consistent and legible, we follow these guidelines for design tokens:

  • Naming structure:
    • {prefix}-{category}-{name}-{variant}
    • {prefix}-{category}-{subcategory}-{name}-{variant}
  • Prefix: Design token names always start with a prefix and a hyphen. For example k-color-accent or k-font-size-xl. “K” stands for “Kesko”. Prefixing is critical to ensure that our naming doesn’t conflict with other systems.
  • Noun rather than verb: Design Tokens are not actions, they are conceptually “things.” It is better to use nouns instead of verbs, such as k-color-success instead of k-color-succeed.
  • Valid characters: Allowed characters include lowercase ASCII letters (a-z) and hyphens (-). Do not use uppercase characters, symbols, underscores (_), dots (.), or digits (0-9).
  • Default value: When naming sizes, {prefix}-{category}-{name}-md is always the default value.
  • Categorization: Design token names always include at least one category, like color,font, or similar. If it makes sense, you can also include a subcategory, for example k-font-size-xl or k-color-status-error.
  • Usage examples:
    • k-color-accent
    • k-color-text
    • k-color-text-link
    • k-color-text-on-accent
    • k-color-bg
    • k-color-bg-surface
    • k-color-status-error
    • k-color-status-success
    • k-font-size-xl
    • k-font-weight-bold
    • k-font-family-sans
    • k-font-leading-md
  • Font weights:
    • black
    • bold
    • medium
    • regular
  • Categories and subcategories:
    • Color
      • Accent
      • Bg
      • Border
      • Fill
      • Overlay
      • Status
      • Text
      • Orange
      • Beige
      • Blue
      • Green
      • Purple
      • Red
      • Teal
      • Yellow
      • Neutral
      • Neutral Dark
      • Brand
    • Font
      • Family
      • Leading
      • Size
      • Weight
    • Layer
    • Motion
      • Duration
      • Easing
    • Opacity
    • Radius
    • Shadow
    • Size
      • Border
    • Space

Sizes #

Kesko Design System defines semantic sizes using the t-shirt metaphor. This makes it possible for anyone, technical or non-technical person, to understand the differences and how they relate to each other at a glance.

  • Keep it consistent and short: Always use the short form version (sm, md, lg, xl) when naming things. This makes it quicker for developers and designers to reference the sizes.
  • Default size: md is always the default value.
  • Larger than default: When you want to define a size larger than medium, use lg, xl, 2xl, 3xl.
  • Smaller than default: When you want to define a size smaller than medium, we use sm, xs, 2xs, 3xs.
  • Usage example:
    • k-font-size-2xl
    • k-font-size-xl
    • k-font-size-lg
    • k-font-size-md
    • k-font-size-sm

Styles #

Our design system styles follow a simple naming structure based on .{prefix}-{name}-{modifier} format.

  • Naming structure: .{prefix}-{name}-{modifier}.
  • Prefix: Styles always start with a prefix and a hyphen. For example .k-button or .k-input. “K” stands for “Kesko”. Prefixing is critical to ensure that our naming doesn’t conflict with other systems.
  • Modifiers: Modifier is a flag on an element. Use them to change appearance or behavior. For example .k-button-primary or .k-button-outline.
  • Status: To indicate status, we use a specific class name .k-is-{status}. For example: .k-is-loading.
  • Usage examples:
    • .k-button
    • .k-input
    • .k-button-outline
    • .k-is-loading

Properties #

When naming component properties, it’s important to pay attention to the consistency between the different components so that the API stays as predictable as possible. The same conventions apply to component properties in Figma.

React props #

  • Mirror HTML where possible: When an equivalent HTML attribute exists, use the same name — e.g. disabled, size, type. This makes the React API read naturally alongside native element properties and is especially important for form components.
  • Format: camelCase for multi-word names (e.g. onPress, expand), lowercase for single-word names (e.g. size, variant). Event handlers follow the on{Event} pattern (e.g. onPress, onFocus).
  • Meaningful: Not over specific, not overly abstract.
  • Short: Maximum of 2 words. Prefer 1 word when possible.
  • Pronounceable: We want to be able to talk about them.
  • Sizes: Use a property called size and follow our sizes guideline for naming.
  • Disabled state: Use a boolean property named disabled.
  • Style variants: Use a property called variant for style variants such as primary, secondary, or plain.
  • Reserved names: Avoid property names that collide with React’s own reserved names:
    • children
    • className
    • style
    • ref
    • key
    • dangerouslySetInnerHTML

Custom element attributes #

  • Generic rules: Follow the HTMLElement API to make sure the developer- and LLM-facing APIs are as predictable as possible. This is especially important for form components.
  • Valid characters: Allowed characters include lowercase ASCII letters (a-z) and hyphens (-). Do not use uppercase characters, symbols, underscores (_), dots (.), or digits (0-9).
  • Meaningful: Not over specific, not overly abstract.
  • Short: Maximum of 2 words. Prefer 1 word when possible.
  • Pronounceable: We want to be able to talk about them.
  • Sizes: Use a property called size and follow our sizes guideline for naming.
  • Disabled state: Use a boolean property nameddisabled.
  • Style variants: Use a property called variant for style variants such as success, error and such.
  • Reserved names: You should be careful that the property names do not conflict with existing standardized prototype members. Reserved names include:
    • align
    • title
    • lang
    • translate
    • dir
    • dataset
    • hidden
    • tabIndex
    • accessKey
    • draggable
    • spellcheck
    • autocapitalize
    • contentEditable
    • isContentEditable
    • inputMode
    • offsetParent
    • offsetTop
    • offsetLeft
    • offsetWidth
    • offsetHeight
    • style
    • innerText
    • outerText
    • oncopy
    • oncut
    • onpaste
    • onabort
    • onblur
    • oncancel
    • oncanplay
    • oncanplaythrough
    • onchange
    • onclick
    • onclose
    • oncontextmenu
    • oncuechange
    • ondblclick
    • ondrag
    • ondragend
    • ondragenter
    • ondragleave
    • ondragover
    • ondragstart
    • ondrop
    • ondurationchange
    • onemptied
    • onended
    • onerror
    • onfocus
    • onfocusin
    • onfocusout
    • oninput
    • oninvalid
    • onkeydown
    • onkeypress
    • onkeyup
    • onload
    • onloadeddata
    • onloadedmetadata
    • onloadstart
    • onmousedown
    • onmouseenter
    • onmouseleave
    • onmousemove
    • onmouseout
    • onmouseover
    • onmouseup
    • onmousewheel
    • onpause
    • onplay
    • onplaying
    • onprogress
    • onratechange
    • onreset
    • onresize
    • onscroll
    • onseeked
    • onseeking
    • onselect
    • onstalled
    • onsubmit
    • onsuspend
    • ontimeupdate
    • ontoggle
    • onvolumechange
    • onwaiting
    • onwheel
    • onauxclick
    • ongotpointercapture
    • onlostpointercapture
    • onpointerdown
    • onpointermove
    • onpointerup
    • onpointercancel
    • onpointerover
    • onpointerout
    • onpointerenter
    • onpointerleave
    • onselectstart
    • onselectionchange
    • nonce
    • click
    • focus
    • blur
    • namespaceURI
    • prefix
    • localName
    • tagName
    • id
    • className
    • classList
    • slot
    • attributes
    • shadowRoot
    • assignedSlot
    • innerHTML
    • outerHTML
    • scrollTop
    • scrollLeft
    • scrollWidth
    • scrollHeight
    • clientTop
    • clientLeft
    • clientWidth
    • clientHeight
    • attributeStyleMap
    • onbeforecopy
    • onbeforecut
    • onbeforepaste
    • onsearch
    • previousElementSibling
    • nextElementSibling
    • children
    • firstElementChild
    • lastElementChild
    • childElementCount
    • onfullscreenchange
    • onfullscreenerror
    • onwebkitfullscreenchange
    • onwebkitfullscreenerror
    • setPointerCapture
    • releasePointerCapture
    • hasPointerCapture
    • hasAttributes
    • getAttributeNames
    • getAttribute
    • getAttributeNS
    • setAttribute
    • setAttributeNS
    • removeAttribute
    • removeAttributeNS
    • hasAttribute
    • hasAttributeNS
    • toggleAttribute
    • getAttributeNode
    • getAttributeNodeNS
    • setAttributeNode
    • setAttributeNodeNS
    • removeAttributeNode
    • closest
    • matches
    • webkitMatchesSelector
    • attachShadow
    • getElementsByTagName
    • getElementsByTagNameNS
    • getElementsByClassName
    • insertAdjacentElement
    • insertAdjacentText
    • insertAdjacentHTML
    • requestPointerLock
    • getClientRects
    • getBoundingClientRect
    • scrollIntoView
    • scroll
    • scrollTo
    • scrollBy
    • scrollIntoViewIfNeeded
    • animate
    • computedStyleMap
    • before
    • after
    • replaceWith
    • remove
    • prepend
    • append
    • querySelector
    • querySelectorAll
    • requestFullscreen
    • webkitRequestFullScreen
    • webkitRequestFullscreen
    • part
    • createShadowRoot
    • getDestinationInsertionPoints
    • nodeType
    • nodeName
    • baseURI
    • isConnected
    • ownerDocument
    • parentNode
    • parentElement
    • childNodes
    • firstChild
    • lastChild
    • previousSibling
    • nextSibling
    • nodeValue
    • textContent
    • hasChildNodes
    • getRootNode
    • normalize
    • cloneNode
    • isEqualNode
    • isSameNode
    • compareDocumentPosition
    • contains
    • lookupPrefix
    • lookupNamespaceURI
    • isDefaultNamespace
    • insertBefore
    • appendChild
    • replaceChild
    • removeChild