Typography

Installation

  yarn add @chewy/kib-foundations

Import

  @use '~@chewy/kib-foundations/src/typography';

Functions

get

@function get($path) { ... }@function get($path) { 
  @return -get-type-style-property($path...);
 }
Description

Get a single type style property definition.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$path

The map path to the desired property definition.

List none
Returns
List or String or Number

Return the value of the type style property.

Requires

get-weight

@function get-weight($name) { ... }@function get-weight($name) { 
  // Check if it's a category-specific token (contains '-weight-')
  @if string.index($name, '-weight-') {
    // Transform old pattern to new: 'product-text-weight-strong' → 'fw-product-text-strong'
    // The new tokens use 'fw-{category}-{strength}' instead of '{category}-weight-{strength}'
    $weight-index: string.index($name, '-weight-');
    $category: string.slice($name, 1, $weight-index - 1); // e.g., 'product-text'
    $strength: string.slice($name, $weight-index + 8); // e.g., 'strong' (skip '-weight-')
    @return get('fw-#{$category}-#{$strength}');
  }
  // Otherwise, use generic pattern: 'bold' → 'weight-bold'
  // This will resolve through aliases in _settings.scss
  @return get('weight-#{$name}');
 }
Description

Get a type weight style property

Supports both generic weight tokens (e.g., 'bold', 'semibold') and category-specific weight tokens (e.g., 'product-text-weight-strong', 'editorial-heading-weight-strong').

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$name

The name of the weight token. Can be:

  • Generic: 'bold', 'semibold', 'medium', 'normal', 'heavy' (maps to 'weight-{name}')
  • Category-specific: 'product-text-weight-strong', 'editorial-heading-weight-strong', etc.
String none
Returns
String

Return the custom property and fallback of the weight style.

Example
// Generic weight tokens
font-weight: typography.get-weight('bold');
font-weight: typography.get-weight('semibold');

// Category-specific weight tokens
font-weight: typography.get-weight('product-text-weight-strong');
font-weight: typography.get-weight('editorial-heading-weight-strong');
Requires
Used by

weight-variant-token-exists

@function weight-variant-token-exists($type-style, $variant) { ... }@function weight-variant-token-exists($type-style, $variant) { 
  // Find the matching category
  // Special handling for utility-display: check if style ends with '-display'
  $category: null;

  // Check for utility-display first (more specific)
  @if string.index($type-style, 'utility') and string.index($type-style, 'display') {
    $display-pos: string.index($type-style, 'display');
    $style-length: string.length($type-style);
    // Check if 'display' is at the end of the string
    @if $display-pos + 6 == $style-length {
      $category: 'utility-display';
    }
  }

  // If not utility-display, check other categories
  @if not $category {
    @each $c in settings.$type-style-categories {
      @if not $category and string.index($type-style, $c) {
        $category: $c;
      }
    }
  }

  @if not $category {
    @return false;
  }

  $weight-token-legacy: '#{$category}-weight-#{$variant}';
  $weight-token-fw: 'fw-#{$category}-#{$variant}';

  $theme-map: common.get-theme-map(settings.$themes, settings.$preferred-theme);
  @if map.has-key($theme-map, $weight-token-legacy) or map.has-key($theme-map, $weight-token-fw) {
    @return true;
  }
  $theme-map: common.get-theme-map(settings.$themes, common.$default-theme);
  @if map.has-key($theme-map, $weight-token-legacy) or map.has-key($theme-map, $weight-token-fw) {
    @return true;
  }
  @return false;
 }
Description

Check if a weight variant token exists (either {category}-weight-{variant} or fw-{category}-{variant}). Used to prefer weight-only override over full variant style for theme size reduction.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$type-style

The type style name (e.g. product-heading-1)

String none
$variant

Variant name (e.g. strong, stronger)

String none
Returns
Boolean

True if the weight token exists

Requires
Used by

type-style-exists

@function type-style-exists($name, $alternate: false) { ... }@function type-style-exists($name, $alternate: false) { 
  $theme-map: common.get-theme-map(settings.$themes, settings.$preferred-theme);
  $path: ($name);
  @if $alternate {
    $path: ('deprecated', $name);
  }
  @if map.has-key($theme-map, $path...) {
    @return true;
  }
  $theme-map: common.get-theme-map(settings.$themes, common.$default-theme);
  @if map.has-key($theme-map, $path...) {
    @return true;
  }
  @return false;
 }
Description

