initial commit

This commit is contained in:
Ray Elliott 2021-02-17 18:25:50 +00:00
commit 3a7bd357fa
20 changed files with 884 additions and 0 deletions

7
LICENCE.md Normal file
View File

@ -0,0 +1,7 @@
Copyright 2021 Ray Elliott
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

14
README.md Normal file
View File

@ -0,0 +1,14 @@
# CSS Base
Simple CSS Base framework.
**Heavily** inspired by [GitHub - CodyHouse/codyhouse-framework](https://github.com/CodyHouse/codyhouse-framework).
**NOTE** media queries based on variables have only been implemented for SASS. No postccss solution has yet been implemented.
## TODO
* documentation
- .text-component
- visibility.css - make notes on classes with `\:` in the selectors
- media queries (sass codyhouse implementation)

10
src/css/accessibility.css Normal file
View File

@ -0,0 +1,10 @@
/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}

80
src/css/buttons.css Normal file
View File

@ -0,0 +1,80 @@
:root {
--btn-font-size: 1em;
--btn-padding-x: var(--space-sm);
--btn-padding-y: var(--space-xxs);
--btn-radius: 0.25em;
}
.btn {
cursor: pointer;
text-decoration: none;
line-height: 1.2;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-shadow: var(--shadow-xs);
transition: all 0.2s ease;
}
.btn:hover {
box-shadow: var(--shadow-sm);
}
.btn:focus {
box-shadow: 0px 0px 0px 2px alpha(var(--color-contrast-higher), 0.15);
outline: none;
}
.btn:active {
transform: translateY(2px);
}
/* themes */
.btn--primary {
background: var(--color-primary);
color: var(--color-white);
}
.btn--primary:hover {
background: var(--color-primary-dark);
}
.btn--primary:focus {
box-shadow: 0px 0px 0px 2px alpha(var(--color-primary), 0.2);
}
.btn--subtle {
background: var(--color-contrast-lower);
color: var(--color-contrast-higher);
}
.btn--accent {
background: var(--color-accent);
color: var(--color-white);
}
.btn--accent:hover {
background: var(--color-accent-dark);
}
.btn--accent:focus {
box-shadow: 0px 0px 0px 2px alpha(var(--color-accent), 0.2);
}
/* feedback */
.btn--disabled, .btn[disabled], .btn[readonly] {
opacity: 0.6;
cursor: not-allowed;
}
/* size */
.btn--sm {
font-size: 0.8em;
}
.btn--md {
font-size: 1.2em;
}
.btn--lg {
font-size: 1.4em;
}

44
src/css/colors.css Normal file
View File

