Design tokens > Token naming
Design token naming
Purpose
Align on a design token naming direction that makes the most sense in the context of GitLab while learning from industry standards and working within technical constraints.
Scope
The initial focus is on design tokens that relate to color, however, the naming convention must be validated with all design token applications.
Audience
- Authors - Design token creators. An author chooses from constants and semantic tokens to construct both semantic and contextual tokens while following the naming convention to determine what the design token will be.
- Users - A user will apply semantic tokens in design and code and make decisions based on how the design token satisfies the use case.
Goals
- Leverage and express patterns that optimize for readability and clarity over brevity and shorthand
- Consider how naming is translated and presented for different users — designers and engineers
- Provide choice for authors
- Provide decisions for users
- Bound ubiquity and semantics in the context of a design system for GitLab
- Understand where learning will need to occur — anticipate questions/ambiguity
Key learnings
- Multiple naming conventions and patterns exist across design systems as a whole, however they don't differ that much. While a new system might benefit from an established convention as-is, it's much more important to capture localized nuance. The ingredients are all very similar, but the recipes are unique.
- There will be future learnings or constraints that have an impact, we're trying to optimize for the least amount of disruption, but are aware that it will likely happen and need to have a tolerance for it.
- Design tokens live at the convergence of multiple technologies, multiple types of roles (design and development), and multiple mental models, there will be tradeoffs.
- We have to be aware that not everything is called the same thing everywhere. For example, Figma and SCSS use "variables," but CSS uses "custom properties." Other examples are a component in Figma vs. a component in Storybook, or "type" as a shorthand for typography and also meaning a type of a thing.
- There's much more learning to come!
Naming convention
After working through a number of naming exercises and directions (expand section below for reference), we've aligned on the following convention where:
- A string of different attribute collections comprises each token name.
- In most cases only a few of the attributes will be used.
- Some collections, like group and component are less flexible in what they can contain, while others, like variant/category, property, or type, are more flexible to accommodate a wider variety of historical and forward looking concepts.
- Order optimizes for readability and clarity.
- A term may exist in more than one attribute collection, but will never be present at the same time. For example, an info variant of an alert, and a background color with an info type. In the future we may explore more separation, but the current scope and need is to not introduce that level of change and to leverage existing paradigms as much as possible. Think of a variant or category being paired with a component, while a type is paired with an element or property.
- While case will depend on the needed output (for example, Figma uses a
/
delineator), these are presented in kebab-case to normalize terms (for examplecolor-picker
instead ofcolorPicker
) and create a more flat, sentence-like structure.
{group}-{component}-{variant-category}-{element}-{position}-{relationship}-{property}-{type}-{scale}-{state}
Definitions
Attribute collection | Definition | Example items |
---|---|---|
group |
A high-level prefix. Typical when larger sets exist that don't require the use of component or variant / category . |
asset , constant , data , form
|
component |
Objects that have specific functionality and/or purpose and are documented as Pajamas components. |
accordion , button , radio-button , tooltip
|
variant / category |
In Pajamas, the concepts of variant and category are mixed, which is why they're included together. For example, buttons can have a variant and a category at the same time. Links have categories, but not variants. And alerts have variants, but no categories. A variant or category should be paired with a component. |
info , danger , default-primary , default
|
element |
An element is a distinct thing that can have relationships and properties on its own, but can also be part of a component. |
background , border , icon , text
|
position |
The placement of an element. |
top , bottom , right , left , inner , outer
|
relationship |
The association of an element to other elements or constraints. |
to-edge , to-text , gap
|
property |
The specific attribute being changed. |
color , font-family , height , style , transition
|
type |
A way to describe or classify and element or property. A type should be paired with an element, property, or both. |
neutral , blue , data-orange , sans , heading , info
|
scale |
A way to express available choices while indicating relationship to sibling choices by way of intervals, ordinals, or ratios. Ratios are currently used, but can be harder to decipher because they refer back to a potentially unknown or hidden multiplier. |
100 , 200 , 300 , xs , sm , md , 1 , 2 , 4 , 8 , 12
|
state |
Describe the current mechanics of a component. |
checked , unchecked , rest , hover , disabled , expanded , on , error
|
Examples
Open questions and tasks
- Need more clarity around our scales and where and when we should be generic vs. specific.
- Continuing working on naming consistency that aligns with intent, but doesn’t infer pairs (e.g., subtle border doesn’t have to be used with subtle background as a pair, but the intent for each is still consistent and means the same thing regardless of the element). This is for semantic and contextual design tokens.
- Document color patterns. e.g., icon color is one step lighter (light UI) in the color ramp from its text counterpart to aid with optical balance (opposite is true in dark mode). Border color should never be stronger than the main enabled content color within. And more!
- Investigating what uses of color we have in either GitLab UI or the product that aren’t documented in Pajamas or that current color token scope wouldn’t cover. e.g., dynamic values, magic numbers, random values, etc.
- Token matching. Does naming infer pairing (wanting to avoid this) and how to document token matching patterns. e.g., A designer might ask, should
background-color-accent
have to be paired withborder-color-accent
? The answer is no, but why? Doestext-color-disabled
have to rest onbackground-color-disabled
? Again, the answer is no, but it can, so how do I reliably know when to choose what. Are there things that should always pair? e.g.,text-color-body
andicon-color-emphasis
. - Clarifying what is a choice (more for authors, like choosing what color constant to use) vs. what is a decision (what is the intent or purpose I’m using this token for).
Outcome
- Document our decision for naming tokens in our architecture design doc (internal)
Resources
- Inside Design Tokens (Gossman, 2023) has been a massive help and also links to dozens of other resources that have helped shape the above. Additionally, Naming Tokens in Design Systems (Nathan Curtis, 2020), Creating a flexible design token taxonomy for Intuit’s Design System (Nate Baldwin, 2023), and When “semantic tokens” are no longer semantic. (Nate Baldwin 2024) have been supremely beneficial.
- https://gos.si/blog/the-primary-secondary-naming-controversy-in-design-systems
- https://gos.si/blog/the-hidden-skill-and-art-of-naming-things
Initial concepts and exploration…
Naming structure concepts
The following are two different naming structures that are being explored.
1. Least to most specific…
Reference: https://t.co/K3lgZvTNg7
[type][element][attribute][purpose][prominence][size][speed][state][index]
Exercise:
- What is the name of the color design token for gray 700?
- What is the name of the color design token for a secondary confirm buttons border while hovering?
- What is the name the color design token used in the dropdown shadow?
- What is the name of the color design token for the background of the bottom half of the nav?
- What is the name of the color design token for primary text?
This is the line of thinking…
Describe the thing from its least to most specific aspects
Token category (not part of naming) | type | element | attribute | purpose | prominence | size | speed | state | index | Name |
---|---|---|---|---|---|---|---|---|---|---|
Constant | color | neutral | 700 | color.neutral.700 |
||||||
Contextual | color | button | border | confirm | secondary | hover | color.button.border.confirm.secondary.hover |
|||
Constant | color | alphaDark | 16 | color.alphaDark.16 |
||||||
Semantic | color | surface | background | subtle | color.surface.background.subtle |
|||||
Semantic | color | text | primary | color.text.primary |
2. Separating concepts…
Reference: https://medium.com/eightshapes-llc/naming-tokens-in-design-systems-9e86c7444676
[object][base][modifier]
Where…
-
Object:
[group][component][element]
-
Base:
[property][category][concept]
(Note that property is first here to align with Tailwind. The Eight Shapes example places it last.) -
Modifier:
[variant][state][scale][mode]
Exercise:
- What is the name of the color design token for gray 700?
- What is the name of the color design token for a secondary confirm buttons border while hovering?
- What is the name the color design token used in the dropdown shadow?
- What is the name of the color design token for the background of the bottom half of the nav?
- What is the name of the color design token for primary text?
This is the line of thinking…
What is the thing → What part does it apply to → What aspect are we addressing → What's unique about it → What else describes it
Token category (not part of naming) | object | base | modifier | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
group | component | element | property | category | concept | variant | state | scale | mode | Name | |
constant | color | neutral | 700 | color.neutral.700 |
|||||||
contextual | button | border | color | confirm | secondary | hover | button.border.color.confirm.secondary.hover |
||||
constant | color | alphaDark | 16 | color.alphaDark.16 |
|||||||
semantic | background | color | surface | subtle | background.color.surface.subtle |
||||||
semantic | text | color | primary | text.color.primary |
Exploration from the POC…
In the design token POC there is an approach to standardising token names
{namespace}-{context}-{property}-{value}-{scale}-{variant}
-
namespace
global namespace constraint e.g.gl
-
context
(optional) conceptual area e.g.text
ortheme
-
property
(optional) style property e.g.border-radius
orfont-weight
-
value
(optional) token name e.g.blue
orbold
-
scale
(optional) token scale e.g.500
orsmall
-
variant
(optional) token variant e.g.alpha-008
orlighter
The order/hierarchy of terms assists with automation and should be consistent wherever possible. Potentiality leveraging linting/validation rules to help.
style-dictionary has a Category / Type / Item structure. The POC uses further nesting to emulate namespacing and allow for variants etc.
Token naming may assist with autocomplete searching through long lists of tokens, e.g is color.brand.charcoal
or brand.color.charcoal
better for finding tokens, what is the parent categorisation of token groups?
Namespace
gitlab-org/gitlab-ui!3607 (merged) adds 'name/prefix'
transform to automatically add gl-
prefix to CSS/SCSS/JS variables compiled output. It's opt-out so indiviudal tokens can use the "prefix": false
property to exclude them form adding a namespace, for example colors.tokens.json
where $blue-500
etc. do not contain gl-
prefixes.
Scales
Do we maintain existing scale values e.g. spacing-scale.11-5
for ease of migration or define new scales which replicate a consistent scale e.g. millennial (100
...900
)?
Pros:
- Existing scales mirror 1:1 to current SCSS variable usage
- Updating scales could align to TailwindCSS scales
Cons:
- Updating scale requires mapping to compatability alias variables and/or updating usage in codebases
Distinction between base/design tokens
What is the distinction between color.blue.500
vs color.link
etc. do we want consumers to use base tokens or do we want to define tokens for all general usage instances e.g. button.confirm.background.hover
etc.