Check if a type style exists in the theme (without throwing).

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$name

The name of the type style

String none
$alternate

Whether to check deprecated/alternate styles

Booleanfalse
Returns
Boolean

True if the type style exists

Requires
Used by

get-type-style-with-fallback

@function get-type-style-with-fallback($path) { ... }@function get-type-style-with-fallback($path) { 
  $theme-map: common.get-theme-map(settings.$themes, settings.$preferred-theme);
  $type-style: map.get($theme-map, $path...);

  // Fallback to default theme if type style doesn't exist on the preferred theme to avoid an error
  @if not $type-style {
    @warn "Attempting to fallback to '#{common.$default-theme}' theme";

    $theme-map: common.get-theme-map(settings.$themes, common.$default-theme);
    $type-style: map.get($theme-map, $path...);
  }

  @return $type-style;
 }
Description

Retrieve a defined type style group definition from the preferred theme map first, then if not found retry with the fallback default theme.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$path

Path of type style definition in theme map

List none
Returns
Map

Theme map containing a style definition.

Requires
Used by

get-type-style

@function get-type-style($name) { ... }@function get-type-style($name) { 
  $resolved-name: $name;
  @if map.has-key(settings.$aliases, $name) {
    $alias-style: map.get(settings.$aliases, $name);
    @if meta.type-of($alias-style) == 'list' and list.length($alias-style) > 0 {
      $resolved-name: list.nth($alias-style, 1);
    } @else {
      $resolved-name: $alias-style;
    }
  }

  @if not $alternate {
    $name: $resolved-name;
  }

  $type-style: null;
  $is-hero: string.index($name, 'hero');
  $has-alternate: string.index($name, 'alternate');

  @if $alternate or $is-hero {
    @if $alternate and $is-hero and not $has-alternate {
      $name: '#{$name}-alternate';
    }

    $type-style: get-type-style-with-fallback('deprecated', $name);
  } @else {
    $type-style: get-type-style-with-fallback($name);
  }

  @if not $type-style and $alternate {
    @warn "Alternate type style '#{$name}' not found. Falling back to non-alternate style.";
    $type-style: get-type-style-with-fallback($resolved-name);
  }

  @if not $type-style {
    $alt-msg: '';
    @if $alternate {
      $alt-msg: 'alternate variant of the ';
    }
    @error "The #{$alt-msg}type style "#{$name}" does not exist.";
  }

  @return $type-style;
 }
Description

Get a defined type style group definition.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$name

The name of the defined type style.

String none
Returns
Map

Return a map containing a style definition.

Throws
  • The #{$alt-msg}type style

Requires
Used by

-get-typography-property-alternate-segment

@function -get-typography-property-alternate-segment($alternate) { ... }@function -get-typography-property-alternate-segment($alternate) { 
  @if $alternate {
    @return 'deprecated';
  }

  @return null;
 }
Description

Returns the deprecated typography path segment when alternate styles are requested.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$alternate

Whether this is a deprecated/alternate style

Boolean none
Returns
String or Null
Used by

-get-base-font-weight-var

@function -get-base-font-weight-var($type-style, $base-style, $alternate: false) { ... }@function -get-base-font-weight-var($type-style, $base-style, $alternate: false) { 
  @return var(
    #{common.get-property-name(
        'typography',
        -get-typography-property-alternate-segment($alternate),
        $type-style,
        'font-weight'
      )},
    #{map.get($base-style, 'font-weight')}
  );
 }
Description

Returns the base font-weight CSS custom property for a type style

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$type-style

The type style name

String none
$base-style

The base style map containing font-weight

Map none
$alternate

Whether this is a deprecated/alternate style

Booleanfalse
Returns
String

CSS custom property with fallback for the base font-weight

get-type-style-variant-weight