@ -0,0 +1,44 @@
:root, [data-theme="default"] {
/* main */
@include defineHSL(--color-primary-darker, 220, 90%, 42%); /* hsl(220, 90%, 42%) */
@include defineHSL(--color-primary-dark, 220, 90%, 49%); /* hsl(220, 90%, 49%) */
@include defineHSL(--color-primary, 220, 90%, 56%); /* hsl(220, 90%, 56%) */
@include defineHSL(--color-primary-light, 220, 90%, 63%); /* hsl(220, 90%, 63%) */
@include defineHSL(--color-primary-lighter, 220, 90%, 70%); /* hsl(220, 90%, 70%) */
@include defineHSL(--color-accent-darker, 349, 75%, 36%); /* hsl(349, 75%, 36%) */
@include defineHSL(--color-accent-dark, 349, 75%, 44%); /* hsl(349, 75%, 44%) */
@include defineHSL(--color-accent, 349, 75%, 51%); /* hsl(349, 75%, 51%) */
@include defineHSL(--color-accent-light, 349, 75%, 59%); /* hsl(349, 75%, 59%) */
@include defineHSL(--color-accent-lighter, 349, 75%, 67%); /* hsl(349, 75%, 67%) */
@include defineHSL(--color-black, 240, 8%, 12%); /* hsl(240, 8%, 12%) */
@include defineHSL(--color-white, 0, 0%, 100%); /* hsl(0, 0%, 100%) */
/* feedback */
@include defineHSL(--color-warning-darker, 46, 100%, 47%); /* hsl(46, 100%, 47%) */
@include defineHSL(--color-warning-dark, 46, 100%, 50%); /* hsl(46, 100%, 50%) */
@include defineHSL(--color-warning, 46, 100%, 61%); /* hsl(46, 100%, 61%) */
@include defineHSL(--color-warning-light, 46, 100%, 71%); /* hsl(46, 100%, 71%) */
@include defineHSL(--color-warning-lighter, 46, 100%, 80%); /* hsl(46, 100%, 80%) */
@include defineHSL(--color-success-darker, 94, 48%, 42%); /* hsl(94, 48%, 42%) */
@include defineHSL(--color-success-dark, 94, 48%, 48%); /* hsl(94, 48%, 48%) */
@include defineHSL(--color-success, 94, 48%, 56%); /* hsl(94, 48%, 56%) */
@include defineHSL(--color-success-light, 94, 48%, 65%); /* hsl(94, 48%, 65%) */
@include defineHSL(--color-success-lighter, 94, 48%, 74%); /* hsl(94, 48%, 74%) */
@include defineHSL(--color-error-darker, 349, 75%, 36%); /* hsl(349, 75%, 36%) */
@include defineHSL(--color-error-dark, 349, 75%, 44%); /* hsl(349, 75%, 44%) */
@include defineHSL(--color-error, 349, 75%, 51%); /* hsl(349, 75%, 51%) */
@include defineHSL(--color-error-light, 349, 75%, 59%); /* hsl(349, 75%, 59%) */
@include defineHSL(--color-error-lighter, 349, 75%, 67%); /* hsl(349, 75%, 67%) */
/* color contrasts */
@include defineHSL(--color-bg, 0, 0%, 100%); /* hsl(0, 0%, 100%) */
@include defineHSL(--color-contrast-lower, 0, 0%, 95%); /* hsl(0, 0%, 95%) */
@include defineHSL(--color-contrast-low, 240, 1%, 83%); /* hsl(240, 1%, 83%) */
@include defineHSL(--color-contrast-medium, 240, 1%, 48%); /* hsl(240, 1%, 48%) */
@include defineHSL(--color-contrast-high, 240, 4%, 20%); /* hsl(240, 4%, 20%) */
@include defineHSL(--color-contrast-higher, 240, 8%, 12%); /* hsl(240, 8%, 12%) */
}

46
src/css/forms.css Normal file
View File

@ -0,0 +1,46 @@
:root {
--form-control-font-size: 1em;
--form-control-padding-x: var(--space-xs);
--form-control-padding-y: var(--space-xxs);
--form-control-radius: 0.25em;
}
.form-control {
background: var(--color-bg);
border: 2px solid var(--color-contrast-low);
line-height: 1.2;
transition: all 0.2s ease;
}
.form-control::placeholder {
opacity: 1;
color: var(--color-contrast-medium);
}
.form-control:focus {
border-color: var(--color-primary);
box-shadow: 0px 0px 0px 2px alpha(var(--color-primary), 0.2);
outline: none;
}
.form-control--disabled, .form-control[disabled], .form-control[readonly] {
cursor: not-allowed;
}
.form-control[aria-invalid="true"],
.form-control--error {
border-color: var(--color-error);
}
.form-control[aria-invalid="true"]:focus,
.form-control--error:focus {
box-shadow: 0px 0px 0px 2px alpha(var(--color-error), 0.2);
}
.form-legend {
font-size: var(--text-md);
}
.form-label {
font-size: var(--text-sm);
}

82
src/css/icons.css Normal file
View File

