/// Functions ///-------------------------- /// Add alpha channel to a color /// @access public /// @param {Color} $color - color to work with /// @param {Number} $percentage - percentage of `$color` opacity /// @return {Color} $color @function mix-alpha($color, $percentage) { @return rgba($color, $percentage); } /// Add spacing length according to given unit /// @access public /// @param {Number} $num /// @return {Size} $em @function space-x($num) { @return $num * $space-unit; } /// Calculate z-index value /// @access public /// @use {List} $z-indexes /// @param {String} $key1 - key to retrieve for z-index matching /// @param {String} $key2 - optiona, second key for deeper matching /// @return {Number} z-index value @function z-index($key1, $key2: null) { $map: $z-indexes; $found-index: null; @if (map-has-key($map, $key1)) { $found-index: index(map-keys($map), $key1); @if ($key2) { $map: map-get($map, $key1); $found-index: index($map, $key2); } } @return $found-index; } /// Mixins ///-------------------------- /// UX/UI rules regarding element that can be clicked and /// others than <a/> tags @mixin clickable() { cursor: pointer; &:focus { outline: 0; } } @mixin unclickable() { cursor: default; &:focus { outline: 0; } } @mixin unselectable() { user-select: none; } @mixin disabled() { cursor: not-allowed; &:focus { outline: 0; } } @mixin gradient($primary, $secondary, $direction) { background: linear-gradient($direction, $primary, $secondary); } /// Place contextualised element (&) at the root, /// prefixed with left handed class /// @access public @mixin left-handed() { @at-root .left-handed & { @content; } } /// Place contextualised element (&) at the root, /// prefixed with right handed class /// @access public @mixin right-handed() { @at-root .right-handed & { @content; } } /// Centering an element (you'll have to change the position /// of the element though) @mixin centered() { top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); } /// Mixin from "bootstrap v4" /// @link https://getbootstrap.com/docs/4.3/utilities/clearfix/ @mixin clearfix() { &::after { display: block; content: ""; clear: both; } } /// Reverse an element @mixin reversed() { transform: scaleX(-1); } /// Add led effect with the input color /// @param {Color} $color @mixin led($color) { color: $color; text-shadow: 0 0 4px brighten($color, 90); } @mixin light-bulb($color) { color: $color; // text-shadow: 0 0 4px; } /// Extend element to fit all four positions /// @param {value} value [default: 0] @mixin fit-positions($value: 0) { top: $value; right: $value; bottom: $value; left: $value; } /// Add a basic ripple effect based on CSS pseudo class /// /// * Not as qualitative as a dedicated ripple HTML element /// * One design flaw on "mouseover" where the transition will be the one /// one the ripple layer (instead of the first classic CTA layer) /// * Offers a YAGNI solution when only CSS is available) /// /// @param {Color} $background-color /// @param {Color} $wave-color default is a lighten version of bg color @mixin ripple-effect( $background-color, $wave-color: lighten($background-color, 15%) ) { position: relative; /// First layer: classic CTA hover effect &::before { @include fit-positions; content: ""; position: absolute; z-index: 1; background-color: $background-color; transition: background 0.15s ease-in-out; } &:hover::before { background-color: $wave-color; } /// Second layer: more slower ripple effect &::after { @include fit-positions; content: ""; position: absolute; z-index: 2; background-position: center; background-color: transparent; transition: background 0.6s ease-out; } &:hover::after { background: $wave-color radial-gradient( circle, transparent 1%, $wave-color 1% ) center/15000%; } &:active::after { background-color: $background-color; background-size: 100%; transition: background 0s; } /// Other layers: container contents & > * { z-index: 3; } } /// Add a virtual space on pure empty tag /// This will allow to set a width or height rules @mixin virtual-content() { content: "\200B"; } @mixin virtual-space() { &::after { @include virtual-content(); } } /// Hidden vertical scrollbar @mixin hidden-scrollbar() { scrollbar-width: none; overflow-y: scroll; &::-webkit-scrollbar { display: none; } }