@use "sass:math";
@use "../../core/settings" as *;
@use "../../core/tools" as *;

////
/// Button component
///
/// 1. Ensure that any global link styles are overridden.
/// 2. Fix unwanted button padding in Firefox.
/// 3. Use a pseudo element to expand the click target area to include the
///    button's shadow as well, in case users try to click it.
/// 4. Use a pseudo element to expand and cover the button's bounds, used to
///    add a button shadow or border without affecting the total height
/// 5. Adjust margin and padding to accommodate button shadow
///
/// @group components/button
////

$nhsuk-button-padding-top-bottom-mobile: nhsuk-px-to-rem(10px);
$nhsuk-button-padding-top-bottom-desktop: nhsuk-px-to-rem(14px);
$nhsuk-button-padding-top-bottom-small: nhsuk-px-to-rem(6px);
$nhsuk-button-padding-left-right: nhsuk-px-to-rem(16px);
$nhsuk-button-padding-left-right-small: nhsuk-px-to-rem(12px);

$nhsuk-button-search-icon-size: 28px;
$nhsuk-button-search-icon-size-large: 38px;

// @deprecated To be removed in v11.0
$button-border-radius: $nhsuk-button-border-radius;
$button-padding-top-bottom-mobile: $nhsuk-button-padding-top-bottom-mobile;
$button-padding-top-bottom-desktop: $nhsuk-button-padding-top-bottom-desktop;
$button-padding-left-right: $nhsuk-button-padding-left-right;
$button-shadow-size: $nhsuk-button-shadow-size;