@ -0,0 +1,82 @@
:root {
/* default icon sizes */
--icon-xxxs: 8px;
--icon-xxs: 12px;
--icon-xs: 16px;
--icon-sm: 24px;
--icon-md: 32px;
--icon-lg: 48px;
--icon-xl: 64px;
--icon-xxl: 96px;
--icon-xxxl: 128px;
}
.icon {
display: inline-block;
color: inherit;
fill: currentColor;
height: 1em;
width: 1em;
line-height: 1;
flex-shrink: 0;
max-width: initial;
}
/* icon size */
.icon--xxxs {
width: var(--icon-xxxs);
height: var(--icon-xxxs);
}
.icon--xxs {
width: var(--icon-xxs);
height: var(--icon-xxs);
}
.icon--xs {
width: var(--icon-xs);
height: var(--icon-xs);
}
.icon--sm {
width: var(--icon-sm);
height: var(--icon-sm);
}
.icon--md {
width: var(--icon-md);
height: var(--icon-md);
}
.icon--lg {
width: var(--icon-lg);
height: var(--icon-lg);
}
.icon--xl {
width: var(--icon-xl);
height: var(--icon-xl);
}
.icon--xxl {
width: var(--icon-xxl);
height: var(--icon-xxl);
}
.icon--xxxl {
width: var(--icon-xxxl);
height: var(--icon-xxxl);
}
.icon--is-spinning { /* rotate the icon infinitely */
animation: icon-spin 1s infinite linear;
}
@keyframes icon-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

0
src/css/main.css Normal file
View File

70
src/css/reset.css Normal file
View File

