18F/web-design-standards

View on GitHub
packages/usa-breadcrumb/src/styles/_usa-breadcrumb.scss

Summary

Maintainability
Test Coverage
@use "sass:math";
@use "sass:map";
@use "sass:list";

@use "uswds-core" as *;

//
// General Settings
// =====================================

// This helps balance spacing around inline-block elements
$breadcrumb-context: "Breadcrumb";
$gap-inline-spacer: -0.25em;
$icon-vertical-spacer: -0.2em;

$breadcrumb-gap: 1.5;
$breadcrumb-icon-height: 2.5ex;
$breadcrumb-icon-display-height: 2ex;
$breadcrumb-icon-spacing: 0px;

$icon-breadcrumb-separator: (
  "name": "navigate_next",
  "svg-height": 40,
  "svg-width": 40,
  "height": $breadcrumb-icon-display-height,
  "color": $theme-breadcrumb-separator-color,
);

$icon-breadcrumb-back: (
  "name": "arrow_back",
  "svg-height": 40,
  "svg-width": 40,
  "height": $breadcrumb-icon-display-height,
  "color": $theme-breadcrumb-separator-color,
);

// Set default value for custom mixin exdent-icon()
$breadcrumb-back-icon-aspect: (
  map.get($icon-breadcrumb-back, "svg-width"),
  map.get($icon-breadcrumb-back, "svg-height")
);

// Defines spacing so back icon is optically placed
@mixin exdent-icon($dim: $breadcrumb-back-icon-aspect) {
  $aspect: math.div(list.nth($dim, 1), list.nth($dim, 2));
  $icon-width: $breadcrumb-icon-display-height * $aspect;
  padding-left: calc(#{$icon-width} + #{$breadcrumb-icon-spacing});
  text-indent: calc((#{$icon-width} + #{$breadcrumb-icon-spacing}) * -1);
}

.usa-breadcrumb {
  @include typeset(
    $theme-breadcrumb-font-family,
    $theme-breadcrumb-font-size,
    3
  );
  @include set-text-and-bg(
    $theme-breadcrumb-background-color,
    $context: $breadcrumb-context
  );
  @include u-padding-x($theme-breadcrumb-padding-x);

  @include at-media($theme-breadcrumb-min-width) {
    @include u-padding-bottom($theme-breadcrumb-padding-bottom);
    @include u-padding-top($theme-breadcrumb-padding-top);
  }

  &:not(.usa-breadcrumb--wrap) {
    .usa-breadcrumb__list {
      @include at-media($theme-breadcrumb-min-width) {
        @include u-white-space("no-wrap");
        text-overflow: ellipsis;
        overflow: hidden;
      }
    }
  }
}

.usa-breadcrumb__list {
  @include unstyled-list;
  @include u-display("block");
  @include u-padding($theme-focus-width);
  margin-left: units($theme-focus-width) * -1;
  margin-right: units($theme-focus-width) * -1;
}

.usa-breadcrumb__list-item {
  @include sr-only;
  @include u-display("inline");

  @include at-media-max($theme-breadcrumb-min-width) {
    @include u-white-space("wrap");

    // If parent link only (mobile), only show parent of current link
    &:nth-last-child(2) {
      @include not-sr-only;

      .usa-breadcrumb__link {
        @include button-unstyled;
        @include exdent-icon;
        @include place-icon(
          $icon-breadcrumb-back,
          "before",
          0,
          baseline,
          $theme-breadcrumb-background-color
        );

        // Override link colors from button-unstyled()

        @include set-link-from-bg(
          $theme-breadcrumb-background-color,
          $theme-breadcrumb-link-color,
          $context: $breadcrumb-context
        );

        @include u-display("inline-block");
        @include u-padding-bottom($theme-breadcrumb-padding-bottom);
        @include u-padding-top($theme-breadcrumb-padding-top);

        &:before {
          bottom: $icon-vertical-spacer;
          // Magic number to center icon
          height: $breadcrumb-icon-display-height;
          position: relative;
        }

        // Prevent underline that extends beyond text
        &,
        &:hover,
        &:active {
          @include u-text("no-underline");
        }
        span {
          @include u-text("underline");
        }
      }

      // Override icon spacing from place-icon() with non-token value
      .usa-breadcrumb__link::before {
        margin-right: $breadcrumb-icon-spacing;
      }
    }
  }

  @include at-media($theme-breadcrumb-min-width) {
    @include not-sr-only;

    // Breadcrumb separator ›
    &:not(:last-child) {
      @include place-icon(
        $icon-breadcrumb-separator,
        "after",
        0,
        baseline,
        $theme-breadcrumb-background-color
      );
    }

    // Style overrides for separator using non-token values
    &:not(:last-child)::after {
      // Magic number to center icon
      bottom: $icon-vertical-spacer;
      margin-left: $breadcrumb-icon-spacing;
      margin-right: $breadcrumb-icon-spacing;
      height: $breadcrumb-icon-display-height;
      position: relative;
    }
  }
}

.usa-breadcrumb__link {
  @include set-link-from-bg(
    $theme-breadcrumb-background-color,
    $theme-breadcrumb-link-color,
    $context: $breadcrumb-context
  );
  @include u-display("inline");

  // Prevent underline that extends beyond text
  @include u-text("no-underline");

  span {
    @include u-text("underline");
  }
}

// ---------------------------------
// Variations
// ---------------------------------

// Breadcrumb wrap
.usa-breadcrumb--wrap {
  @include at-media($theme-breadcrumb-min-width) {
    @include u-line-height($theme-breadcrumb-font-family, 4);
  }

  .usa-breadcrumb__list-item {
    @include u-display("inline-block");
  }
}