@include nhsuk-exports("nhsuk/components/button") {
  .nhsuk-button {
    box-sizing: border-box;

    display: inline-block;

    position: relative;

    width: 100%;
    min-height: nhsuk-px-to-rem(40px + $nhsuk-button-shadow-size);
    margin-top: 0;
    padding: $nhsuk-button-padding-top-bottom-mobile $nhsuk-button-padding-left-right; // [5]

    overflow: visible;

    border: $nhsuk-border-width-form-element solid transparent;
    border-radius: nhsuk-px-to-rem($nhsuk-button-border-radius);

    text-align: center;
    vertical-align: top;

    cursor: pointer;

    appearance: none;

    @include nhsuk-button-style(
      $button-colour: $nhsuk-button-colour,
      $button-hover-colour: $nhsuk-button-hover-colour,
      $button-active-colour: $nhsuk-button-active-colour,
      $button-text-colour: $nhsuk-button-text-colour,
      $button-shadow-colour: $nhsuk-button-shadow-colour
    );

    @include nhsuk-font(19, $line-height: 19px, $weight: bold);
    @include nhsuk-responsive-margin(5, "bottom", $adjustment: $nhsuk-button-shadow-size); // [5]

    @include nhsuk-media-query($from: tablet) {
      width: auto;
      min-height: nhsuk-px-to-rem(52px + $nhsuk-button-shadow-size);
      padding: $nhsuk-button-padding-top-bottom-desktop $nhsuk-button-padding-left-right; // [5]
      line-height: nhsuk-line-height(24px, $font-size: 19px);
    }

    // [1]
    &,
    &:hover,
    &:active {
      text-decoration: none;
    }

    // [2]
    &::-moz-focus-inner {
      padding: 0;
      border: 0;
    }

    // Reset focus styles added to buttons as links
    &:focus {
      outline: none;
      box-shadow: none;
    }

    // Add button focus styles ensuring the active "pressed" state has priority
    &:focus:not(:active),
    &:focus:not(:active):hover {
      @include nhsuk-focused-button;
    }

    // Remove button shadow when pressed
    &:active,
    &:active:focus {
      top: $nhsuk-button-shadow-size;
      box-shadow: none;
    }

    &:disabled {
      pointer-events: none;
      opacity: (0.5);
    }

    // Default pseudo element styles for [3] and [4]
    &::before,
    &::after {
      content: "";

      display: block;

      position: absolute;
      top: -$nhsuk-border-width-form-element;
      right: -$nhsuk-border-width-form-element;
      bottom: -$nhsuk-border-width-form-element;
      left: -$nhsuk-border-width-form-element;

      border-radius: nhsuk-px-to-rem($nhsuk-button-border-radius);
    }

    // Use a pseudo element to expand the click target area to include the
    // button's shadow as well, in case users try to click it [3]
    &::before {
      bottom: -($nhsuk-border-width-form-element + $nhsuk-button-shadow-size);
      border: $nhsuk-border-width-form-element solid transparent;
      background-color: transparent;
    }

    // When the button is active it is shifted down by $nhsuk-button-shadow-size to
    // denote a 'pressed' state. If the user happened to click at the very top
    // of the button, their mouse is no longer over the button (because it has
    // 'moved beneath them') and so the click event is not fired.
    //
    // This corrects that by shifting the top of the pseudo element so that it
    // continues to cover the area that the user originally clicked, which means
    // the click event is still fired.
    &:active::before {
      top: -($nhsuk-border-width-form-element + $nhsuk-button-shadow-size);
      bottom: -$nhsuk-border-width-form-element;
    }

    // Override high-contrast link colours to match buttons
    @media screen and (forced-colors: active), (-ms-high-contrast: active) {
      color: ButtonText;

      &,
      &::before {
        border-color: ButtonBorder;
      }

      &:not(:focus):not(:active):hover,
      &:not(:focus):not(:active):hover::before,
      &:not(:focus):not(:active):hover::after {
        border-color: Highlight;
        color: Highlight;
      }
    }
  }

  // Button variations

  .nhsuk-button--secondary,
  .nhsuk-button--secondary-solid {
    @include nhsuk-button-style(
      $button-colour: $nhsuk-secondary-button-colour,
      $button-border-colour: $nhsuk-secondary-button-border-colour,
      $button-hover-colour: $nhsuk-secondary-button-hover-colour,
      $button-active-colour: $nhsuk-secondary-button-active-colour,
      $button-text-colour: $nhsuk-secondary-button-text-colour,
      $button-shadow-colour: $nhsuk-secondary-button-shadow-colour
    );
  }

  .nhsuk-button--secondary-solid {
    background-color: $nhsuk-secondary-button-solid-background-colour;
  }

  .nhsuk-button--reverse {
    @include nhsuk-button-style(
      $button-colour: $nhsuk-reverse-button-colour,
      $button-hover-colour: $nhsuk-reverse-button-hover-colour,
      $button-active-colour: $nhsuk-reverse-button-active-colour,
      $button-text-colour: $nhsuk-reverse-button-text-colour,
      $button-shadow-colour: $nhsuk-reverse-button-shadow-colour
    );
  }

  .nhsuk-button--warning {
    @include nhsuk-button-style(
      $button-colour: $nhsuk-warning-button-colour,
      $button-hover-colour: $nhsuk-warning-button-hover-colour,
      $button-active-colour: $nhsuk-warning-button-active-colour,
      $button-text-colour: $nhsuk-button-text-colour,
      $button-shadow-colour: $nhsuk-warning-button-shadow-colour
    );
  }

  .nhsuk-button--brand,
  .nhsuk-button--login {
    @include nhsuk-button-style(
      $button-colour: $nhsuk-login-button-colour,
      $button-hover-colour: $nhsuk-login-button-hover-colour,
      $button-active-colour: $nhsuk-login-button-active-colour,
      $button-text-colour: $nhsuk-button-text-colour,
      $button-shadow-colour: $nhsuk-login-button-shadow-colour
    );
  }

  // =========================================================
  // Small buttons
  // =========================================================

  .nhsuk-button--small {
    min-height: nhsuk-px-to-rem(32px + $nhsuk-button-shadow-size);
    padding: $nhsuk-button-padding-top-bottom-small $nhsuk-button-padding-left-right-small; // [5]

    @include nhsuk-responsive-margin(4, "bottom", $adjustment: $nhsuk-button-shadow-size); // [5]

    @include nhsuk-media-query($from: tablet) {
      @include nhsuk-font(16, $line-height: 19px, $weight: bold);
    }
  }

  // =========================================================
  // Icon buttons
  // =========================================================

  .nhsuk-button--icon {
    display: flex;
    position: relative;
    align-items: center;

    // Add minimum width for icon-only buttons
    min-width: nhsuk-px-to-rem(44px);

    // Prevent users from selecting icon button text
    // e.g. When double clicking the button
    user-select: none;

    @include nhsuk-media-query($until: tablet) {
      // Align icon and text in centre of button
      justify-content: center;

      // Reduce padding to better fit icon
      padding-top: 0;
      padding-bottom: 0;
    }
  }

  .nhsuk-button:not(.nhsuk-button--small) {
    @include nhsuk-media-query($from: tablet) {
      min-width: nhsuk-px-to-rem(66px);
    }
  }

  .nhsuk-button .nhsuk-icon {
    flex-shrink: 0;

    // Offset icon to the left when at the end, towards text
    &:not(:only-child):last-child {
      margin-right: nhsuk-px-to-rem(-6px);
      margin-left: nhsuk-px-to-rem(-$nhsuk-icon-size + 6px);
    }

    // Offset icon to the right when at the start, towards text
    &:not(:only-child):first-child {
      margin-right: nhsuk-px-to-rem(-$nhsuk-icon-size + 6px);
      margin-left: nhsuk-px-to-rem(-6px);
    }

    &:only-child {
      margin-right: nhsuk-px-to-rem(-6px);
      margin-left: nhsuk-px-to-rem(-6px);
    }

    @include nhsuk-media-query($from: tablet) {
      position: absolute;
      top: 50%;
      left: $nhsuk-button-padding-left-right;

      // Offset icon vertically (from top: 50%) into the centre
      margin-top: nhsuk-px-to-rem(math.div($nhsuk-icon-size, -2));

      // Offset icon to the left when at the end, towards text
      &:not(:only-child):last-child {
        right: $nhsuk-button-padding-left-right;
        left: auto;
        margin-right: nhsuk-px-to-rem(-6px);
        margin-left: 0;
      }

      // Offset icon to the right when at the start, towards text
      &:not(:only-child):first-child {
        left: $nhsuk-button-padding-left-right;
        margin-right: 0;
        margin-left: nhsuk-px-to-rem(-6px);
      }

      &:only-child {
        left: 50%;
        margin-right: 0;
        margin-left: nhsuk-px-to-rem(math.div($nhsuk-icon-size, -2));
      }
    }
  }

  // Increase icon size (tablet), excluding small buttons
  .nhsuk-button:not(.nhsuk-button--small) .nhsuk-icon {
    @include nhsuk-media-query($from: tablet) {
      width: nhsuk-px-to-rem($nhsuk-icon-size-large);
      height: nhsuk-px-to-rem($nhsuk-icon-size-large);

      // Offset icon vertically (from top: 50%) into the centre
      margin-top: nhsuk-px-to-rem(math.div($nhsuk-icon-size-large, -2));

      // Offset icon to the left when at the end, towards text
      &:not(:only-child):last-child {
        margin-left: nhsuk-px-to-rem(-$nhsuk-icon-size-large + 6px);
      }

      // Offset icon to the right when at the start, towards text
      &:not(:only-child):first-child {
        margin-right: nhsuk-px-to-rem(-$nhsuk-icon-size-large + 6px);
      }

      &:only-child {
        left: 50%;
        margin-right: 0;
        margin-left: nhsuk-px-to-rem(math.div($nhsuk-icon-size-large, -2));
      }
    }
  }

  // Increase icon size (tablet), search only
  .nhsuk-button:not(.nhsuk-button--small) .nhsuk-icon--search:only-child {
    @include nhsuk-media-query($from: tablet) {
      width: nhsuk-px-to-rem($nhsuk-button-search-icon-size-large);
      height: nhsuk-px-to-rem($nhsuk-button-search-icon-size-large);

      // Offset icon vertically (from top: 50%) into the centre
      margin-top: nhsuk-px-to-rem(math.div($nhsuk-button-search-icon-size-large, -2));
      margin-left: nhsuk-px-to-rem(math.div($nhsuk-button-search-icon-size-large, -2));
    }
  }

  // Prevent button icon size increase for small buttons (at tablet) by
  // overriding the core icon size increase back to default size again
  .nhsuk-button.nhsuk-button--small .nhsuk-icon {
    @include nhsuk-media-query($from: tablet) {
      width: nhsuk-px-to-rem($nhsuk-icon-size);
      height: nhsuk-px-to-rem($nhsuk-icon-size);

      &:not(:only-child):last-child {
        right: $nhsuk-button-padding-left-right-small;
      }

      &:not(:only-child):first-child {
        left: $nhsuk-button-padding-left-right-small;
      }
    }
  }

  // Increase icon size, search only
  .nhsuk-button .nhsuk-icon--search:only-child {
    @include nhsuk-media-query($from: mobile) {
      width: nhsuk-px-to-rem($nhsuk-button-search-icon-size);
      height: nhsuk-px-to-rem($nhsuk-button-search-icon-size);
    }
  }

  .nhsuk-button.nhsuk-button--small .nhsuk-icon--search:only-child {
    @include nhsuk-media-query($from: tablet) {
      // Offset icon vertically (from top: 50%) into the centre
      margin-top: nhsuk-px-to-rem(math.div($nhsuk-button-search-icon-size, -2));
      margin-left: nhsuk-px-to-rem(math.div($nhsuk-button-search-icon-size, -2));
    }
  }

  .nhsuk-button__content {
    display: block;

    // Preserve space for icon (small) at the end
    padding-right: nhsuk-px-to-rem($nhsuk-icon-size);
    padding-left: 0;

    // Preserve space for icon (small) at the start
    .nhsuk-icon + & {
      padding-right: 0;
      padding-left: nhsuk-px-to-rem($nhsuk-icon-size);
    }

    // Move padding to content to better fit icon
    @include nhsuk-media-query($until: tablet) {
      padding-top: $nhsuk-button-padding-top-bottom-mobile;
      padding-bottom: $nhsuk-button-padding-top-bottom-mobile;

      .nhsuk-button.nhsuk-button--small & {
        padding-top: $nhsuk-button-padding-top-bottom-small;
        padding-bottom: $nhsuk-button-padding-top-bottom-small;
      }
    }

    @include nhsuk-media-query($from: tablet) {
      // Preserve space for icon (large) at the end
      .nhsuk-button:not(.nhsuk-button--small) & {
        padding-right: nhsuk-px-to-rem($nhsuk-icon-size-large);
      }

      // Preserve space for icon (large) at the start
      .nhsuk-button:not(.nhsuk-button--small) .nhsuk-icon + & {
        padding-right: 0;
        padding-left: nhsuk-px-to-rem($nhsuk-icon-size-large);
      }
    }
  }
}