@ -0,0 +1,70 @@
*,
*::before,
*::after {
box-sizing: border-box;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
p,
ul,
ol,
figure,
blockquote,
dl,
dd {
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
min-height: 100vh;
text-rendering: optimizeSpeed;
line-height: 1.5;
}
ul,
ol {
list-style: none;
}
/* A elements that don't have a class get default styles */
a {
text-decoration-skip-ink: auto;
}
img,
picture {
max-width: 100%;
display: block;
}
p {
line-height: 1.5;
}
input,
button,
textarea,
select {
font: inherit;
}
.reset {
background-color: transparent;
padding: 0;
border: 0;
border-radius: 0;
color: inherit;
line-height: inherit;
appearance: none;
}

19
src/css/spacing.css Normal file
View File

@ -0,0 +1,19 @@
:root {
--space-unit: 1rem;
}
:root,
* {
--space-xxxxs: calc(0.125 * var(--space-unit));
--space-xxxs: calc(0.25 * var(--space-unit));
--space-xxs: calc(0.375 * var(--space-unit));
--space-xs: calc(0.5 * var(--space-unit));
--space-sm: calc(0.75 * var(--space-unit));
--space-md: calc(1.25 * var(--space-unit));
--space-lg: calc(2 * var(--space-unit));
--space-xl: calc(3.25 * var(--space-unit));
--space-xxl: calc(5.25 * var(--space-unit));
--space-xxxl: calc(8.5 * var(--space-unit));
--space-xxxxl: calc(13.75 * var(--space-unit));
--component-padding: var(--space-md);
}

227
src/css/typography.css Normal file
View File

@ -0,0 +1,227 @@
:root {
--heading-line-height: 1.2;
--body-line-height: 1.4;
}
.font-sans {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Oxygen-Sans, Ubuntu, Cantarell,
"Helvetica Neue", sans-serif;
}
.font-serif {
font-family: georgia, "times new roman", times, sans-serif;
}
.font-mono {
font-family: SFMono-Regular, Menlo, Monaco,
Consolas, "Liberation Mono",
"Courier New", monospace;
}
body,
.font-body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Oxygen-Sans, Ubuntu, Cantarell,
"Helvetica Neue", sans-serif;
}
h1,
h2,
h3,
h4,
h5,
h6,
.font-title {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Roboto, Oxygen-Sans, Ubuntu, Cantarell,
"Helvetica Neue", sans-serif;
}
body {
font-size: var(--text-base-size, 1em);
font-family: var(--font-primary, sans-serif);
color: var(--color-contrast-high, hsl(240, 4%, 20%));
}
h1,
h2,
h3,
h4,
h5,
h6{
color: var(--color-contrast-higher, hsl(240, 8%, 12%));
line-height: var(--heading-line-height, 1.2);
}
h1 {
font-size: var(--text-xxl, 2.074em);
}
h2 {
font-size: var(--text-xl, 1.728em);
}
h3 {
font-size: var(--text-lg, 1.44em);
}
h4,
h5,
h6{
font-size: var(--text-md, 1.2em);
}
small {
font-size: var(--text-sm, 0.833em);
}
/* -------------------------------- */
/* Inline Text */
/* -------------------------------- */
a,
.link {
color: var(--color-primary, hsl(220, 90%, 56%));
text-decoration: underline;
}
strong {
font-weight: bold;
}
s {
text-decoration: line-through;
}
u {
text-decoration: underline;
}
/* -------------------------------- */
/* Text Component - class used to stylize text blocks */
/* -------------------------------- */
.text-component h1,
.text-component h2,
.text-component h3,
.text-component h4 {
line-height: calc(var(--heading-line-height) * var(--line-height-multiplier, 1));
margin-bottom: calc(var(--space-unit) * 0.25 * var(--text-vspace-multiplier, 1));
}
.text-component h2,
.text-component h3,
.text-component h4 {
margin-top: calc(var(--space-unit) * 0.75 * var(--text-vspace-multiplier, 1));
}
.text-component p,
.text-component blockquote,
.text-component ul
.text-component li,
.text-component ol
.text-component li {
line-height: calc(var(--body-line-height) * var(--line-height-multiplier, 1));
}
.text-component ul,
.text-component ol,
.text-component p,
.text-component blockquote,
.text-component .text-component__block {
margin-bottom: calc(var(--space-unit) * 0.75 * var(--text-vspace-multiplier, 1));
}
.text-component ul,
.text-component ol {
list-style-position: inside;
}
.text-component ul {
list-style-type: disc;
}
.text-component ol {
list-style-type: decimal;
}
.text-component img {
display: block;
margin: 0 auto;
}
.text-component figcaption {
text-align: center;
margin-top: calc(var(--space-unit) * 0.5);
}
.text-component em {
font-style: italic;
}
.text-component hr {
margin-top: calc(var(--space-unit) * var(--text-vspace-multiplier, 1));
margin-bottom: calc(var(--space-unit) * var(--text-vspace-multiplier, 1));
margin-left: auto;
margin-right: auto;
}
.text-component *:first-child {
margin-top: 0;
}
.text-component *:last-child {
margin-bottom: 0;
}
/* text block container */
.text-component__block--full-width {
width: 100vw;
margin-left: calc(50% - 50vw);
}
@include breakpoint(sm) {
.text-component__block--left,
.text-component__block--right {
width: 45%;
}
.text-component__block--left img,
.text-component__block--right img {
width: 100%;
}
.text-component__block--left {
float: left;
margin-right: calc(var(--space-unit) * 0.75 * var(--text-vspace-multiplier, 1));
}
.text-component__block--right {
float: right;
margin-left: calc(var(--space-unit) * 0.75 * var(--text-vspace-multiplier, 1));
}
}
/* outset content */
@include breakpoint(xl) {
.text-component__block--outset {
width: calc(100% + 10.5 * var(--space-unit));
}
.text-component__block--outset img {
width: 100%;
}
.text-component__block--outset:not(.text-component__block--right) {
margin-left: calc(-5.25 * var(--space-unit));
}
.text-component__block--left, .text-component__block--right {
width: 50%;
}
.text-component__block--right.text-component__block--outset {
margin-right: calc(-5.25 * var(--space-unit));
}
}

39
src/css/variables.css Normal file
View File

