@import 'settings';

/*
  @classreference
  side-navigation:
    Root element:
        .p-side-navigation:
            Side navigation in default variant.
        .p-side-navigation--icons:
            Side navigation with item icons.
        .p-side-navigation--accordion:
            Side navigation with expanding accordion items.
        .p-side-navigation--raw-html:
            Raw HTML version of side navigation (used with links generated by an external service).
        "&.is-drawer-expanded":
            Set `.is-drawer-expanded` when side navigation drawer is open on small screens.
        "&.is-drawer-collapsed":
            Set `.is-drawer-collapsed` when side navigation drawer is closed on small screens.
        "&.is-drawer-hidden":
            Set `.is-drawer-hidden` when side navigation drawer is closed on small screens.
        "&.is-sticky":
            Sticky version of side navigation.
        "&.is-dark":
            Side navigation in dark theme (if default is light).
        "&.is-light":
            Side navigation in light theme (if default is dark).

    Overlay:
        .p-side-navigation__overlay:
            Screen overlay to display when side navigation drawer is open on small screens.

    Drawer:
        .p-side-navigation__drawer:
            Side navigation drawer (to allow expanding and collapsing the navigation on small screens).

    Drawer header:
        .p-side-navigation__drawer-header:
            Header of the side navigation drawer.

    Toggle button:
        .p-side-navigation__toggle:
            Side navigation toggle button (to open side navigation on small screens).
        .p-side-navigation__toggle--in-drawer:
            Side navigation toggle button in drawer (to close navigation on small screens).

    Items list heading:
        .p-side-navigation__heading:
            Heading for side navigation items group (text only).
        .p-side-navigation__heading--linked:
            Heading for side navigation items group that contains a link (`.p-side-navigation__link`).

    Items list:
        .p-side-navigation__list:
            Group of side navigation items (usually a `<ul>` element).

    Item element:
        .p-side-navigation__item:
            Single item in side navigation (usually a `<li>` element). May contain nested items lists.
        .p-side-navigation__item--title:
            Single title item in side navigation (usually a `<li>` element).
        "&.has-active-child":
            Set `.has-active-child` on a item that contains an active nested item. This is used in collapsible side navigation in application layout.

    Item link:
        .p-side-navigation__link:
            Single link in the side navigation.

    Item text:
        .p-side-navigation__text:
            Single text item in side navigation (for items that are not linked).

    Item accordion button:
        .p-side-navigation__accordion-button:
            Single accordion button item in side navigation with `.p-side-navigation--accordion` variant.

    Item icon:
        .p-side-navigation__icon:
            An icon in side navigation item (used with `.p-side-navigation--icons` variant).

    Item status:
        .p-side-navigation__status:
            A container for status icon or label inside the navigation item.
*/

