/* Copyright (c) Fortanix, Inc.
|* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
|* the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// stylelint-disable declaration-no-important

@mixin focus-hidden($override-layer: true) {
  --bk-focus-color-anim: transparent; // Start transparent for animation purposes
  
  &, &.pseudo-focus-visible {
    box-shadow: none if($override-layer, !important, null);
    outline: none if($override-layer, !important, null);
  }
}

// Configure an element with a focus outline outset from the element.
@mixin focus-outset($selector: '&:focus-visible, &.pseudo-focus-visible', $override-layer: true) {
  --bk-focus-color-anim: transparent; // Start transparent for animation purposes
  
  box-shadow: none if($override-layer, !important, null); // Remove focus-inset, if any
  outline: var(--bk-focus-outline-width) solid var(--bk-focus-color-anim) if($override-layer, !important, null);
  
  // Should add `.pseudo-focus-visible` here for visual testing purposes
  #{$selector} {
    --bk-focus-color-anim: var(--bk-focus-outline-color) #{if($override-layer, !important, null)};
    @content;
  }
  
  /*
  // FIXME: this breaks any `transition` set in a lower layer
  @media (prefers-reduced-motion: no-preference) {
    transition: outline 80ms ease-in-out;
  }
  */
}

// Configure an element with a focus outline inset into the element. This can be useful for elements
// that have overflow hidden and thus can't have an exterior outline.
@mixin focus-inset($selector: '&:focus-visible, &.pseudo-focus-visible', $override-layer: true) {
  --bk-focus-color-anim: transparent; // Start transparent for animation purposes
  
  outline: none if($override-layer, !important, null); // Remove focus-outset, if any
  
  $w: var(--bk-focus-outline-width);
  box-shadow: // Note: add one for each corner so that we get proper inner border radii
    inset $w $w var(--bk-focus-color-anim),
    inset $w calc(-1 * $w) var(--bk-focus-color-anim),
    inset calc(-1 * $w) $w var(--bk-focus-color-anim),
    inset calc(-1 * $w) calc(-1 * $w) var(--bk-focus-color-anim) if($override-layer, !important, null);
  
  // Add `.pseudo-focus-visible` for visual testing purposes
  #{$selector} {
    --bk-focus-color-anim: var(--bk-focus-outline-color);
  }
  
  /*
  // FIXME: this breaks any `transition` set in a lower layer
  @media (prefers-reduced-motion: no-preference) {
    transition: outline 80ms ease-in-out;
  }
  */
}

// Hide an element visually, but keep it in the accessibility tree (sometimes also called "sr-only").
// https://www.w3.org/WAI/tutorials/forms/labels/#note-on-hiding-elements
@mixin visually-hidden {
  border: 0;
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  block-size: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  inline-size: 1px;
  white-space: nowrap;
}

@mixin styles {
  /*
  :root {
    // See `theming.scss`
    //--bk-focus-outline-width
    //--bk-focus-outline-color
  }
  */
  
  $elements-with-inset: div, section, dialog;
  [tabindex]:is(#{$elements-with-inset}) {
    @include focus-inset($override-layer: false);
  }
  :not([tabindex]:is(#{$elements-with-inset})) {
    @include focus-outset($override-layer: false);
  }
  
  // https://www.smashingmagazine.com/2021/10/respecting-users-motion-preferences
  @media screen and (prefers-reduced-motion: reduce), (update: slow) {
    * {
      animation-duration: 0.001ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.001ms !important;
    }
  }
  
  .visually-hidden {
    @include visually-hidden;
  }
}
