Opening up

When creating a design system, it's important to make sure that the system is flexible and can be easily extended. This allows the design system to be used in a variety of contexts and applications.

One way to do this is to expose the design system's tokens to the end-user. This allows the user to easily customize the design system to fit their needs.

Exposing theme tokens

Based on your design systems' specifications, theme tokens can vary. Let's use a portion of Material Design's color roles as an example.

Based on the specifications, we need to have a primary color, a secondary color, a tertiary color, and an error color. All of which have a background, and a text color. We can create a theme token for each of these colors. We're going to create the theme file inside of the foundations directory of our design system.

// foundations/_tokens.scss
 
:root {
  @include sentro.token-config(
    $primary: #6200ee,
    $on-primary: #ffffff,
    $secondary: #03dac6,
    $on-secondary: #000000,
    $tertiary: #03dac6,
    $on-tertiary: #000000,
    $error: #b00020,
    $on-error: #ffffff
  );
}

We can also implement their container variants using token nesting.

// foundations/_tokens.scss
 
:root {
  @include sentro.token-config(
    $primary: (
      'default': #6200ee,
      'container': #caaafc
    ),
    $on-primary: (
      'default': #ffffff,
      'container': #250062
    ),
    $secondary: (
      'default': #03dac6,
      'container': #d2fff8
    ),
    $on-secondary: (
      'default': #000000,
      'container': #004d44
    ),
    $tertiary: (
      'default': #03dac6,
      'container': #d2fff8
    ),
    $on-tertiary: (
      'default': #000000,
      'container': #004d44
    ),
    $error: (
      'default': #b00020,
      'container': #ffcad1
    ),
    $on-error: (
      'default': #ffffff,
      'container': #8c0009
    )
  );
}

Now we can start opening this up to the end-user by transferring the values to modifiable variables.

// foundations/_tokens.scss
 
$primary: (
  'default': #6200ee,
  'container': #caaafc
) !default;
 
$on-primary: (
  'default': #ffffff,
  'container': #250062
) !default;
 
$secondary: (
  'default': #03dac6,
  'container': #d2fff8
) !default;
 
$on-secondary: (
  'default': #000000,
  'container': #004d44
) !default;
 
// ...
 
:root {
  @include sentro.token-config(
    $primary: $primary,
    $on-primary: $on-primary,
    $secondary: $secondary,
    $on-secondary: $on-secondary,
    $tertiary: $tertiary,
    $on-tertiary: $on-tertiary,
    $error: $error,
    $on-error: $on-error
  );
}

This way, the end-user can easily override the default values upon import.

// main.scss
 
@use 'foundations/tokens' with (
  $primary: (
    'default': #ee6300,
    'container': #ffc298
  ),
  $on-primary: (
    'default': #ffffff,
    'container': #1e0a00
  ),
  $secondary: (
    'default': #6200ee,
    'container': #caaafc
  ),
  $on-secondary: (
    'default': #ffffff,
    'container': #250062
  ),
  // ...
);

Exposing component tokens (keys)

In the same way, we can expose component tokens to the end-user. Let's say we have a component that has a fill, an ink, and a border color. We can create a key for each of these properties.

// components/_sdc-component.scss
.sdc-component {
  background-color: sentro.key-create('component-fill', 'surface-400');
  color: sentro.key-create('component-ink', 'surface-ink');
  border: 1px solid sentro.key-create('component-border', 'surface-400');
}

We can then expose these keys to the end-user by transferring the values to modifiable variables.

// components/_sdc-component.scss
 
$fill: 'surface-400' !default;
$ink: 'surface-ink' !default;
$border: 'surface-400' !default;
 
.sdc-component {
  background-color: sentro.key-create('component-fill', $fill);
  color: sentro.key-create('component-ink', $ink);
  border: 1px solid sentro.key-create('component-border', $border);
}

The end-user can then override the default values upon import.

// main.scss
 
@use 'components/sdc-component' with (
  $fill: 'surface-200',
  $ink: 'accent-600',
  $border: 'surface-200'
);