@mixin vf-p-side-navigation {
  // STYLING OF SIDE NAVIGATION RESPONSIVE DRAWER

  @keyframes vf-p-side-navigation-expand {
    0% {
      transform: translate(-100%);
    }

    100% {
      transform: translate(0);
    }
  }

  @keyframes vf-p-side-navigation-collapse {
    0% {
      transform: translate(0);
    }

    100% {
      transform: translate(-100%);
    }
  }

  .p-side-navigation__drawer {
    background: $colors--theme--background-default;
    bottom: 0;
    color: $colors--theme--text-default;
    left: 0;
    overflow: auto;
    position: fixed;
    top: 0;
    transform: translateX(-100%);
    width: 100%;
    z-index: 102;

    // is-expanded and is-collapsed are deprecated and replaced by is-drawer-expanded and is-drawer-collapsed
    .p-side-navigation.is-expanded &,
    .p-side-navigation.is-drawer-expanded &,
    [class*='p-side-navigation--'].is-expanded &,
    [class*='p-side-navigation--'].is-drawer-expanded & {
      @extend %vf-has-box-shadow;

      @media (max-width: $threshold-6-12-col - 1px) {
        animation: vf-p-side-navigation-expand map-get($animation-duration, brisk);
        transform: translateX(0);
      }
    }

    .p-side-navigation.is-collapsed &,
    .p-side-navigation.is-drawer-collapsed &,
    [class*='p-side-navigation--'].is-collapsed &,
    [class*='p-side-navigation--'].is-drawer-collapsed & {
      @media (max-width: $threshold-6-12-col - 1px) {
        animation: vf-p-side-navigation-collapse map-get($animation-duration, brisk);
      }
    }

    .p-side-navigation.is-drawer-hidden &,
    [class*='p-side-navigation--'].is-drawer-hidden & {
      display: none;
      @media (min-width: $threshold-6-12-col) {
        display: block;
      }
    }

    @media (min-width: $breakpoint-x-small) {
      max-width: 20rem;
    }
  }

  .p-side-navigation__overlay {
    @include vf-transition(opacity);

    background: $colors--theme--background-overlay;
    bottom: 0;
    left: 0;
    opacity: 0;
    pointer-events: none;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 101;

    .p-side-navigation.is-expanded &,
    .p-side-navigation.is-drawer-expanded &,
    [class*='p-side-navigation--'].is-expanded &,
    [class*='p-side-navigation--'].is-drawer-expanded & {
      opacity: 1;
      pointer-events: all;
    }
  }

  .p-side-navigation__drawer-header {
    background: $colors--theme--background-default;
    border-bottom-style: solid;
    border-bottom-width: 1px;
    border-color: $colors--theme--border-low-contrast;
    margin-bottom: $spv--small;
    padding-bottom: calc($spv--small - 1px); // compensate for border thickness
    padding-left: 0.25rem; // nudge to visually align icon with text
    padding-top: $spv--small;
    position: sticky;
    top: 0;
    z-index: 1;
  }

  .p-side-navigation__toggle,
  .p-side-navigation__toggle--in-drawer {
    @extend %vf-button-base;
    &::before {
      @extend %icon;

      content: '';
      margin-left: -$sph--small;
      margin-right: $sph--small;
    }
  }

  .p-side-navigation__toggle {
    @include vf-button-pattern;

    &::before {
      @include vf-icon-chevron-themed;
      transform: rotate(-90deg);
    }
  }

  .p-side-navigation__toggle--in-drawer {
    @include vf-button-pattern(
      $button-background-color: $color-transparent,
      $button-border-color: $colors--theme--border-high-contrast,
      $button-text-color: $colors--theme--text-inactive,
      $button-hover-background-color: $colors--theme--background-hover,
      $button-hover-border-color: $colors--theme--border-high-contrast,
      $button-active-background-color: $colors--theme--background-active,
      $button-active-border-color: $color-transparent
    );
    margin-bottom: $sp-unit * 2 - $spv-nudge * 2;

    &::before {
      @include vf-icon-chevron-themed;
      transform: rotate(90deg);
    }

    &[aria-expanded='true'] {
      background-color: $color-transparent;

      &:hover {
        background: $colors--theme--background-hover;
        color: $colors--theme--text-default;
      }
    }
  }

  @media (min-width: $threshold-6-12-col) {
    // make whole navigation sticky on large screens
    .p-side-navigation.is-sticky,
    [class*='p-side-navigation--'].is-sticky {
      max-height: 100dvh;
      overflow-y: auto;
      position: sticky;
      top: 0;
    }

    .p-side-navigation__toggle,
    .p-side-navigation__toggle--in-drawer,
    .p-side-navigation__drawer-header {
      display: none;
    }

    .p-side-navigation__drawer,
    // fight specificity of expanded version
    .p-side-navigation.is-expanded .p-side-navigation__drawer,
    .p-side-navigation.is-drawer-expanded .p-side-navigation__drawer,
    [class*='p-side-navigation--'].is-expanded .p-side-navigation__drawer,
    [class*='p-side-navigation--'].is-drawer-expanded .p-side-navigation__drawer {
      box-shadow: none;
      display: block;
      max-width: none;
      overflow: visible;
      position: static;
      transform: translateX(0);
    }

    .p-side-navigation__overlay {
      display: none;
    }
  }

  // STYLING OF SIDE NAVIGATION LINKS LIST

  // space for the right hand icon with default inner spacing on the left
  $sp-sidenav--icon-width: map-get($icon-sizes, default);

  %side-navigation__list {
    @extend %vf-list;
    @extend %vf-pseudo-border--bottom;
    color: $colors--theme--text-inactive;

    &::after {
      @include vf-side-navigation-spacing-left($prop: left);

      background: $colors--theme--border-low-contrast;
      bottom: -0.5 * $spv--x-large; // place border in the middle of the margin
    }

    .p-side-navigation--icons &::after {
      @include vf-side-navigation-spacing-left($prop: left, $multiplier: 2, $offset: $sp-sidenav--icon-width);
    }

    .p-side-navigation--accordion &::after {
      @include vf-side-navigation-spacing-left($prop: left, $multiplier: 2);
    }

    &:last-of-type::after {
      content: none;
    }
  }

  .p-side-navigation__list {
    @extend %side-navigation__list;

    // accordion styles
    &[aria-expanded] {
      @include vf-transition(#{transform, opacity}, fast);
      &.has-tick-elements {
        padding-left: 1em;
      }
    }
    &[aria-expanded='false'] {
      height: 0;
      opacity: 0;
      overflow: hidden;
      transform: translate3d(0, -0.5rem, 0);
      visibility: hidden;
    }
    &[aria-expanded='true'] {
      height: auto;
      opacity: 1;
      transform: translate3d(0, 0, 0);
      visibility: visible;
    }
  }

  %side-navigation__text {
    @include vf-side-navigation-spacing-left;

    display: flex;
    padding-bottom: $spv--x-small;
    padding-right: $sph--large;
    padding-top: $spv--x-small;

    .p-side-navigation__item--title > & {
      color: $colors--theme--text-default;
      font-weight: $font-weight-bold;
    }
  }

  %side-navigation__heading {
    @extend %side-navigation__text;

    // reset heading styles
    @extend %common-default-text-properties;
    @extend %bold;

    display: block;
    font-size: map-get($base-font-sizes, base);
    margin: 0;
    max-width: none;
  }

  %side-navigation__link {
    @include vf-focus-themed;

    &,
    &:visited {
      color: $colors--theme--text-inactive;
    }

    &:hover {
      background: $colors--theme--background-hover;
      color: $colors--theme--text-default;
      text-decoration: none;
    }

    &:active,
    &.is-active,
    &[aria-current='page'],
    &[aria-current='true'] {
      background: $colors--theme--background-active;
      color: $colors--theme--text-default;
      cursor: default;
    }

    &.is-active,
    &[aria-current='page'],
    &[aria-current='true'] {
      @include vf-highlight-bar($colors--theme--text-default, left);
    }

    // vf-highlight-bar is rendered above focus outline
    // so we need to hide it on focus
    &:focus::before {
      display: none;
    }

    // Display the highlight when focussing in modern browsers that support
    // focus-visible.
    &:focus:not(:focus-visible)::before {
      display: block;
    }
  }

  .p-side-navigation__link {
    @extend %side-navigation__link;

    &:visited {
      color: $colors--theme--text-inactive;
    }
  }

  .p-side-navigation__accordion-button {
    // reset default button styles
    background-color: inherit;
    border: 0;
    border-radius: 0;
    color: inherit;
    font-size: inherit;
    justify-content: flex-start;
    margin-bottom: 0;
    text-align: left;
    width: 100%;

    &::before {
      @extend %icon;
      @include vf-icon-chevron-themed;
      @include vf-transition($property: transform, $duration: fast);

      align-self: center;
      content: '';
      flex-shrink: 0;
      margin-left: calc(-1 * ($sph--large + $sp-sidenav--icon-width));
      margin-right: $sph--large;
    }

    &:hover {
      background: $colors--theme--background-hover;
      color: $colors--theme--text-default;
    }

    // aria-selected controls the open and closed state for the accordion tab
    &[aria-expanded='true'] {
      // override base expanded button styles
      background-color: inherit;

      &:hover {
        background: $colors--theme--background-hover;
        color: $colors--theme--text-default;
      }
      @include vf-transition(#{background-color, border-color});
    }

    &[aria-expanded='false'] {
      &::before {
        transform: rotate(-90deg);
      }

      @include vf-transition(#{background-color, border-color});
    }
  }

  .p-side-navigation__heading,
  .p-side-navigation__text,
  .p-side-navigation__link,
  .p-side-navigation__accordion-button {
    // offset for accordion chevrons is icon size + twice spacing around it
    // we don't use grid width spacing for accordion (as we do in icon version)
    $sp-sidenav--accordion-offset: $sp-sidenav--icon-width + 2 * $sph--large;
    @extend %side-navigation__text;

    .p-side-navigation--icons & {
      @include vf-side-navigation-spacing-left($multiplier: 2, $offset: $sp-sidenav--icon-width);
      position: relative;
    }

    .p-side-navigation--accordion & {
      @include vf-side-navigation-spacing-left($multiplier: 0, $offset: $sp-sidenav--accordion-offset);
    }

    // nested 2nd level of navigation
    .p-side-navigation__item--title .p-side-navigation__item &,
    .p-side-navigation__item .p-side-navigation__item & {
      @include vf-side-navigation-spacing-left($multiplier: 2);

      // add spacing for variant with right side icons
      .p-side-navigation--icons & {
        @include vf-side-navigation-spacing-left($multiplier: 3, $offset: $sp-sidenav--icon-width);
      }

      // add spacing for variant with accordions
      .p-side-navigation--accordion & {
        @include vf-side-navigation-spacing-left($multiplier: 1, $offset: $sp-sidenav--accordion-offset);
      }
    }

    // nested 3rd level of navigation
    .p-side-navigation__item--title .p-side-navigation__item .p-side-navigation__item &,
    .p-side-navigation__item .p-side-navigation__item .p-side-navigation__item & {
      @include vf-side-navigation-spacing-left($multiplier: 3);

      // add spacing for variant with right side icons
      .p-side-navigation--icons & {
        @include vf-side-navigation-spacing-left($multiplier: 4, $offset: $sp-sidenav--icon-width);
      }

      // add spacing for variant with accordions
      .p-side-navigation--accordion & {
        @include vf-side-navigation-spacing-left($multiplier: 2, $offset: $sp-sidenav--accordion-offset);
      }
    }

    // nested 4th level of navigation
    .p-side-navigation__item--title .p-side-navigation__item .p-side-navigation__item .p-side-navigation__item &,
    .p-side-navigation__item .p-side-navigation__item .p-side-navigation__item .p-side-navigation__item & {
      @include vf-side-navigation-spacing-left($multiplier: 4);

      // add spacing for variant with right side icons
      .p-side-navigation--icons & {
        @include vf-side-navigation-spacing-left($multiplier: 5, $offset: $sp-sidenav--icon-width);
      }

      // add spacing for variant with accordions
      .p-side-navigation--accordion & {
        @include vf-side-navigation-spacing-left($multiplier: 3, $offset: $sp-sidenav--accordion-offset);
      }
    }
  }

  .p-side-navigation--icons {
    .p-side-navigation__icon {
      @include vf-side-navigation-spacing-left($prop: left);

      position: absolute;
      top: $spv--small;
    }
  }

  .p-side-navigation__status {
    margin-left: auto;
    padding-left: $spv--small;
  }

  .p-side-navigation__heading,
  .p-side-navigation__heading--linked {
    @extend %side-navigation__heading;
  }

  .p-side-navigation__heading--linked {
    padding: 0; // padding will come from the link in heading
  }

  .p-side-navigation__heading,
  .p-side-navigation__heading--linked .p-side-navigation__link,
  .p-side-navigation__item--title,
  .p-side-navigation__item--title .p-side-navigation__link {
    color: $colors--theme--text-default;
  }

  // Styles for markup in raw HTML docs variant
  .p-side-navigation--raw-html {
    // stylelint-disable selector-max-type -- we support raw HTML markup for discourse-generated side nav
    h2,
    h3,
    h4,
    h5,
    h6 {
      @extend %side-navigation__heading;
      color: $colors--theme--text-default;
    }

    ul {
      @extend %side-navigation__list;

      &::after {
        background: $colors--theme--border-low-contrast;
      }
    }

    li > a {
      @extend %side-navigation__link;

      &,
      &:visited {
        color: $colors--theme--text-inactive;
      }

      &:hover {
        background: $colors--theme--background-hover;
        color: $colors--theme--text-default;
      }

      &:active,
      &.is-active,
      &[aria-current='page'],
      &[aria-current='true'] {
        @include vf-highlight-bar($colors--theme--text-default, left);

        background: $colors--theme--background-active;
        color: $colors--theme--text-default;
      }
    }

    li > span,
    li > strong,
    li > a {
      @extend %side-navigation__text;

      display: block;
    }

    li li > span,
    li li > strong,
    li li > a {
      @include vf-side-navigation-spacing-left($multiplier: 2);
    }

    li li li > span,
    li li li > strong,
    li li li > a {
      @include vf-side-navigation-spacing-left($multiplier: 3);
    }
    // stylelint-enable selector-max-type
  }

  @if mixin-exists(vf-application-layout--when-collapsed) {
    .p-side-navigation__item.has-active-child {
      // parent element that has active child should be selected when navigation is collapsed
      @include vf-application-layout--when-collapsed() {
        // @include vf-highlight-bar($color-sidenav-item-border-highlight, left);
        @include vf-highlight-bar($colors--theme--text-default, left);

        background: $colors--theme--background-hover;
        color: $colors--theme--text-default;
      }

      // parent element with active child should not be selected when navigation is expanded
      @include vf-application-layout--when-expanded() {
        @include vf-highlight-bar(transparent, left);

        background: transparent;
        color: $colors--theme--text-inactive;
      }
    }
  }
}

// helper

// elements in side nav should be aligned from left based on grid margin for given screen size
// additional offset is added when icons are used or for nested navigation levels
@mixin vf-side-navigation-spacing-left(
  // property to adjust spacing, defaults to `padding-left`
  $prop: padding-left,
  // how many times grid margin width should be multiplied (for nested navigation levels)
  $multiplier: 1,
  // offset to use for additional spacing (for icons)
  $offset: 0
) {
  #{$prop}: $multiplier * map-get($grid-margin-widths, small) + $offset;

  @media (min-width: $threshold-4-6-col) {
    #{$prop}: $multiplier * map-get($grid-margin-widths, default) + $offset;
  }
}