@ -0,0 +1,39 @@
:root {
/* z-index */
--zindex-header: 3; /* e.g., main header */
--zindex-popover: 5; /* e.g., tooltips and dropdown */
--zindex-fixed-element: 10; /* e.g., 'back to top' button */
--zindex-overlay: 15; /* e.g., modals and dialogs */
/*radius */
--radius-sm: calc(var(--radius, 0.25em)/2);
--radius-md: var(--radius, 0.25em);
--radius-lg: calc(var(--radius, 0.25em)*2);
/*box shadow */
--shadow-xs: 0 0.1px 0.3px rgba(0, 0, 0, 0.06),
0 1px 2px rgba(0, 0, 0, 0.12);
--shadow-sm: 0 0.3px 0.4px rgba(0, 0, 0, 0.025),
0 0.9px 1.5px rgba(0, 0, 0, 0.05),
0 3.5px 6px rgba(0, 0, 0, 0.1);
--shadow-md: 0 0.9px 1.5px rgba(0, 0, 0, 0.03),
0 3.1px 5.5px rgba(0, 0, 0, 0.08),
0 14px 25px rgba(0, 0, 0, 0.12);
--shadow-lg: 0 1.2px 1.9px -1px rgba(0, 0, 0, 0.014),
0 3.3px 5.3px -1px rgba(0, 0, 0, 0.038),
0 8.5px 12.7px -1px rgba(0, 0, 0, 0.085),
0 30px 42px -1px rgba(0, 0, 0, 0.15);
--shadow-xl: 0 1.5px 2.1px -6px rgba(0, 0, 0, 0.012),
0 3.6px 5.2px -6px rgba(0, 0, 0, 0.035),
0 7.3px 10.6px -6px rgba(0, 0, 0, 0.07),
0 16.2px 21.9px -6px rgba(0, 0, 0, 0.117),
0 46px 60px -6px rgba(0, 0, 0, 0.2);
/*timing functions */
/*credits: https://github.com/ai/easings.net */
--bounce: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* ⚠️ deprecated - replaced with --ease-out-back */
--ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
--ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19);
--ease-out: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}

22
src/css/visibility.css Normal file
View File

@ -0,0 +1,22 @@
:root {
--display: block;
}
.is-visible {
display: var(--display) !important;
}
.is-hidden {
display: none !important;
}
html:not(.js) .no-js\:is-hidden {
display: none !important;
}
@media print {
.print\:is-hidden {
display: none !important;
}
}

3
src/postcss/README.md Normal file
View File

@ -0,0 +1,3 @@
**NOTE** - breakpoints are not currently included.
Need to evaluate various solutions to breakpoints using postcss.

15
src/postcss/functions.js Normal file
View File

@ -0,0 +1,15 @@
const postcssFunctions = {
// takes the custom property defined by a color defining mixin, along
// with an alpha value and returns the derived css hsla() function.
alpha(name, alpha) {
const hue = `var(${name}__h)`;
const saturation = `var(${name}__s)`;
const lightness = `var(${name}__l)`;
return `hsla(${hue}, ${saturation}, ${lightness}, ${alpha})`;
},
spacer(number = 1) {
return `calc(var(--spacer-height, 1.5rem) * ${number})`;
},
};
module.exports = postcssFunctions;

40
src/postcss/mixins.js Normal file
View File

@ -0,0 +1,40 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const toHSL = require('hex-to-hsl');
const postcssMixins = {
// untested TODO - test
defineHSL(mixin, name, hue, sat, light) {
const obj = {};
obj[name] = name;
// need to ensure hue is a string otherwise postcss (is it postcss?) appends
// 'px' to the property's value.
obj[`${name}__h`] = hue.toString();
obj[`${name}__s`] = `${sat}%`;
obj[`${name}__l`] = `${light}%`;
return obj;
},
// defines a custom property with identifier name, along with individual hue,
// saturation and lightness components
defineHex(mixin, name, hex) {
const [hue, sat, light] = toHSL(hex);
return defineHSL(name, hue, sat, light)
},
// TODO - untested
// // font rendering -> useful for light text on dark backgrounds
fontSmooth() {
return {
'-webkit-font-smoothing': 'antialiased',
'-moz-osx-font-smoothing': 'grayscale',
}
},
}
const postcssMixins = {
defineHSL,
defineHex,
};
module.exports = postcssMixins;

14
src/postcss/package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "postcss",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"hex-to-hsl": "^1.0.2"
}
}

View File

