From 3a7bd357faab32f80ceb7803af4c2f7bdd224db7 Mon Sep 17 00:00:00 2001 From: ray Date: Wed, 17 Feb 2021 18:25:50 +0000 Subject: [PATCH] initial commit --- LICENCE.md | 7 ++ README.md | 14 +++ src/css/accessibility.css | 10 ++ src/css/buttons.css | 80 ++++++++++++++ src/css/colors.css | 44 ++++++++ src/css/forms.css | 46 ++++++++ src/css/icons.css | 82 ++++++++++++++ src/css/main.css | 0 src/css/reset.css | 70 ++++++++++++ src/css/spacing.css | 19 ++++ src/css/typography.css | 227 ++++++++++++++++++++++++++++++++++++++ src/css/variables.css | 39 +++++++ src/css/visibility.css | 22 ++++ src/postcss/README.md | 3 + src/postcss/functions.js | 15 +++ src/postcss/mixins.js | 40 +++++++ src/postcss/package.json | 14 +++ src/sass/breakpoints.scss | 7 ++ src/sass/main.scss | 1 + src/sass/mixins.scss | 144 ++++++++++++++++++++++++ 20 files changed, 884 insertions(+) create mode 100644 LICENCE.md create mode 100644 README.md create mode 100644 src/css/accessibility.css create mode 100644 src/css/buttons.css create mode 100644 src/css/colors.css create mode 100644 src/css/forms.css create mode 100644 src/css/icons.css create mode 100644 src/css/main.css create mode 100644 src/css/reset.css create mode 100644 src/css/spacing.css create mode 100644 src/css/typography.css create mode 100644 src/css/variables.css create mode 100644 src/css/visibility.css create mode 100644 src/postcss/README.md create mode 100644 src/postcss/functions.js create mode 100644 src/postcss/mixins.js create mode 100644 src/postcss/package.json create mode 100644 src/sass/breakpoints.scss create mode 100644 src/sass/main.scss create mode 100644 src/sass/mixins.scss diff --git a/LICENCE.md b/LICENCE.md new file mode 100644 index 0000000..3d95dbf --- /dev/null +++ b/LICENCE.md @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cde5512 --- /dev/null +++ b/README.md @@ -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) diff --git a/src/css/accessibility.css b/src/css/accessibility.css new file mode 100644 index 0000000..73db195 --- /dev/null +++ b/src/css/accessibility.css @@ -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; + } +} + diff --git a/src/css/buttons.css b/src/css/buttons.css new file mode 100644 index 0000000..4fea5bc --- /dev/null +++ b/src/css/buttons.css @@ -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; +} diff --git a/src/css/colors.css b/src/css/colors.css new file mode 100644 index 0000000..49d130d --- /dev/null +++ b/src/css/colors.css @@ -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%) */ +} diff --git a/src/css/forms.css b/src/css/forms.css new file mode 100644 index 0000000..2913a7f --- /dev/null +++ b/src/css/forms.css @@ -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); +} diff --git a/src/css/icons.css b/src/css/icons.css new file mode 100644 index 0000000..773ff93 --- /dev/null +++ b/src/css/icons.css @@ -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); + } + } diff --git a/src/css/main.css b/src/css/main.css new file mode 100644 index 0000000..e69de29 diff --git a/src/css/reset.css b/src/css/reset.css new file mode 100644 index 0000000..5de4f4f --- /dev/null +++ b/src/css/reset.css @@ -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; +} diff --git a/src/css/spacing.css b/src/css/spacing.css new file mode 100644 index 0000000..1e402a7 --- /dev/null +++ b/src/css/spacing.css @@ -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); +} diff --git a/src/css/typography.css b/src/css/typography.css new file mode 100644 index 0000000..3693d89 --- /dev/null +++ b/src/css/typography.css @@ -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)); + } +} diff --git a/src/css/variables.css b/src/css/variables.css new file mode 100644 index 0000000..9e430c1 --- /dev/null +++ b/src/css/variables.css @@ -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); +} diff --git a/src/css/visibility.css b/src/css/visibility.css new file mode 100644 index 0000000..a1355ff --- /dev/null +++ b/src/css/visibility.css @@ -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; + } +} diff --git a/src/postcss/README.md b/src/postcss/README.md new file mode 100644 index 0000000..dbe205b --- /dev/null +++ b/src/postcss/README.md @@ -0,0 +1,3 @@ +**NOTE** - breakpoints are not currently included. + +Need to evaluate various solutions to breakpoints using postcss. diff --git a/src/postcss/functions.js b/src/postcss/functions.js new file mode 100644 index 0000000..b7577c9 --- /dev/null +++ b/src/postcss/functions.js @@ -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; diff --git a/src/postcss/mixins.js b/src/postcss/mixins.js new file mode 100644 index 0000000..8c7ab02 --- /dev/null +++ b/src/postcss/mixins.js @@ -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; diff --git a/src/postcss/package.json b/src/postcss/package.json new file mode 100644 index 0000000..85ef0fe --- /dev/null +++ b/src/postcss/package.json @@ -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" + } +} diff --git a/src/sass/breakpoints.scss b/src/sass/breakpoints.scss new file mode 100644 index 0000000..037ef8c --- /dev/null +++ b/src/sass/breakpoints.scss @@ -0,0 +1,7 @@ +$breakpoints: ( + xs: 32rem, // ~512px + sm: 48rem, // ~768px + md: 64rem, // ~1024px + lg: 80rem, // ~1280px + xl: 90rem // ~1440px +); diff --git a/src/sass/main.scss b/src/sass/main.scss new file mode 100644 index 0000000..1333ed7 --- /dev/null +++ b/src/sass/main.scss @@ -0,0 +1 @@ +TODO diff --git a/src/sass/mixins.scss b/src/sass/mixins.scss new file mode 100644 index 0000000..7ac90b0 --- /dev/null +++ b/src/sass/mixins.scss @@ -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, you’ll 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; +}