@function get-type-style-variant-weight($type-style, $variant, $base-style, $alternate) { ... }@function get-type-style-variant-weight($type-style, $variant, $base-style, $alternate) { 
  // Find the matching category
  // Special handling for utility-display: check if style ends with '-display'
  $category: null;

  // Check for utility-display first (more specific)
  @if string.index($type-style, 'utility') and string.index($type-style, 'display') {
    $display-pos: string.index($type-style, 'display');
    $style-length: string.length($type-style);
    // Check if 'display' is at the end of the string
    @if $display-pos + 6 == $style-length {
      $category: 'utility-display';
    }
  }

  // If not utility-display, check other categories
  @if not $category {
    @each $c in settings.$type-style-categories {
      @if not $category and string.index($type-style, $c) {
        $category: $c;
      }
    }
  }

  // If no category matched, fallback to base font-weight
  @if not $category {
    @if $base-style {
      @return -get-base-font-weight-var($type-style, $base-style, $alternate);
    }
    @return null;
  }

  // Support both token formats for theme size optimization (unwantedTokens filters full variants):
  // - kib-tokens (legacy): {category}-weight-{variant} e.g. product-heading-weight-stronger
  // - chirp-design-tokens: fw-{category}-{variant} e.g. fw-product-heading-stronger
  // IMPORTANT: Always generate legacy property names for backward compatibility
  $weight-token-legacy: '#{$category}-weight-#{$variant}';
  $weight-token-fw: 'fw-#{$category}-#{$variant}';

  // Try legacy token first
  $value: map.get(
    common.get-theme-map(settings.$themes, settings.$preferred-theme),
    $weight-token-legacy
  );
  @if not $value {
    $value: map.get(
      common.get-theme-map(settings.$themes, common.$default-theme),
      $weight-token-legacy
    );
  }

  // Fallback to fw- token if legacy not found
  @if not $value {
    $value: map.get(
      common.get-theme-map(settings.$themes, settings.$preferred-theme),
      $weight-token-fw
    );
    @if not $value {
      $value: map.get(
        common.get-theme-map(settings.$themes, common.$default-theme),
        $weight-token-fw
      );
    }
  }

  // Always use legacy property name format for backward compatibility
  $property-name: common.get-property-name('typography', $category, 'weight', $variant);

  // If variant value doesn't exist, fallback to base font-weight
  @if not $value {
    @if $base-style {
      @return -get-base-font-weight-var($type-style, $base-style, $alternate);
    }
    @return null;
  }

  // Fallback (second argument to var()) must come from base theme only.
  $base-fallback: map.get(
    common.get-theme-map(settings.$themes, common.$default-theme),
    $weight-token-fw
  );
  @if not $base-fallback {
    $base-fallback: map.get(
      common.get-theme-map(settings.$themes, common.$default-theme),
      $weight-token-legacy
    );
  }
  @if not $base-fallback and $base-style {
    $base-fallback: map.get($base-style, 'font-weight');
  }
  @if not $base-fallback {
    $base-fallback: $value;
  }
  @return var(#{$property-name}, #{$base-fallback});
 }
Description

Returns a font weight variant custom property and fallback for the new typography tokens set. This is used to override the default font-weight with the variant value instead.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$type-style

Type style name

String none
$variant

Variant name (strong, stronger)

String none
$base-style

The base type style map (used as fallback if variant doesn't exist)

Map none
$alternate

Whether this is a deprecated/alternate style

Boolean none
Returns
String or Null

Variant font weight value with CSS custom property, base font-weight if variant not supported, or null if no fallback available

Requires
Used by

get-properties

@function get-properties($theme: settings.$preferred-theme, $deprecated: false) { ... }@function get-properties($theme: settings.$preferred-theme, $deprecated: false) { 
  $theme-map: common.get-theme-map(settings.$themes, $theme);

  @if not $deprecated {
    $theme-map: map.deep-remove($theme-map, 'deprecated');
  }

  $properties: common.flatten-map($theme-map);

  @return $properties;
 }
Description

Returns a theme's typography tokens as a flattened map

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$theme

Name of the theme

Stringsettings.$preferred-theme
$deprecated

Include deprecated typography styles. Not recommended.

Boolfalse
Returns
Map

Final flattened map

Requires

-get-type-style-value

@function -get-type-style-value($theme: settings.$default-theme, $alias) { ... }@function -get-type-style-value($theme: settings.$default-theme, $alias) { 
  $theme-map: common.get-theme-map(settings.$themes, $theme);
  $has-key: map.has-key($theme-map, $path...);

  @if not $has-key {
    @error "Type style value (#{$path}) not found.";
  }

  @return map.get($theme-map, $path...);
 }
Description

Retrieves a typography style property value

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$theme

Name of the theme

Stringsettings.$default-theme
$alias

Alias of spacing unit

String none
Returns
Number

Spacing value from the theme

Throws
  • Type style value (#{$path}) not found.

Requires
Used by

-get-type-style-property

@function -get-type-style-property($path) { ... }@function -get-type-style-property($path) { 
  $theme-map: common.get-theme-map(settings.$themes, settings.$preferred-theme);

  // Resolve aliases for the first path segment (type style name)
  $resolved-path: $path;
  @if list.length($path) > 0 {
    $first-segment: list.nth($path, 1);
    @if map.has-key(settings.$aliases, $first-segment) {
      $aliased-name: map.get(settings.$aliases, $first-segment);
      @if meta.type-of($aliased-name) == 'list' and list.length($aliased-name) > 0 {
        // For aliases like ('utility-1', 'strong'), use the style key.
        $aliased-name: list.nth($aliased-name, 1);
      }
      // Rebuild path with aliased first segment
      $resolved-path: ($aliased-name);
      // Only append remaining path segments if there are any
      @if list.length($path) > 1 {
        @for $i from 2 through list.length($path) {
          $resolved-path: list.append($resolved-path, list.nth($path, $i));
        }
      }
    }
  }

  @if not map.has-key($theme-map, $resolved-path...) {
    @error "The type style property (#{$path}) does not exist.";
  }

  $property: common.get-property-name('typography', $resolved-path...);
  // Fallback value in var() must come from base theme only (consistent when custom property is undefined).
  $fallback: -get-type-style-value(common.$default-theme, $resolved-path...);

  // Line-height fallbacks that use calc() (e.g. calc(2rem/var(--fs))) break PostCSS when
  // nested inside another calc(). Use a unitless fallback to avoid parse errors.
  $last-segment: list.nth($resolved-path, list.length($resolved-path));
  $is-line-height: $last-segment == 'line-height' or $last-segment == 'lineHeight';
  @if $is-line-height and string.index(meta.inspect($fallback), 'calc(') {
    $fallback: 1.2;
  }

  @return string.unquote('var(#{$property}, #{$fallback})');
 }
Description

Get a single type style property definition.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$path

The map path to the desired property definition.

List none
Returns
List or String or Number

Return the value of the type styoe property.

Throws
  • The type style property (#{$path}) does not exist.

Requires
Used by

Mixins

custom-properties

Deprecated!

Use prebuilt CSS theme files from @chewy/chirp-design-tokens instead.

Generates CSS Custom Properties for typography tokens. Prefer importing theme files directly:

```css

@mixin custom-properties($theme, $deprecated: false, $overrides: null) { ... }@mixin custom-properties($theme, $deprecated: false, $overrides: null) { 
  @warn "typography.custom-properties() is deprecated. Import CSS theme files from @chewy/chirp-design-tokens/web/css (for example, theme-base-light.css and theme-base-dark.css).";
  @warn "typography.custom-properties() no longer emits theme tokens by default. Load @chewy/chirp-design-tokens/web/css/theme-*.css files instead.";

  @if $overrides {
    @each $key, $value in $overrides {
      #{common.get-property-name('typography', $key)}: $value;
    }
  }
 }
Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$theme

Unused, retained for backwards compatibility.

String none
$deprecated

Unused, retained for backwards compatibility.

Boolfalse
$overrides

Map that overrides matching custom property values.

Mapnull
Requires

style-as

@mixin style-as($name, $variant, $alternate: false) { ... }@mixin style-as($name, $variant, $alternate: false) { 
  // Note: $alternate parameter is deprecated and no longer has any effect.
  // It's kept for backward compatibility to avoid breaking changes.

  // Check if this is a strikethrough style (e.g., 'price-x-small-strikethrough')
  // The style exists with the full name, but we need to add text-decoration manually
  $is-strikethrough: false;
  @if string.index($type-style, '-strikethrough') {
    $strikethrough-pos: string.index($type-style, '-strikethrough');
    $style-length: string.length($type-style);
    // Check if '-strikethrough' is at the end of the string
    @if $strikethrough-pos + 13 == $style-length {
      // 13 = length of '-strikethrough'
      $is-strikethrough: true;
      // Keep the full style name - don't strip the suffix
    }
  }

  // Parse variant from style name if not provided as separate argument
  // Supports: style-as('utility-3-strong') equivalent to style-as('utility-3', 'strong')
  @if $variant == null {
    $known-variants: ('light', 'strong', 'stronger', 'italic', 'strong-italic', 'stronger-italic');
    @each $v in $known-variants {
      @if string.index($type-style, '-#{$v}') {
        $variant-pos: string.index($type-style, '-#{$v}');
        $style-length: string.length($type-style);
        $variant-length: string.length($v);
        // Check if variant is at the end of the string
        @if $variant-pos + $variant-length == $style-length {
          $variant: $v;
          $type-style: string.slice($type-style, 1, $variant-pos - 1);
        }
      }
    }
  }

  // Resolve aliases
  @if map.has-key(settings.$aliases, $type-style) {
    $alias-style: map.get(settings.$aliases, $type-style);

    @if meta.type-of($alias-style) == 'list' and list.length($alias-style) == 2 {
      $type-style: list.nth($alias-style, 1);
      @if $variant == null {
        $variant: list.nth($alias-style, 2);
      }
    } @else {
      $type-style: $alias-style;
    }
  }

  // Parse variant: extract weight part and italic flag (e.g. "strong-italic" → weight: "strong", italic: true)
  $weight-variant: $variant;
  $has-italic: false;
  @if $variant and meta.type-of($variant) == 'string' and string.index($variant, 'italic') {
    $has-italic: true;
    @if $variant != 'italic' {
      // "strong-italic" → "strong"
      $italic-pos: string.index($variant, '-italic');
      $weight-variant: null;
      @if $italic-pos {
        $weight-variant: string.slice($variant, 1, $italic-pos - 1);
      }
    } @else {
      $weight-variant: null;
    }
  }

  // Normalize: style-as('token', 'strong') and style-as('token-strong') are equivalent.
  // Prefer weight-only override when the weight token exists (reduces theme size - no full variant styles needed).
  // Fall back to combined full style only when weight token doesn't exist. (Italic variants are filtered—no fallback.)
  @if $weight-variant {
    @if not functions.weight-variant-token-exists($type-style, $weight-variant) {
      $combined: '#{$type-style}-#{$variant}';
      @if functions.type-style-exists($combined, $alternate) {
        $type-style: $combined;
        $variant: null;
        $weight-variant: null;
        $has-italic: false;
      }
    }
  }

  $style: functions.get-type-style($type-style, $alternate);

  // Fallback values in var() must come from base theme only.
  $base-theme-map: common.get-theme-map(settings.$themes, common.$default-theme);
  $base-style: map.get($base-theme-map, $type-style);
  @if $alternate {
    $base-style: map.get($base-theme-map, 'deprecated', $type-style);
  }

  $alternate-property-segment: null;
  @if $alternate {
    $alternate-property-segment: 'deprecated';
  }

  @each $name, $value in $style {
    $property-name: common.get-property-name(
      'typography',
      $alternate-property-segment,
      $type-style,
      $name
    );

    $fallback-value: $value;
    @if $base-style {
      $fallback-value: map.get($base-style, $name);
    }
    $css-variable: var(#{$property-name}, #{$fallback-value});

    @if $name == 'font-weight' {
      @if $weight-variant {
        $variant-weight: functions.get-type-style-variant-weight(
          $type-style,
          $weight-variant,
          $style,
          $alternate
        );
        $font-weight: $css-variable;
        @if $variant-weight {
          $font-weight: $variant-weight;
        }
        font-weight: $font-weight;
      } @else {
        font-weight: $css-variable;
      }
    } @else if $name == 'text-case' {
      text-transform: $css-variable;
    } @else {
      #{$name}: $css-variable;
    }
  }

  @if $has-italic {
    font-style: italic;
  }

  @if $is-strikethrough {
    text-decoration: line-through;
  }
 }
Description

Generate styles using custom properties from a defined type style.

Parameters
Parameters
parameter Nameparameter Descriptionparameter Typeparameter Default value
$name

The name of the type style

String none
$variant

The variant name of the type style

String none
$alternate

DEPRECATED: This parameter is no longer used but kept for backward compatibility

Booleanfalse
Example

Apply styles for a type style definition

@use '~@chewy/kib-foundations/src/typography';

.my-custom-class {
  @include typography.style-as('display-1');
}

Apply styles with font weight variants (two equivalent formats)

@use '~@chewy/kib-foundations/src/typography';

// Format 1: Separate arguments
.heading-strong { @include typography.style-as('editorial-heading-2', 'strong'); }

// Format 2: Combined name (variant parsed automatically)
.heading-strong { @include typography.style-as('editorial-heading-2-strong'); }

Apply italic or strong-italic variants (uses base style + font-style: italic)

@use '~@chewy/kib-foundations/src/typography';

.italic-text { @include typography.style-as('utility-3', 'italic'); }
.strong-italic-text { @include typography.style-as('utility-2', 'strong-italic'); }
Requires