@ -0,0 +1,7 @@
$breakpoints: (
xs: 32rem, // ~512px
sm: 48rem, // ~768px
md: 64rem, // ~1024px
lg: 80rem, // ~1280px
xl: 90rem // ~1440px
);

1
src/sass/main.scss Normal file
View File

@ -0,0 +1 @@
TODO

144
src/sass/mixins.scss Normal file
View File

@ -0,0 +1,144 @@
// TODO - convert to duplicate postcss mixins
// --------------------------------
// Breakpoints
// --------------------------------
//
@mixin bp-min($breakpoint, $logic: false) {
@if( $logic ) {
@media #{$logic} and (min-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
} @else {
@media (min-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
}
}
@mixin bp-max($breakpoint, $logic: false) {
@if( $logic ) {
@media #{$logic} and (max-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
} @else {
@media (max-width: map-get($map: $breakpoints, $key: $breakpoint)) { @content; }
}
}
// --------------------------------
// Typography
// --------------------------------
// edit font rendering -> tip: use for light text on dark backgrounds
@mixin fontSmooth {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
// crop top space on text elements - caused by line height
//
// The mixin also accepts a (not required) second parameter (a number smaller than 1 that varies with the font-family value) that improves the crop effect.
// Since this additional parameter depends on the font-family only (it is not affected by font-size or font-weight or line-height), a good idea would be to define a CSS variable for each one of your font families.
// You can then use that variable to call the lhCrop mixin; this way, if you need to change your font-family, youll only need to update the value of that variable with no need to modify the mixin calls.
// In the 📁 custom-style/_typography.scss file, you find this variable defined for the primary font (--font-primary-capital-letter). Its default value is one, so make sure to update it according to your font-family.
@mixin lhCrop($line-height, $capital-letter: 1) {
&::before {
content: '';
display: block;
height: 0;
width: 0;
margin-top: calc((#{$capital-letter} - #{$line-height}) * 0.5em);
}
}
// edit text unit on a component level
@mixin textUnit($text-unit) {
--text-unit: #{$text-unit};
font-size: var(--text-unit);
}
// --------------------------------
// Spacing
// --------------------------------
// edit space unit on a component level
@mixin spaceUnit($space-unit) {
--space-unit: #{$space-unit};
}
// --------------------------------
// Reset
// --------------------------------
// reset user agent style
@mixin reset {
background-color: transparent;
padding: 0;
border: 0;
border-radius: 0;
color: inherit;
line-height: inherit;
appearance: none;
}
// --------------------------------
// Colors
// --------------------------------
// define HSL color variable
@mixin defineHSL($color, $hue, $saturation, $lightness) {
#{$color}: unquote("hsl(#{$hue}, #{$saturation}, #{$lightness})");#{$color}-h: #{$hue};#{$color}-s: #{$saturation};#{$color}-l: #{$lightness};
}
// return color with different opacity value
@function alpha($color, $opacity) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsla($color-h, $color-s, $color-l, $opacity);
}
// return color with different lightness value
@function lightness($color, $lightnessMultiplier) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsl($color-h, $color-s, calc(#{$color-l} * #{$lightnessMultiplier}));
}
// modify color HSLA values
@function adjustHSLA($color, $hueMultiplier: 1, $saturationMultiplier: 1, $lightnessMultiplier: 1, $opacity: 1) {
$color: str-replace($color, 'var(');
$color: str-replace($color, ')');
$color-h: var(#{$color+'-h'});
$color-s: var(#{$color+'-s'});
$color-l: var(#{$color+'-l'});
@return hsla(calc(#{$color-h} * #{$hueMultiplier}), calc(#{$color-s} * #{$saturationMultiplier}), calc(#{$color-l} * #{$lightnessMultiplier}), $opacity);
}
// replace substring with another string
// credits: https://css-tricks.com/snippets/sass/str-replace-function/
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
// --------------------------------
// Accessibility
// --------------------------------
// hide - content made available only to screen readers
@mixin srHide {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
}
// show
@mixin srShow {
position: static;
clip: auto;
clip-path: none;
}