From 9119fa028ca9efb7fdcb49ccb45619e848f8f318 Mon Sep 17 00:00:00 2001 From: darius Date: Sat, 18 May 2024 18:27:08 +0200 Subject: [PATCH] sass re added --- .gitignore | 5 +- web/assets/css/sass/_index.scss | 10 + web/assets/css/sass/base/_index.scss | 6 + web/assets/css/sass/base/animations.scss | 15 + web/assets/css/sass/base/generic.scss | 239 +++++ web/assets/css/sass/base/minireset.scss | 92 ++ web/assets/css/sass/base/skeleton.scss | 126 +++ web/assets/css/sass/components/_index.scss | 13 + .../css/sass/components/breadcrumb.scss | 139 +++ web/assets/css/sass/components/card.scss | 162 +++ web/assets/css/sass/components/dropdown.scss | 188 ++++ web/assets/css/sass/components/menu.scss | 165 +++ web/assets/css/sass/components/message.scss | 183 ++++ web/assets/css/sass/components/modal.scss | 164 +++ web/assets/css/sass/components/navbar.scss | 788 ++++++++++++++ .../css/sass/components/pagination.scss | 379 +++++++ web/assets/css/sass/components/panel.scss | 218 ++++ web/assets/css/sass/components/tabs.scss | 273 +++++ web/assets/css/sass/elements/_index.scss | 16 + web/assets/css/sass/elements/block.scss | 6 + web/assets/css/sass/elements/box.scss | 59 ++ web/assets/css/sass/elements/button.scss | 640 ++++++++++++ web/assets/css/sass/elements/content.scss | 283 ++++++ web/assets/css/sass/elements/delete.scss | 6 + web/assets/css/sass/elements/icon.scss | 67 ++ web/assets/css/sass/elements/image.scss | 62 ++ web/assets/css/sass/elements/loader.scss | 15 + .../css/sass/elements/notification.scss | 105 ++ web/assets/css/sass/elements/progress.scss | 115 +++ web/assets/css/sass/elements/table.scss | 261 +++++ web/assets/css/sass/elements/tag.scss | 219 ++++ web/assets/css/sass/elements/title.scss | 128 +++ web/assets/css/sass/form/_index.scss | 9 + web/assets/css/sass/form/checkbox-radio.scss | 32 + web/assets/css/sass/form/file.scss | 330 ++++++ web/assets/css/sass/form/input-textarea.scss | 123 +++ web/assets/css/sass/form/select.scss | 143 +++ web/assets/css/sass/form/shared.scss | 172 ++++ web/assets/css/sass/form/tools.scss | 341 +++++++ web/assets/css/sass/grid/_index.scss | 5 + web/assets/css/sass/grid/columns-v2.scss | 957 ++++++++++++++++++ web/assets/css/sass/grid/columns.scss | 877 ++++++++++++++++ web/assets/css/sass/grid/grid.scss | 209 ++++ web/assets/css/sass/helpers/_index.scss | 15 + web/assets/css/sass/helpers/aspect-ratio.scss | 10 + web/assets/css/sass/helpers/border.scss | 15 + web/assets/css/sass/helpers/color.scss | 364 +++++++ web/assets/css/sass/helpers/flexbox.scss | 62 ++ web/assets/css/sass/helpers/float.scss | 28 + web/assets/css/sass/helpers/gap.scss | 24 + web/assets/css/sass/helpers/other.scss | 19 + web/assets/css/sass/helpers/overflow.scss | 21 + web/assets/css/sass/helpers/position.scss | 19 + web/assets/css/sass/helpers/spacing.scss | 64 ++ web/assets/css/sass/helpers/typography.scss | 168 +++ web/assets/css/sass/helpers/visibility.scss | 221 ++++ web/assets/css/sass/layout/_index.scss | 9 + web/assets/css/sass/layout/container.scss | 51 + web/assets/css/sass/layout/footer.scss | 23 + web/assets/css/sass/layout/hero.scss | 270 +++++ web/assets/css/sass/layout/level.scss | 107 ++ web/assets/css/sass/layout/media.scss | 106 ++ web/assets/css/sass/layout/section.scss | 34 + web/assets/css/sass/themes/_index.scss | 35 + web/assets/css/sass/themes/dark.scss | 56 + web/assets/css/sass/themes/light.scss | 145 +++ web/assets/css/sass/themes/setup.scss | 174 ++++ web/assets/css/sass/utilities/_index.scss | 7 + web/assets/css/sass/utilities/controls.scss | 85 ++ .../css/sass/utilities/css-variables.scss | 425 ++++++++ .../css/sass/utilities/derived-variables.scss | 112 ++ web/assets/css/sass/utilities/extends.scss | 34 + web/assets/css/sass/utilities/functions.scss | 258 +++++ .../css/sass/utilities/initial-variables.scss | 155 +++ web/assets/css/sass/utilities/mixins.scss | 460 +++++++++ 75 files changed, 11919 insertions(+), 2 deletions(-) create mode 100644 web/assets/css/sass/_index.scss create mode 100644 web/assets/css/sass/base/_index.scss create mode 100644 web/assets/css/sass/base/animations.scss create mode 100644 web/assets/css/sass/base/generic.scss create mode 100644 web/assets/css/sass/base/minireset.scss create mode 100644 web/assets/css/sass/base/skeleton.scss create mode 100644 web/assets/css/sass/components/_index.scss create mode 100644 web/assets/css/sass/components/breadcrumb.scss create mode 100644 web/assets/css/sass/components/card.scss create mode 100644 web/assets/css/sass/components/dropdown.scss create mode 100644 web/assets/css/sass/components/menu.scss create mode 100644 web/assets/css/sass/components/message.scss create mode 100644 web/assets/css/sass/components/modal.scss create mode 100644 web/assets/css/sass/components/navbar.scss create mode 100644 web/assets/css/sass/components/pagination.scss create mode 100644 web/assets/css/sass/components/panel.scss create mode 100644 web/assets/css/sass/components/tabs.scss create mode 100644 web/assets/css/sass/elements/_index.scss create mode 100644 web/assets/css/sass/elements/block.scss create mode 100644 web/assets/css/sass/elements/box.scss create mode 100644 web/assets/css/sass/elements/button.scss create mode 100644 web/assets/css/sass/elements/content.scss create mode 100644 web/assets/css/sass/elements/delete.scss create mode 100644 web/assets/css/sass/elements/icon.scss create mode 100644 web/assets/css/sass/elements/image.scss create mode 100644 web/assets/css/sass/elements/loader.scss create mode 100644 web/assets/css/sass/elements/notification.scss create mode 100644 web/assets/css/sass/elements/progress.scss create mode 100644 web/assets/css/sass/elements/table.scss create mode 100644 web/assets/css/sass/elements/tag.scss create mode 100644 web/assets/css/sass/elements/title.scss create mode 100644 web/assets/css/sass/form/_index.scss create mode 100644 web/assets/css/sass/form/checkbox-radio.scss create mode 100644 web/assets/css/sass/form/file.scss create mode 100644 web/assets/css/sass/form/input-textarea.scss create mode 100644 web/assets/css/sass/form/select.scss create mode 100644 web/assets/css/sass/form/shared.scss create mode 100644 web/assets/css/sass/form/tools.scss create mode 100644 web/assets/css/sass/grid/_index.scss create mode 100644 web/assets/css/sass/grid/columns-v2.scss create mode 100644 web/assets/css/sass/grid/columns.scss create mode 100644 web/assets/css/sass/grid/grid.scss create mode 100644 web/assets/css/sass/helpers/_index.scss create mode 100644 web/assets/css/sass/helpers/aspect-ratio.scss create mode 100644 web/assets/css/sass/helpers/border.scss create mode 100644 web/assets/css/sass/helpers/color.scss create mode 100644 web/assets/css/sass/helpers/flexbox.scss create mode 100644 web/assets/css/sass/helpers/float.scss create mode 100644 web/assets/css/sass/helpers/gap.scss create mode 100644 web/assets/css/sass/helpers/other.scss create mode 100644 web/assets/css/sass/helpers/overflow.scss create mode 100644 web/assets/css/sass/helpers/position.scss create mode 100644 web/assets/css/sass/helpers/spacing.scss create mode 100644 web/assets/css/sass/helpers/typography.scss create mode 100644 web/assets/css/sass/helpers/visibility.scss create mode 100644 web/assets/css/sass/layout/_index.scss create mode 100644 web/assets/css/sass/layout/container.scss create mode 100644 web/assets/css/sass/layout/footer.scss create mode 100644 web/assets/css/sass/layout/hero.scss create mode 100644 web/assets/css/sass/layout/level.scss create mode 100644 web/assets/css/sass/layout/media.scss create mode 100644 web/assets/css/sass/layout/section.scss create mode 100644 web/assets/css/sass/themes/_index.scss create mode 100644 web/assets/css/sass/themes/dark.scss create mode 100644 web/assets/css/sass/themes/light.scss create mode 100644 web/assets/css/sass/themes/setup.scss create mode 100644 web/assets/css/sass/utilities/_index.scss create mode 100644 web/assets/css/sass/utilities/controls.scss create mode 100644 web/assets/css/sass/utilities/css-variables.scss create mode 100644 web/assets/css/sass/utilities/derived-variables.scss create mode 100644 web/assets/css/sass/utilities/extends.scss create mode 100644 web/assets/css/sass/utilities/functions.scss create mode 100644 web/assets/css/sass/utilities/initial-variables.scss create mode 100644 web/assets/css/sass/utilities/mixins.scss diff --git a/.gitignore b/.gitignore index 9472062..b48b78a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **.env /.idea/ -**/css/sass/ - +**/sass/*/**.css +**/sass/*/**.css.map +!**/css/style.css diff --git a/web/assets/css/sass/_index.scss b/web/assets/css/sass/_index.scss new file mode 100644 index 0000000..82310cb --- /dev/null +++ b/web/assets/css/sass/_index.scss @@ -0,0 +1,10 @@ +@forward "utilities"; +@forward "themes"; +@forward "base"; +@forward "elements"; +@forward "form"; +@forward "components"; +@forward "grid"; +@forward "layout"; +@forward "base/skeleton"; +@forward "helpers"; diff --git a/web/assets/css/sass/base/_index.scss b/web/assets/css/sass/base/_index.scss new file mode 100644 index 0000000..4416b1f --- /dev/null +++ b/web/assets/css/sass/base/_index.scss @@ -0,0 +1,6 @@ +/* Bulma Base */ +@charset "utf-8"; + +@forward "minireset"; +@forward "generic"; +@forward "animations"; diff --git a/web/assets/css/sass/base/animations.scss b/web/assets/css/sass/base/animations.scss new file mode 100644 index 0000000..667124c --- /dev/null +++ b/web/assets/css/sass/base/animations.scss @@ -0,0 +1,15 @@ +@keyframes spinAround { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(359deg); + } +} + +@keyframes pulsate { + 50% { + opacity: 0.5; + } +} diff --git a/web/assets/css/sass/base/generic.scss b/web/assets/css/sass/base/generic.scss new file mode 100644 index 0000000..b7ee0cc --- /dev/null +++ b/web/assets/css/sass/base/generic.scss @@ -0,0 +1,239 @@ +@use "../utilities/css-variables.scss" as cv; +@use "../utilities/mixins" as mx; + +$body-background-color: cv.getVar("scheme-main") !default; +$body-size: 1em !default; +$body-min-width: 300px !default; +$body-rendering: optimizeLegibility !default; +$body-family: cv.getVar("family-primary") !default; +$body-overflow-x: hidden !default; +$body-overflow-y: scroll !default; + +$body-color: cv.getVar("text") !default; +$body-font-size: 1em !default; +$body-weight: cv.getVar("weight-normal") !default; +$body-line-height: 1.5 !default; + +$code-family: cv.getVar("family-code") !default; +$code-padding: 0.25em 0.5em 0.25em !default; +$code-weight: normal !default; +$code-size: 0.875em !default; + +$small-font-size: 0.875em !default; + +$hr-background-color: cv.getVar("background") !default; +$hr-height: 2px !default; +$hr-margin: 1.5rem 0 !default; + +$strong-color: cv.getVar("text-strong") !default; +$strong-weight: cv.getVar("weight-semibold") !default; + +$pre-font-size: 0.875em !default; +$pre-padding: 1.25rem 1.5rem !default; +$pre-code-font-size: 1em !default; + +:root { + @include cv.register-vars( + ( + "body-background-color": #{$body-background-color}, + "body-size": #{$body-size}, + "body-min-width": #{$body-min-width}, + "body-rendering": #{$body-rendering}, + "body-family": #{$body-family}, + "body-overflow-x": #{$body-overflow-x}, + "body-overflow-y": #{$body-overflow-y}, + "body-color": #{$body-color}, + "body-font-size": #{$body-font-size}, + "body-weight": #{$body-weight}, + "body-line-height": #{$body-line-height}, + "code-family": #{$code-family}, + "code-padding": #{$code-padding}, + "code-weight": #{$code-weight}, + "code-size": #{$code-size}, + "small-font-size": #{$small-font-size}, + "hr-background-color": #{$hr-background-color}, + "hr-height": #{$hr-height}, + "hr-margin": #{$hr-margin}, + "strong-color": #{$strong-color}, + "strong-weight": #{$strong-weight}, + "pre-font-size": #{$pre-font-size}, + "pre-padding": #{$pre-padding}, + "pre-code-font-size": #{$pre-code-font-size}, + ) + ); +} + +html { + background-color: cv.getVar("body-background-color"); + font-size: cv.getVar("body-size"); + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + min-width: cv.getVar("body-min-width"); + overflow-x: cv.getVar("body-overflow-x"); + overflow-y: cv.getVar("body-overflow-y"); + text-rendering: cv.getVar("body-rendering"); + text-size-adjust: 100%; +} + +article, +aside, +figure, +footer, +header, +hgroup, +section { + display: block; +} + +body, +button, +input, +optgroup, +select, +textarea { + font-family: cv.getVar("body-family"); +} + +code, +pre { + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: auto; + font-family: cv.getVar("code-family"); +} + +body { + color: cv.getVar("body-color"); + font-size: cv.getVar("body-font-size"); + font-weight: cv.getVar("body-weight"); + line-height: cv.getVar("body-line-height"); +} + +// Inline + +a, +button { + cursor: pointer; + + &:focus-visible { + outline-color: hsl( + cv.getVar("focus-h"), + cv.getVar("focus-s"), + cv.getVar("focus-l") + ); + outline-offset: cv.getVar("focus-offset"); + outline-style: cv.getVar("focus-style"); + outline-width: cv.getVar("focus-width"); + + &:active { + outline-width: 1px; + } + } + + &:active { + outline-width: 1px; + } +} + +a { + color: cv.getVar("link-text"); + cursor: pointer; + text-decoration: none; + transition-duration: cv.getVar("duration"); + transition-property: background-color, border-color, color; + + strong { + color: currentColor; + } +} + +button { + @include mx.reset; + transition-duration: cv.getVar("duration"); + transition-property: background-color, border-color, color; +} + +code { + background-color: cv.getVar("code-background"); + border-radius: 0.5em; + color: cv.getVar("code"); + font-size: cv.getVar("code-size"); + font-weight: cv.getVar("code-weight"); + padding: cv.getVar("code-padding"); +} + +hr { + background-color: cv.getVar("hr-background-color"); + border: none; + display: block; + height: cv.getVar("hr-height"); + margin: cv.getVar("hr-margin"); +} + +img { + height: auto; + max-width: 100%; +} + +input[type="checkbox"], +input[type="radio"] { + vertical-align: baseline; +} + +small { + font-size: cv.getVar("small-font-size"); +} + +span { + font-style: inherit; + font-weight: inherit; +} + +strong { + color: cv.getVar("strong-color"); + font-weight: cv.getVar("strong-weight"); +} + +svg { + height: auto; + width: auto; +} + +// Block + +fieldset { + border: none; +} + +pre { + @include mx.overflow-touch; + + background-color: cv.getVar("pre-background"); + color: cv.getVar("pre"); + font-size: cv.getVar("pre-font-size"); + overflow-x: auto; + padding: cv.getVar("pre-padding"); + white-space: pre; + word-wrap: normal; + + code { + background-color: transparent; + color: currentColor; + font-size: cv.getVar("pre-code-font-size"); + padding: 0; + } +} + +table { + td, + th { + vertical-align: top; + + &:not([align]) { + text-align: inherit; + } + } + + th { + color: cv.getVar("text-strong"); + } +} diff --git a/web/assets/css/sass/base/minireset.scss b/web/assets/css/sass/base/minireset.scss new file mode 100644 index 0000000..5b09693 --- /dev/null +++ b/web/assets/css/sass/base/minireset.scss @@ -0,0 +1,92 @@ +/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */ +// Blocks +html, +body, +p, +ol, +ul, +li, +dl, +dt, +dd, +blockquote, +figure, +fieldset, +legend, +textarea, +pre, +iframe, +hr, +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0; + padding: 0; +} + +// Headings +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: 100%; + font-weight: normal; +} + +// List +ul { + list-style: none; +} + +// Form +button, +input, +select, +textarea { + margin: 0; +} + +// Box sizing +html { + box-sizing: border-box; +} + +* { + &, + &::before, + &::after { + box-sizing: inherit; + } +} + +// Media +img, +video { + height: auto; + max-width: 100%; +} + +// Iframe +iframe { + border: 0; +} + +// Table +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; + + &:not([align]) { + text-align: inherit; + } +} diff --git a/web/assets/css/sass/base/skeleton.scss b/web/assets/css/sass/base/skeleton.scss new file mode 100644 index 0000000..792e2ce --- /dev/null +++ b/web/assets/css/sass/base/skeleton.scss @@ -0,0 +1,126 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; +@use "../utilities/extends"; + +$skeleton-background: cv.getVar("border") !default; +$skeleton-radius: cv.getVar("radius-small") !default; +$skeleton-block-min-height: 4.5em !default; +$skeleton-lines-gap: 0.75em !default; +$skeleton-line-height: 0.75em !default; + +:root { + @include cv.register-vars( + ( + "skeleton-background": #{$skeleton-background}, + "skeleton-radius": #{$skeleton-radius}, + "skeleton-block-min-height": #{$skeleton-block-min-height}, + "skeleton-lines-gap": #{$skeleton-lines-gap}, + "skeleton-line-height": #{$skeleton-line-height}, + ) + ); +} + +%skeleton-pulsation { + animation-duration: 2s; + animation-iteration-count: infinite; + animation-name: pulsate; + animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1); + background-color: cv.getVar("skeleton-background"); + border-radius: cv.getVar("skeleton-radius"); + box-shadow: none; + pointer-events: none; +} + +.#{iv.$class-prefix}is-skeleton { + @extend %skeleton-pulsation; + color: transparent !important; + + em, + strong { + color: inherit; + } + + img { + visibility: hidden; + } + + &.#{iv.$class-prefix}checkbox { + input { + opacity: 0; + } + } + + &.#{iv.$class-prefix}delete { + border-radius: cv.getVar("radius-rounded"); + + &::before, + &::after { + display: none; + } + } +} + +input.#{iv.$class-prefix}is-skeleton, +textarea.#{iv.$class-prefix}is-skeleton { + resize: none; + + @include mx.placeholder { + color: transparent !important; + } +} + +.#{iv.$class-prefix}has-skeleton { + color: transparent !important; + position: relative; + + &::after { + @extend %skeleton-pulsation; + content: ""; + display: block; + height: 100%; + left: 0; + max-width: 100%; + min-width: 10%; + position: absolute; + top: 0; + width: 7em; + } +} + +.#{iv.$class-prefix}skeleton-block { + @extend %block; + @extend %skeleton-pulsation; + color: transparent !important; + min-height: cv.getVar("skeleton-block-min-height"); +} + +.#{iv.$class-prefix}skeleton-lines { + color: transparent !important; + display: flex; + flex-direction: column; + gap: cv.getVar("skeleton-lines-gap"); + position: relative; + + > div { + @extend %skeleton-pulsation; + height: cv.getVar("skeleton-line-height"); + + &:last-child { + min-width: 4em; + width: 30%; + } + } +} + +.#{iv.$class-prefix}skeleton { + background-image: linear-gradient( + 0deg, + transparent 0%, + transparent 50%, + #f60 50%, + #f60 100% + ); + background-position: top left; + background-size: 1.5em; +} diff --git a/web/assets/css/sass/components/_index.scss b/web/assets/css/sass/components/_index.scss new file mode 100644 index 0000000..2decd67 --- /dev/null +++ b/web/assets/css/sass/components/_index.scss @@ -0,0 +1,13 @@ +/* Bulma Components */ +@charset "utf-8"; + +@forward "breadcrumb"; +@forward "card"; +@forward "dropdown"; +@forward "menu"; +@forward "message"; +@forward "modal"; +@forward "navbar"; +@forward "pagination"; +@forward "panel"; +@forward "tabs"; diff --git a/web/assets/css/sass/components/breadcrumb.scss b/web/assets/css/sass/components/breadcrumb.scss new file mode 100644 index 0000000..bd261fb --- /dev/null +++ b/web/assets/css/sass/components/breadcrumb.scss @@ -0,0 +1,139 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins"; + +$breadcrumb-item-color: cv.getVar("link-text") !default; +$breadcrumb-item-hover-color: cv.getVar("link-text-hover") !default; +$breadcrumb-item-active-color: cv.getVar("link-text-active") !default; + +$breadcrumb-item-padding-vertical: 0 !default; +$breadcrumb-item-padding-horizontal: 0.75em !default; + +$breadcrumb-item-separator-color: cv.getVar("border") !default; + +.#{iv.$class-prefix}breadcrumb { + @include cv.register-vars( + ( + "breadcrumb-item-color": #{$breadcrumb-item-color}, + "breadcrumb-item-hover-color": #{$breadcrumb-item-hover-color}, + "breadcrumb-item-active-color": #{$breadcrumb-item-active-color}, + "breadcrumb-item-padding-vertical": #{$breadcrumb-item-padding-vertical}, + "breadcrumb-item-padding-horizontal": #{$breadcrumb-item-padding-horizontal}, + "breadcrumb-item-separator-color": #{$breadcrumb-item-separator-color}, + ) + ); +} + +.#{iv.$class-prefix}breadcrumb { + @extend %block; + @extend %unselectable; + font-size: cv.getVar("size-normal"); + white-space: nowrap; + + a { + align-items: center; + color: cv.getVar("breadcrumb-item-color"); + display: flex; + justify-content: center; + padding: cv.getVar("breadcrumb-item-padding-vertical") + cv.getVar("breadcrumb-item-padding-horizontal"); + + &:hover { + color: cv.getVar("breadcrumb-item-hover-color"); + } + } + + li { + align-items: center; + display: flex; + + &:first-child a { + padding-inline-start: 0; + } + + &.#{iv.$class-prefix}is-active { + a { + color: cv.getVar("breadcrumb-item-active-color"); + cursor: default; + pointer-events: none; + } + } + + & + li::before { + color: cv.getVar("breadcrumb-item-separator-color"); + content: "/"; + } + } + + ul, + ol { + align-items: flex-start; + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + } + + .#{iv.$class-prefix}icon { + &:first-child { + margin-inline-end: 0.5em; + } + + &:last-child { + margin-inline-start: 0.5em; + } + } + + // Alignment + &.#{iv.$class-prefix}is-centered { + ol, + ul { + justify-content: center; + } + } + + &.#{iv.$class-prefix}is-right { + ol, + ul { + justify-content: flex-end; + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } + + // Styles + &.#{iv.$class-prefix}has-arrow-separator { + li + li::before { + content: "→"; + } + } + + &.#{iv.$class-prefix}has-bullet-separator { + li + li::before { + content: "•"; + } + } + + &.#{iv.$class-prefix}has-dot-separator { + li + li::before { + content: "·"; + } + } + + &.#{iv.$class-prefix}has-succeeds-separator { + li + li::before { + content: "≻"; + } + } +} diff --git a/web/assets/css/sass/components/card.scss b/web/assets/css/sass/components/card.scss new file mode 100644 index 0000000..0b3b2c5 --- /dev/null +++ b/web/assets/css/sass/components/card.scss @@ -0,0 +1,162 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$card-color: cv.getVar("text") !default; +$card-background-color: cv.getVar("scheme-main") !default; +$card-shadow: cv.getVar("shadow") !default; +$card-radius: 0.75rem !default; + +$card-header-background-color: transparent !default; +$card-header-color: cv.getVar("text-strong") !default; +$card-header-padding: 0.75rem 1rem !default; +$card-header-shadow: 0 0.125em 0.25em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.1 + ) !default; +$card-header-weight: cv.getVar("weight-bold") !default; + +$card-content-background-color: transparent !default; +$card-content-padding: 1.5rem !default; + +$card-footer-background-color: transparent !default; +$card-footer-border-top: 1px solid cv.getVar("border-weak") !default; +$card-footer-padding: 0.75rem !default; + +$card-media-margin: cv.getVar("block-spacing") !default; + +.#{iv.$class-prefix}card { + @include cv.register-vars( + ( + "card-color": #{$card-color}, + "card-background-color": #{$card-background-color}, + "card-shadow": #{$card-shadow}, + "card-radius": #{$card-radius}, + "card-header-background-color": #{$card-header-background-color}, + "card-header-color": #{$card-header-color}, + "card-header-padding": #{$card-header-padding}, + "card-header-shadow": #{$card-header-shadow}, + "card-header-weight": #{$card-header-weight}, + "card-content-background-color": #{$card-content-background-color}, + "card-content-padding": #{$card-content-padding}, + "card-footer-background-color": #{$card-footer-background-color}, + "card-footer-border-top": #{$card-footer-border-top}, + "card-footer-padding": #{$card-footer-padding}, + "card-media-margin": #{$card-media-margin}, + ) + ); +} + +.#{iv.$class-prefix}card { + @extend %block; + background-color: cv.getVar("card-background-color"); + border-radius: cv.getVar("card-radius"); + box-shadow: cv.getVar("card-shadow"); + color: cv.getVar("card-color"); + max-width: 100%; + position: relative; +} + +%card-item { + &:first-child { + border-start-start-radius: cv.getVar("card-radius"); + border-start-end-radius: cv.getVar("card-radius"); + } + + &:last-child { + border-end-start-radius: cv.getVar("card-radius"); + border-end-end-radius: cv.getVar("card-radius"); + } +} + +.#{iv.$class-prefix}card-header { + @extend %card-item; + background-color: cv.getVar("card-header-background-color"); + align-items: stretch; + box-shadow: cv.getVar("card-header-shadow"); + display: flex; +} + +.#{iv.$class-prefix}card-header-title { + align-items: center; + color: cv.getVar("card-header-color"); + display: flex; + flex-grow: 1; + font-weight: cv.getVar("card-header-weight"); + padding: cv.getVar("card-header-padding"); + + &.#{iv.$class-prefix}is-centered { + justify-content: center; + } +} + +.#{iv.$class-prefix}card-header-icon { + @include mx.reset; + + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + padding: cv.getVar("card-header-padding"); +} + +.#{iv.$class-prefix}card-image { + display: block; + position: relative; + + &:first-child { + img { + border-start-start-radius: cv.getVar("card-radius"); + border-start-end-radius: cv.getVar("card-radius"); + } + } + + &:last-child { + img { + border-end-start-radius: cv.getVar("card-radius"); + border-end-end-radius: cv.getVar("card-radius"); + } + } +} + +.#{iv.$class-prefix}card-content { + @extend %card-item; + + background-color: cv.getVar("card-content-background-color"); + padding: cv.getVar("card-content-padding"); +} + +.#{iv.$class-prefix}card-footer { + @extend %card-item; + + background-color: cv.getVar("card-footer-background-color"); + border-top: cv.getVar("card-footer-border-top"); + align-items: stretch; + display: flex; +} + +.#{iv.$class-prefix}card-footer-item { + align-items: center; + display: flex; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + justify-content: center; + padding: cv.getVar("card-footer-padding"); + + &:not(:last-child) { + border-inline-end: cv.getVar("card-footer-border-top"); + } +} + +// Combinations + +.#{iv.$class-prefix}card { + .#{iv.$class-prefix}media:not(:last-child) { + margin-bottom: cv.getVar("card-media-margin"); + } +} diff --git a/web/assets/css/sass/components/dropdown.scss b/web/assets/css/sass/components/dropdown.scss new file mode 100644 index 0000000..415728b --- /dev/null +++ b/web/assets/css/sass/components/dropdown.scss @@ -0,0 +1,188 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$dropdown-menu-min-width: 12rem !default; + +$dropdown-content-background-color: cv.getVar("scheme-main") !default; +$dropdown-content-offset: 0.25rem !default; +$dropdown-content-padding-bottom: 0.5rem !default; +$dropdown-content-padding-top: 0.5rem !default; +$dropdown-content-radius: cv.getVar("radius") !default; +$dropdown-content-shadow: cv.getVar("shadow") !default; +$dropdown-content-z: 20 !default; + +$dropdown-item-h: cv.getVar("scheme-h"); +$dropdown-item-s: cv.getVar("scheme-s"); +$dropdown-item-l: cv.getVar("scheme-main-l"); +$dropdown-item-background-l: cv.getVar("scheme-main-l"); +$dropdown-item-background-l-delta: 0%; +$dropdown-item-hover-background-l-delta: cv.getVar("hover-background-l-delta"); +$dropdown-item-active-background-l-delta: cv.getVar( + "active-background-l-delta" +); +$dropdown-item-color-l: cv.getVar("text-strong-l"); +$dropdown-item-selected-h: cv.getVar("link-h"); +$dropdown-item-selected-s: cv.getVar("link-s"); +$dropdown-item-selected-l: cv.getVar("link-l"); +$dropdown-item-selected-background-l: cv.getVar("link-l"); +$dropdown-item-selected-color-l: cv.getVar("link-invert-l"); + +$dropdown-divider-background-color: cv.getVar("border-weak") !default; + +.#{iv.$class-prefix}dropdown { + // prettier-ignore-start + @include cv.register-vars( + ( + "dropdown-menu-min-width": #{$dropdown-menu-min-width}, + "dropdown-content-background-color": #{$dropdown-content-background-color}, + "dropdown-content-offset": #{$dropdown-content-offset}, + "dropdown-content-padding-bottom": #{$dropdown-content-padding-bottom}, + "dropdown-content-padding-top": #{$dropdown-content-padding-top}, + "dropdown-content-radius": #{$dropdown-content-radius}, + "dropdown-content-shadow": #{$dropdown-content-shadow}, + "dropdown-content-z": #{$dropdown-content-z}, + "dropdown-item-h": #{$dropdown-item-h}, + "dropdown-item-s": #{$dropdown-item-s}, + "dropdown-item-l": #{$dropdown-item-l}, + "dropdown-item-background-l": #{$dropdown-item-background-l}, + "dropdown-item-background-l-delta": #{$dropdown-item-background-l-delta}, + "dropdown-item-hover-background-l-delta": #{$dropdown-item-hover-background-l-delta}, + "dropdown-item-active-background-l-delta": #{$dropdown-item-active-background-l-delta}, + "dropdown-item-color-l": #{$dropdown-item-color-l}, + "dropdown-item-selected-h": #{$dropdown-item-selected-h}, + "dropdown-item-selected-s": #{$dropdown-item-selected-s}, + "dropdown-item-selected-l": #{$dropdown-item-selected-l}, + "dropdown-item-selected-background-l": #{$dropdown-item-selected-background-l}, + "dropdown-item-selected-color-l": #{$dropdown-item-selected-color-l}, + "dropdown-divider-background-color": #{$dropdown-divider-background-color}, + ) + ); + // prettier-ignore-end +} + +.#{iv.$class-prefix}dropdown { + display: inline-flex; + position: relative; + vertical-align: top; + + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-hoverable:hover { + .#{iv.$class-prefix}dropdown-menu { + display: block; + } + } + + &.#{iv.$class-prefix}is-right { + .#{iv.$class-prefix}dropdown-menu { + left: auto; + right: 0; + } + } + + &.#{iv.$class-prefix}is-up { + .#{iv.$class-prefix}dropdown-menu { + bottom: 100%; + padding-bottom: cv.getVar("dropdown-content-offset"); + padding-top: initial; + top: auto; + } + } +} + +.#{iv.$class-prefix}dropdown-menu { + display: none; + @include mx.ltr-position(0, false); + min-width: cv.getVar("dropdown-menu-min-width"); + padding-top: cv.getVar("dropdown-content-offset"); + position: absolute; + top: 100%; + z-index: cv.getVar("dropdown-content-z"); +} + +.#{iv.$class-prefix}dropdown-content { + background-color: cv.getVar("dropdown-content-background-color"); + border-radius: cv.getVar("dropdown-content-radius"); + box-shadow: cv.getVar("dropdown-content-shadow"); + padding-bottom: cv.getVar("dropdown-content-padding-bottom"); + padding-top: cv.getVar("dropdown-content-padding-top"); +} + +.#{iv.$class-prefix}dropdown-item { + color: hsl( + #{cv.getVar("dropdown-item-h")}, + #{cv.getVar("dropdown-item-s")}, + #{cv.getVar("dropdown-item-color-l")} + ); + display: block; + font-size: 0.875rem; + line-height: 1.5; + padding: 0.375rem 1rem; +} + +a.#{iv.$class-prefix}dropdown-item, +button.#{iv.$class-prefix}dropdown-item { + background-color: hsl( + #{cv.getVar("dropdown-item-h")}, + #{cv.getVar("dropdown-item-s")}, + calc( + #{cv.getVar("dropdown-item-background-l")} + #{cv.getVar( + "dropdown-item-background-l-delta" + )} + ) + ); + padding-inline-end: 3rem; + text-align: inherit; + white-space: nowrap; + width: 100%; + + &:hover { + @include cv.register-vars( + ( + "dropdown-item-background-l-delta": #{cv.getVar( + "dropdown-item-hover-background-l-delta" + )}, + "dropdown-item-border-l-delta": #{cv.getVar( + "dropdown-item-hover-border-l-delta" + )}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "dropdown-item-background-l-delta": #{cv.getVar( + "dropdown-item-active-background-l-delta" + )}, + "dropdown-item-border-l-delta": #{cv.getVar( + "dropdown-item-active-border-l-delta" + )}, + ) + ); + } + + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-selected { + @include cv.register-vars( + ( + "dropdown-item-h": #{cv.getVar("dropdown-item-selected-h")}, + "dropdown-item-s": #{cv.getVar("dropdown-item-selected-s")}, + "dropdown-item-l": #{cv.getVar("dropdown-item-selected-l")}, + "dropdown-item-background-l": #{cv.getVar( + "dropdown-item-selected-background-l" + )}, + "dropdown-item-color-l": #{cv.getVar("dropdown-item-selected-color-l")}, + ) + ); + } +} + +.#{iv.$class-prefix}dropdown-divider { + background-color: cv.getVar("dropdown-divider-background-color"); + border: none; + display: block; + height: 1px; + margin: 0.5rem 0; +} diff --git a/web/assets/css/sass/components/menu.scss b/web/assets/css/sass/components/menu.scss new file mode 100644 index 0000000..2bee7d5 --- /dev/null +++ b/web/assets/css/sass/components/menu.scss @@ -0,0 +1,165 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$menu-item-h: cv.getVar("scheme-h"); +$menu-item-s: cv.getVar("scheme-s"); +$menu-item-l: cv.getVar("scheme-main-l"); +$menu-item-background-l: cv.getVar("scheme-main-l"); +$menu-item-background-l-delta: 0%; +$menu-item-hover-background-l-delta: cv.getVar("hover-background-l-delta"); +$menu-item-active-background-l-delta: cv.getVar("active-background-l-delta"); +$menu-item-color-l: cv.getVar("text-l"); +$menu-item-radius: cv.getVar("radius-small") !default; +$menu-item-selected-h: cv.getVar("link-h"); +$menu-item-selected-s: cv.getVar("link-s"); +$menu-item-selected-l: cv.getVar("link-l"); +$menu-item-selected-background-l: cv.getVar("link-l"); +$menu-item-selected-color-l: cv.getVar("link-invert-l"); + +$menu-list-border-left: 1px solid cv.getVar("border") !default; +$menu-list-line-height: 1.25 !default; +$menu-list-link-padding: 0.5em 0.75em !default; +$menu-nested-list-margin: 0.75em !default; +$menu-nested-list-padding-left: 0.75em !default; + +$menu-label-color: cv.getVar("text-weak") !default; +$menu-label-font-size: 0.75em !default; +$menu-label-letter-spacing: 0.1em !default; +$menu-label-spacing: 1em !default; + +.#{iv.$class-prefix}menu { + @include cv.register-vars( + ( + "menu-item-h": #{$menu-item-h}, + "menu-item-s": #{$menu-item-s}, + "menu-item-l": #{$menu-item-l}, + "menu-item-background-l": #{$menu-item-background-l}, + "menu-item-background-l-delta": #{$menu-item-background-l-delta}, + "menu-item-hover-background-l-delta": #{$menu-item-hover-background-l-delta}, + "menu-item-active-background-l-delta": #{$menu-item-active-background-l-delta}, + "menu-item-color-l": #{$menu-item-color-l}, + "menu-item-radius": #{$menu-item-radius}, + "menu-item-selected-h": #{$menu-item-selected-h}, + "menu-item-selected-s": #{$menu-item-selected-s}, + "menu-item-selected-l": #{$menu-item-selected-l}, + "menu-item-selected-background-l": #{$menu-item-selected-background-l}, + "menu-item-selected-color-l": #{$menu-item-selected-color-l}, + "menu-list-border-left": #{$menu-list-border-left}, + "menu-list-line-height": #{$menu-list-line-height}, + "menu-list-link-padding": #{$menu-list-link-padding}, + "menu-nested-list-margin": #{$menu-nested-list-margin}, + "menu-nested-list-padding-left": #{$menu-nested-list-padding-left}, + "menu-label-color": #{$menu-label-color}, + "menu-label-font-size": #{$menu-label-font-size}, + "menu-label-letter-spacing": #{$menu-label-letter-spacing}, + "menu-label-spacing": #{$menu-label-spacing}, + ) + ); +} + +.#{iv.$class-prefix}menu { + font-size: cv.getVar("size-normal"); + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } +} + +.#{iv.$class-prefix}menu-list { + line-height: cv.getVar("menu-list-line-height"); + + a, + button, + .#{iv.$class-prefix}menu-item { + @extend %reset; + background-color: hsl( + #{cv.getVar("menu-item-h")}, + #{cv.getVar("menu-item-s")}, + calc( + #{cv.getVar("menu-item-background-l")} + #{cv.getVar( + "menu-item-background-l-delta" + )} + ) + ); + border-radius: cv.getVar("menu-item-radius"); + color: hsl( + #{cv.getVar("menu-item-h")}, + #{cv.getVar("menu-item-s")}, + #{cv.getVar("menu-item-color-l")} + ); + display: block; + padding: cv.getVar("menu-list-link-padding"); + text-align: left; + width: 100%; + + &:hover { + @include cv.register-vars( + ( + "menu-item-background-l-delta": #{cv.getVar( + "menu-item-hover-background-l-delta" + )}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "menu-item-background-l-delta": #{cv.getVar( + "menu-item-active-background-l-delta" + )}, + ) + ); + } + + // Modifiers + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-selected { + @include cv.register-vars( + ( + "menu-item-h": #{cv.getVar("menu-item-selected-h")}, + "menu-item-s": #{cv.getVar("menu-item-selected-s")}, + "menu-item-l": #{cv.getVar("menu-item-selected-l")}, + "menu-item-background-l": #{cv.getVar( + "menu-item-selected-background-l" + )}, + "menu-item-color-l": #{cv.getVar("menu-item-selected-color-l")}, + ) + ); + } + } + + li { + ul { + border-inline-start: cv.getVar("menu-list-border-left"); + margin: cv.getVar("menu-nested-list-margin"); + padding-inline-start: cv.getVar("menu-nested-list-padding-left"); + } + } +} + +.#{iv.$class-prefix}menu-label { + color: cv.getVar("menu-label-color"); + font-size: cv.getVar("menu-label-font-size"); + letter-spacing: cv.getVar("menu-label-letter-spacing"); + text-transform: uppercase; + + &:not(:first-child) { + margin-top: cv.getVar("menu-label-spacing"); + } + + &:not(:last-child) { + margin-bottom: cv.getVar("menu-label-spacing"); + } +} diff --git a/web/assets/css/sass/components/message.scss b/web/assets/css/sass/components/message.scss new file mode 100644 index 0000000..03196fe --- /dev/null +++ b/web/assets/css/sass/components/message.scss @@ -0,0 +1,183 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$message-h: cv.getVar("scheme-h"); +$message-s: cv.getVar("scheme-s"); +$message-background-l: cv.getVar("background-l"); +$message-border-l: cv.getVar("border-l"); +$message-border-l-delta: -20% !default; +$message-border-style: solid; +$message-border-width: 0.25em; +$message-color-l: cv.getVar("text-l"); +$message-header-background-l: cv.getVar("dark-l"); +$message-header-color-l: cv.getVar("text-dark-invert-l"); +$message-radius: cv.getVar("radius") !default; + +$message-header-weight: cv.getVar("weight-semibold") !default; +$message-header-padding: 1em 1.25em !default; +$message-header-radius: cv.getVar("radius") !default; + +$message-body-border-width: 0 0 0 4px !default; +$message-body-color: cv.getVar("text") !default; +$message-body-padding: 1.25em 1.5em !default; +$message-body-radius: cv.getVar("radius-small") !default; + +$message-body-pre-code-background-color: transparent !default; + +$message-header-body-border-width: 0 !default; +$message-colors: dv.$colors !default; + +.#{iv.$class-prefix}message { + @include cv.register-vars( + ( + "message-border-l-delta": #{$message-border-l-delta}, + "message-radius": #{$message-radius}, + "message-header-weight": #{$message-header-weight}, + "message-header-padding": #{$message-header-padding}, + "message-header-radius": #{$message-header-radius}, + "message-body-border-width": #{$message-body-border-width}, + "message-body-color": #{$message-body-color}, + "message-body-padding": #{$message-body-padding}, + "message-body-radius": #{$message-body-radius}, + "message-body-pre-code-background-color": #{$message-body-pre-code-background-color}, + "message-header-body-border-width": #{$message-header-body-border-width}, + "message-h": #{$message-h}, + "message-s": #{$message-s}, + "message-background-l": #{$message-background-l}, + "message-border-l": #{$message-border-l}, + "message-border-style": #{$message-border-style}, + "message-border-width": #{$message-border-width}, + "message-color-l": #{$message-color-l}, + "message-header-background-l": #{$message-header-background-l}, + "message-header-color-l": #{$message-header-color-l}, + ) + ); +} + +.#{iv.$class-prefix}message { + @extend %block; + border-radius: cv.getVar("message-radius"); + color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-color-l")} + ); + font-size: cv.getVar("size-normal"); + + strong { + color: currentColor; + } + + a:not(.#{iv.$class-prefix}button):not(.#{iv.$class-prefix}tag):not( + .#{iv.$class-prefix}dropdown-item + ) { + color: currentColor; + text-decoration: underline; + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } + + // Colors + @each $name, $components in $message-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "message-h": #{cv.getVar($name, "", "-h")}, + "message-s": #{cv.getVar($name, "", "-s")}, + "message-border-l": + calc( + #{cv.getVar($name, "", "-l")} + #{cv.getVar( + "message-border-l-delta" + )} + ), + "message-color-l": #{cv.getVar($name, "", "-on-scheme-l")}, + "message-header-background-l": #{cv.getVar($name, "", "-l")}, + "message-header-color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + } + } +} + +.#{iv.$class-prefix}message-header { + align-items: center; + background-color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-header-background-l")} + ); + border-start-start-radius: cv.getVar("message-header-radius"); + border-start-end-radius: cv.getVar("message-header-radius"); + color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-header-color-l")} + ); + display: flex; + font-weight: cv.getVar("message-header-weight"); + justify-content: space-between; + line-height: 1.25; + padding: cv.getVar("message-header-padding"); + position: relative; + + .#{iv.$class-prefix}delete { + flex-grow: 0; + flex-shrink: 0; + margin-inline-start: 0.75em; + } + + & + .#{iv.$class-prefix}message-body { + border-width: cv.getVar("message-header-body-border-width"); + border-start-start-radius: 0; + border-start-end-radius: 0; + } +} + +.#{iv.$class-prefix}message-body { + background-color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-background-l")} + ); + border-inline-start-color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-border-l")} + ); + border-inline-start-style: #{cv.getVar("message-border-style")}; + border-inline-start-width: #{cv.getVar("message-border-width")}; + border-radius: cv.getVar("message-body-radius"); + padding: cv.getVar("message-body-padding"); + + code, + pre { + background-color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-header-color-l")} + ); + color: hsl( + #{cv.getVar("message-h")}, + #{cv.getVar("message-s")}, + #{cv.getVar("message-header-background-l")} + ); + } + + pre code { + background-color: cv.getVar("message-body-pre-code-background-color"); + } +} diff --git a/web/assets/css/sass/components/modal.scss b/web/assets/css/sass/components/modal.scss new file mode 100644 index 0000000..0a0aa59 --- /dev/null +++ b/web/assets/css/sass/components/modal.scss @@ -0,0 +1,164 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$modal-z: 40 !default; + +$modal-background-background-color: hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.86 +) !default; + +$modal-content-width: 40rem !default; +$modal-content-margin-mobile: 1.25rem !default; +$modal-content-spacing-mobile: 10rem !default; +$modal-content-spacing-tablet: 2.5rem !default; + +$modal-close-dimensions: 2.5rem !default; +$modal-close-right: 1.25rem !default; +$modal-close-top: 1.25rem !default; + +$modal-card-spacing: 2.5rem !default; + +$modal-card-head-background-color: cv.getVar("scheme-main") !default; +$modal-card-head-padding: 2rem !default; +$modal-card-head-radius: cv.getVar("radius-large") !default; + +$modal-card-title-color: cv.getVar("text-strong") !default; +$modal-card-title-line-height: 1 !default; +$modal-card-title-size: cv.getVar("size-4") !default; + +$modal-card-foot-background-color: cv.getVar("scheme-main-bis") !default; +$modal-card-foot-radius: cv.getVar("radius-large") !default; + +$modal-card-body-background-color: cv.getVar("scheme-main") !default; +$modal-card-body-padding: 2rem !default; + +$modal-breakpoint: iv.$tablet !default; + +.#{iv.$class-prefix}modal { + @include cv.register-vars( + ( + "modal-z": #{$modal-z}, + "modal-background-background-color": #{$modal-background-background-color}, + "modal-content-width": #{$modal-content-width}, + "modal-content-margin-mobile": #{$modal-content-margin-mobile}, + "modal-content-spacing-mobile": #{$modal-content-spacing-mobile}, + "modal-content-spacing-tablet": #{$modal-content-spacing-tablet}, + "modal-close-dimensions": #{$modal-close-dimensions}, + "modal-close-right": #{$modal-close-right}, + "modal-close-top": #{$modal-close-top}, + "modal-card-spacing": #{$modal-card-spacing}, + "modal-card-head-background-color": #{$modal-card-head-background-color}, + "modal-card-head-padding": #{$modal-card-head-padding}, + "modal-card-head-radius": #{$modal-card-head-radius}, + "modal-card-title-color": #{$modal-card-title-color}, + "modal-card-title-line-height": #{$modal-card-title-line-height}, + "modal-card-title-size": #{$modal-card-title-size}, + "modal-card-foot-background-color": #{$modal-card-foot-background-color}, + "modal-card-foot-radius": #{$modal-card-foot-radius}, + "modal-card-body-background-color": #{$modal-card-body-background-color}, + "modal-card-body-padding": #{$modal-card-body-padding}, + ) + ); +} + +.#{iv.$class-prefix}modal { + @extend %overlay; + + align-items: center; + display: none; + flex-direction: column; + justify-content: center; + overflow: hidden; + position: fixed; + z-index: cv.getVar("modal-z"); + + // Modifiers + &.#{iv.$class-prefix}is-active { + display: flex; + } +} + +.#{iv.$class-prefix}modal-background { + @extend %overlay; + background-color: cv.getVar("modal-background-background-color"); +} + +.#{iv.$class-prefix}modal-content, +.#{iv.$class-prefix}modal-card { + margin: 0 cv.getVar("modal-content-margin-mobile"); + max-height: calc(100vh - #{cv.getVar("modal-content-spacing-mobile")}); + overflow: auto; + position: relative; + width: 100%; + + // Responsiveness + @include mx.from($modal-breakpoint) { + margin: 0 auto; + max-height: calc(100vh - #{cv.getVar("modal-content-spacing-tablet")}); + width: cv.getVar("modal-content-width"); + } +} + +.#{iv.$class-prefix}modal-close { + @extend %delete; + background: none; + height: cv.getVar("modal-close-dimensions"); + inset-inline-end: cv.getVar("modal-close-right"); + position: fixed; + top: cv.getVar("modal-close-top"); + width: cv.getVar("modal-close-dimensions"); +} + +.#{iv.$class-prefix}modal-card { + display: flex; + flex-direction: column; + max-height: calc(100vh - #{cv.getVar("modal-card-spacing")}); + overflow: hidden; + overflow-y: visible; +} + +.#{iv.$class-prefix}modal-card-head, +.#{iv.$class-prefix}modal-card-foot { + align-items: center; + display: flex; + flex-shrink: 0; + justify-content: flex-start; + padding: cv.getVar("modal-card-head-padding"); + position: relative; +} + +.#{iv.$class-prefix}modal-card-head { + background-color: cv.getVar("modal-card-head-background-color"); + border-start-start-radius: cv.getVar("modal-card-head-radius"); + border-start-end-radius: cv.getVar("modal-card-head-radius"); + box-shadow: cv.getVar("shadow"); +} + +.#{iv.$class-prefix}modal-card-title { + color: cv.getVar("modal-card-title-color"); + flex-grow: 1; + flex-shrink: 0; + font-size: cv.getVar("modal-card-title-size"); + line-height: cv.getVar("modal-card-title-line-height"); +} + +.#{iv.$class-prefix}modal-card-foot { + background-color: cv.getVar("modal-card-foot-background-color"); + border-end-start-radius: cv.getVar("modal-card-foot-radius"); + border-end-end-radius: cv.getVar("modal-card-foot-radius"); +} + +.#{iv.$class-prefix}modal-card-body { + @include mx.overflow-touch; + background-color: cv.getVar("modal-card-body-background-color"); + flex-grow: 1; + flex-shrink: 1; + overflow: auto; + padding: cv.getVar("modal-card-body-padding"); +} diff --git a/web/assets/css/sass/components/navbar.scss b/web/assets/css/sass/components/navbar.scss new file mode 100644 index 0000000..c755aff --- /dev/null +++ b/web/assets/css/sass/components/navbar.scss @@ -0,0 +1,788 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$navbar-h: cv.getVar("scheme-h"); +$navbar-s: cv.getVar("scheme-s"); +$navbar-l: cv.getVar("scheme-main-l"); +$navbar-background-color: cv.getVar("scheme-main") !default; +$navbar-box-shadow-size: 0 0.125em 0 0 !default; +$navbar-box-shadow-color: cv.getVar("background") !default; +$navbar-height: 3.25rem !default; +$navbar-padding-vertical: 1rem !default; +$navbar-padding-horizontal: 2rem !default; +$navbar-z: 30 !default; +$navbar-fixed-z: 30 !default; + +$navbar-item-background-a: 0; +$navbar-item-background-l: cv.getVar("scheme-main-l"); +$navbar-item-background-l-delta: 0%; +$navbar-item-hover-background-l-delta: cv.getVar("hover-background-l-delta"); +$navbar-item-active-background-l-delta: cv.getVar("active-background-l-delta"); +$navbar-item-color-l: cv.getVar("text-l"); +$navbar-item-selected-h: cv.getVar("link-h"); +$navbar-item-selected-s: cv.getVar("link-s"); +$navbar-item-selected-l: cv.getVar("link-l"); +$navbar-item-selected-background-l: cv.getVar("link-l"); +$navbar-item-selected-color-l: cv.getVar("link-invert-l"); +$navbar-item-img-max-height: 1.75rem !default; + +$navbar-dropdown-item-h: cv.getVar("scheme-h"); +$navbar-dropdown-item-s: cv.getVar("scheme-s"); +$navbar-dropdown-item-l: cv.getVar("scheme-main-l"); +$navbar-dropdown-item-background-l: cv.getVar("scheme-main-l"); +$navbar-dropdown-item-color-l: cv.getVar("text-l"); + +$navbar-burger-color: cv.getVar("navbar-item-color") !default; + +$navbar-tab-hover-background-color: transparent !default; +$navbar-tab-hover-border-bottom-color: cv.getVar("link") !default; +$navbar-tab-active-color: cv.getVar("link") !default; +$navbar-tab-active-background-color: transparent !default; +$navbar-tab-active-border-bottom-color: cv.getVar("link") !default; +$navbar-tab-active-border-bottom-style: solid !default; +$navbar-tab-active-border-bottom-width: 0.1875em !default; + +$navbar-dropdown-background-color: cv.getVar("scheme-main") !default; +$navbar-dropdown-border-l: cv.getVar("border-l") !default; +$navbar-dropdown-border-color: hsl( + cv.getVar("navbar-h"), + cv.getVar("navbar-s"), + cv.getVar("navbar-dropdown-border-l") +) !default; +$navbar-dropdown-border-style: solid !default; +$navbar-dropdown-border-width: 0.125em !default; +$navbar-dropdown-offset: -0.25em !default; +$navbar-dropdown-arrow: cv.getVar("link") !default; +$navbar-dropdown-radius: cv.getVar("radius-large") !default; +$navbar-dropdown-z: 20 !default; + +$navbar-dropdown-boxed-radius: cv.getVar("radius-large") !default; +$navbar-dropdown-boxed-shadow: + 0 0.5em 0.5em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.1 + ), + 0 0 0 1px + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.1 + ) !default; + +$navbar-divider-background-l: cv.getVar("background-l") !default; +$navbar-divider-height: 0.125em !default; + +$navbar-bottom-box-shadow-size: 0 -0.125em 0 0 !default; + +$navbar-breakpoint: iv.$desktop !default; + +$navbar-colors: dv.$colors !default; + +@mixin navbar-fixed { + left: 0; + position: fixed; + right: 0; + z-index: cv.getVar("navbar-fixed-z"); +} + +:root { + @include cv.register-vars( + ( + "navbar-height": #{$navbar-height}, + ) + ); +} + +.#{iv.$class-prefix}navbar { + @include cv.register-vars( + ( + "navbar-h": #{$navbar-h}, + "navbar-s": #{$navbar-s}, + "navbar-l": #{$navbar-l}, + "navbar-background-color": #{$navbar-background-color}, + "navbar-box-shadow-size": #{$navbar-box-shadow-size}, + "navbar-box-shadow-color": #{$navbar-box-shadow-color}, + "navbar-padding-vertical": #{$navbar-padding-vertical}, + "navbar-padding-horizontal": #{$navbar-padding-horizontal}, + "navbar-z": #{$navbar-z}, + "navbar-fixed-z": #{$navbar-fixed-z}, + "navbar-item-background-a": #{$navbar-item-background-a}, + "navbar-item-background-l": #{$navbar-item-background-l}, + "navbar-item-background-l-delta": #{$navbar-item-background-l-delta}, + "navbar-item-hover-background-l-delta": #{$navbar-item-hover-background-l-delta}, + "navbar-item-active-background-l-delta": #{$navbar-item-active-background-l-delta}, + "navbar-item-color-l": #{$navbar-item-color-l}, + "navbar-item-selected-h": #{$navbar-item-selected-h}, + "navbar-item-selected-s": #{$navbar-item-selected-s}, + "navbar-item-selected-l": #{$navbar-item-selected-l}, + "navbar-item-selected-background-l": #{$navbar-item-selected-background-l}, + "navbar-item-selected-color-l": #{$navbar-item-selected-color-l}, + "navbar-item-img-max-height": #{$navbar-item-img-max-height}, + "navbar-burger-color": #{$navbar-burger-color}, + "navbar-tab-hover-background-color": #{$navbar-tab-hover-background-color}, + "navbar-tab-hover-border-bottom-color": #{$navbar-tab-hover-border-bottom-color}, + "navbar-tab-active-color": #{$navbar-tab-active-color}, + "navbar-tab-active-background-color": #{$navbar-tab-active-background-color}, + "navbar-tab-active-border-bottom-color": #{$navbar-tab-active-border-bottom-color}, + "navbar-tab-active-border-bottom-style": #{$navbar-tab-active-border-bottom-style}, + "navbar-tab-active-border-bottom-width": #{$navbar-tab-active-border-bottom-width}, + "navbar-dropdown-background-color": #{$navbar-dropdown-background-color}, + "navbar-dropdown-border-l": #{$navbar-dropdown-border-l}, + "navbar-dropdown-border-color": #{$navbar-dropdown-border-color}, + "navbar-dropdown-border-style": #{$navbar-dropdown-border-style}, + "navbar-dropdown-border-width": #{$navbar-dropdown-border-width}, + "navbar-dropdown-offset": #{$navbar-dropdown-offset}, + "navbar-dropdown-arrow": #{$navbar-dropdown-arrow}, + "navbar-dropdown-radius": #{$navbar-dropdown-radius}, + "navbar-dropdown-z": #{$navbar-dropdown-z}, + "navbar-dropdown-boxed-radius": #{$navbar-dropdown-boxed-radius}, + "navbar-dropdown-boxed-shadow": #{$navbar-dropdown-boxed-shadow}, + "navbar-dropdown-item-h": #{$navbar-dropdown-item-h}, + "navbar-dropdown-item-s": #{$navbar-dropdown-item-s}, + "navbar-dropdown-item-l": #{$navbar-dropdown-item-l}, + "navbar-dropdown-item-background-l": #{$navbar-dropdown-item-background-l}, + "navbar-dropdown-item-color-l": #{$navbar-dropdown-item-color-l}, + "navbar-divider-background-l": #{$navbar-divider-background-l}, + "navbar-divider-height": #{$navbar-divider-height}, + "navbar-bottom-box-shadow-size": #{$navbar-bottom-box-shadow-size}, + ) + ); +} + +.#{iv.$class-prefix}navbar { + background-color: cv.getVar("navbar-background-color"); + min-height: cv.getVar("navbar-height"); + position: relative; + z-index: cv.getVar("navbar-z"); + + @each $name, $pair in $navbar-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "navbar-h": #{cv.getVar($name, "", "-h")}, + "navbar-s": #{cv.getVar($name, "", "-s")}, + "navbar-l": #{cv.getVar($name, "", "-l")}, + "burger-h": #{cv.getVar($name, "", "-h")}, + "burger-s": #{cv.getVar($name, "", "-s")}, + "burger-l": #{cv.getVar($name, "", "-invert-l")}, + "navbar-background-color": #{cv.getVar($name)}, + "navbar-item-background-l": #{cv.getVar($name, "", "-l")}, + "navbar-item-color-l": #{cv.getVar($name, "", "-invert-l")}, + "navbar-item-selected-h": #{cv.getVar($name, "", "-h")}, + "navbar-item-selected-s": #{cv.getVar($name, "", "-s")}, + "navbar-item-selected-l": #{cv.getVar($name, "", "-l")}, + "navbar-item-selected-background-l": #{cv.getVar($name, "", "-l")}, + "navbar-item-selected-color-l": #{cv.getVar($name, "", "-invert-l")}, + "navbar-dropdown-arrow": #{cv.getVar($name, "", "-invert-l")}, + "navbar-dropdown-background-color": + hsl( + #{cv.getVar($name, "", "-h")}, + #{cv.getVar($name, "", "-s")}, + #{cv.getVar("navbar-dropdown-item-background-l")} + ), + "navbar-dropdown-item-h": #{cv.getVar($name, "", "-h")}, + "navbar-dropdown-item-s": #{cv.getVar($name, "", "-s")}, + ) + ); + } + } + + & > .#{iv.$class-prefix}container { + align-items: stretch; + display: flex; + min-height: cv.getVar("navbar-height"); + width: 100%; + } + + &.#{iv.$class-prefix}has-shadow { + box-shadow: cv.getVar("navbar-box-shadow-size") + cv.getVar("navbar-box-shadow-color"); + } + + &.#{iv.$class-prefix}is-fixed-bottom, + &.#{iv.$class-prefix}is-fixed-top { + @include navbar-fixed; + } + + &.#{iv.$class-prefix}is-fixed-bottom { + bottom: 0; + + &.#{iv.$class-prefix}has-shadow { + box-shadow: cv.getVar("navbar-bottom-box-shadow-size") + cv.getVar("navbar-box-shadow-color"); + } + } + + &.#{iv.$class-prefix}is-fixed-top { + top: 0; + } +} + +html, +body { + &.#{iv.$class-prefix}has-navbar-fixed-top { + padding-top: cv.getVar("navbar-height"); + } + + &.#{iv.$class-prefix}has-navbar-fixed-bottom { + padding-bottom: cv.getVar("navbar-height"); + } +} + +.#{iv.$class-prefix}navbar-brand, +.#{iv.$class-prefix}navbar-tabs { + align-items: stretch; + display: flex; + flex-shrink: 0; + min-height: cv.getVar("navbar-height"); +} + +.#{iv.$class-prefix}navbar-tabs { + @include mx.overflow-touch; + max-width: 100vw; + overflow-x: auto; + overflow-y: hidden; +} + +.#{iv.$class-prefix}navbar-burger { + @extend %reset; + @include mx.burger(2.5rem); + align-self: center; + margin-inline-start: auto; + margin-inline-end: 0.375rem; +} + +.#{iv.$class-prefix}navbar-menu { + display: none; +} + +.#{iv.$class-prefix}navbar-item, +.#{iv.$class-prefix}navbar-link { + color: hsl( + #{cv.getVar("navbar-h")}, + #{cv.getVar("navbar-s")}, + #{cv.getVar("navbar-item-color-l")} + ); + display: block; + line-height: 1.5; + padding: 0.5rem 0.75rem; + position: relative; + + .#{iv.$class-prefix}icon { + &:only-child { + margin-left: -0.25rem; + margin-right: -0.25rem; + } + } +} + +a.#{iv.$class-prefix}navbar-item, +.#{iv.$class-prefix}navbar-link { + background-color: hsla( + #{cv.getVar("navbar-h")}, + #{cv.getVar("navbar-s")}, + calc( + #{cv.getVar("navbar-item-background-l")} + #{cv.getVar( + "navbar-item-background-l-delta" + )} + ), + #{cv.getVar("navbar-item-background-a")} + ); + cursor: pointer; + + &:focus, + &:focus-within, + &:hover { + @include cv.register-vars( + ( + "navbar-item-background-l-delta": #{cv.getVar( + "navbar-item-hover-background-l-delta" + )}, + "navbar-item-background-a": 1, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "navbar-item-background-l-delta": #{cv.getVar( + "navbar-item-active-background-l-delta" + )}, + "navbar-item-background-a": 1, + ) + ); + } + + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-selected { + @include cv.register-vars( + ( + "navbar-h": #{cv.getVar("navbar-item-selected-h")}, + "navbar-s": #{cv.getVar("navbar-item-selected-s")}, + "navbar-l": #{cv.getVar("navbar-item-selected-l")}, + "navbar-item-background-l": #{cv.getVar( + "navbar-item-selected-background-l" + )}, + "navbar-item-background-a": 1, + "navbar-item-color-l": #{cv.getVar("navbar-item-selected-color-l")}, + ) + ); + } +} + +.#{iv.$class-prefix}navbar-item { + flex-grow: 0; + flex-shrink: 0; + + img, + svg { + max-height: cv.getVar("navbar-item-img-max-height"); + } + + &.#{iv.$class-prefix}has-dropdown { + padding: 0; + } + + &.#{iv.$class-prefix}is-expanded { + flex-grow: 1; + flex-shrink: 1; + } + + &.#{iv.$class-prefix}is-tab { + border-bottom: 1px solid transparent; + min-height: cv.getVar("navbar-height"); + padding-bottom: calc(0.5rem - 1px); + + &:focus, + &:hover { + background-color: cv.getVar("navbar-tab-hover-background-color"); + border-bottom-color: cv.getVar("navbar-tab-hover-border-bottom-color"); + } + + &.#{iv.$class-prefix}is-active { + background-color: cv.getVar("navbar-tab-active-background-color"); + border-bottom-color: cv.getVar("navbar-tab-active-border-bottom-color"); + border-bottom-style: cv.getVar("navbar-tab-active-border-bottom-style"); + border-bottom-width: cv.getVar("navbar-tab-active-border-bottom-width"); + color: cv.getVar("navbar-tab-active-color"); + padding-bottom: calc( + 0.5rem - #{cv.getVar("navbar-tab-active-border-bottom-width")} + ); + } + } +} + +.#{iv.$class-prefix}navbar-content { + flex-grow: 1; + flex-shrink: 1; +} + +.#{iv.$class-prefix}navbar-link:not(.#{iv.$class-prefix}is-arrowless) { + padding-inline-end: 2.5em; + + &::after { + @extend %arrow; + border-color: cv.getVar("navbar-dropdown-arrow"); + margin-top: -0.375em; + inset-inline-end: 1.125em; + } +} + +.#{iv.$class-prefix}navbar-dropdown { + font-size: 0.875rem; + padding-bottom: 0.75rem; + padding-top: 0.5rem; + + .#{iv.$class-prefix}navbar-item { + padding-left: 1.5rem; + padding-right: 1.5rem; + + &:not(.is-active, .is-selected) { + background-color: hsl( + #{cv.getVar("navbar-dropdown-item-h")}, + #{cv.getVar("navbar-dropdown-item-s")}, + calc( + #{cv.getVar("navbar-dropdown-item-background-l")} + #{cv.getVar( + "navbar-item-background-l-delta" + )} + ) + ); + color: hsl( + #{cv.getVar("navbar-dropdown-item-h")}, + #{cv.getVar("navbar-dropdown-item-s")}, + #{cv.getVar("navbar-dropdown-item-color-l")} + ); + } + } +} + +.#{iv.$class-prefix}navbar-divider { + background-color: hsl( + #{cv.getVar("navbar-h")}, + #{cv.getVar("navbar-s")}, + #{cv.getVar("navbar-divider-background-l")} + ); + border: none; + display: none; + height: cv.getVar("navbar-divider-height"); + margin: 0.5rem 0; +} + +@include mx.until($navbar-breakpoint) { + .#{iv.$class-prefix}navbar > .#{iv.$class-prefix}container { + display: block; + } + + .#{iv.$class-prefix}navbar-brand, + .#{iv.$class-prefix}navbar-tabs { + .#{iv.$class-prefix}navbar-item { + align-items: center; + display: flex; + } + } + + .#{iv.$class-prefix}navbar-link { + &::after { + display: none; + } + } + + .#{iv.$class-prefix}navbar-menu { + background-color: cv.getVar("navbar-background-color"); + box-shadow: 0 0.5em 1em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.1 + ); + padding: 0.5rem 0; + + &.#{iv.$class-prefix}is-active { + display: block; + } + } + + // Fixed navbar + .#{iv.$class-prefix}navbar { + &.#{iv.$class-prefix}is-fixed-bottom-touch, + &.#{iv.$class-prefix}is-fixed-top-touch { + @include navbar-fixed; + } + + &.#{iv.$class-prefix}is-fixed-bottom-touch { + bottom: 0; + + &.#{iv.$class-prefix}has-shadow { + box-shadow: 0 -0.125em 0.1875em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar( + "scheme-s" + )}, #{cv.getVar("scheme-invert-l")}, 0.1); + } + } + + &.#{iv.$class-prefix}is-fixed-top-touch { + top: 0; + } + + &.#{iv.$class-prefix}is-fixed-top, + &.#{iv.$class-prefix}is-fixed-top-touch { + .#{iv.$class-prefix}navbar-menu { + @include mx.overflow-touch; + max-height: calc(100vh - #{cv.getVar("navbar-height")}); + overflow: auto; + } + } + } + + html, + body { + &.#{iv.$class-prefix}has-navbar-fixed-top-touch { + padding-top: cv.getVar("navbar-height"); + } + + &.#{iv.$class-prefix}has-navbar-fixed-bottom-touch { + padding-bottom: cv.getVar("navbar-height"); + } + } +} + +@include mx.from($navbar-breakpoint) { + .#{iv.$class-prefix}navbar, + .#{iv.$class-prefix}navbar-menu, + .#{iv.$class-prefix}navbar-start, + .#{iv.$class-prefix}navbar-end { + align-items: stretch; + display: flex; + } + + .#{iv.$class-prefix}navbar { + min-height: cv.getVar("navbar-height"); + + &.#{iv.$class-prefix}is-spaced { + padding: cv.getVar("navbar-padding-vertical") + cv.getVar("navbar-padding-horizontal"); + + .#{iv.$class-prefix}navbar-start, + .#{iv.$class-prefix}navbar-end { + align-items: center; + } + + a.#{iv.$class-prefix}navbar-item, + .#{iv.$class-prefix}navbar-link { + border-radius: cv.getVar("radius"); + } + } + + &.#{iv.$class-prefix}is-transparent { + @include cv.register-vars( + ( + "navbar-item-background-a": 0, + ) + ); + + .#{iv.$class-prefix}navbar-dropdown { + a.#{iv.$class-prefix}navbar-item { + background-color: hsl( + #{cv.getVar("navbar-h")}, + #{cv.getVar("navbar-s")}, + calc( + #{cv.getVar("navbar-item-background-l")} + #{cv.getVar( + "navbar-item-background-l-delta" + )} + ) + ); + + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-selected { + @include cv.register-vars( + ( + "navbar-h": #{cv.getVar("navbar-item-selected-h")}, + "navbar-s": #{cv.getVar("navbar-item-selected-s")}, + "navbar-l": #{cv.getVar("navbar-item-selected-l")}, + "navbar-item-background-l": #{cv.getVar( + "navbar-item-selected-background-l" + )}, + "navbar-item-color-l": #{cv.getVar( + "navbar-item-selected-color-l" + )}, + ) + ); + } + } + } + } + } + + .#{iv.$class-prefix}navbar-burger { + display: none; + } + + .#{iv.$class-prefix}navbar-item, + .#{iv.$class-prefix}navbar-link { + align-items: center; + display: flex; + } + + .#{iv.$class-prefix}navbar-item { + &.#{iv.$class-prefix}has-dropdown { + align-items: stretch; + } + + &.#{iv.$class-prefix}has-dropdown-up { + .#{iv.$class-prefix}navbar-link::after { + transform: rotate(135deg) translate(0.25em, -0.25em); + } + + .#{iv.$class-prefix}navbar-dropdown { + border-bottom-color: cv.getVar("navbar-dropdown-border-color"); + border-bottom-style: cv.getVar("navbar-dropdown-border-style"); + border-bottom-width: cv.getVar("navbar-dropdown-border-width"); + border-radius: cv.getVar("navbar-dropdown-radius") + cv.getVar("navbar-dropdown-radius") 0 0; + border-top: none; + bottom: 100%; + box-shadow: 0 -0.5em 0.5em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar( + "scheme-s" + )}, #{cv.getVar("scheme-invert-l")}, 0.1); + top: auto; + } + } + + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-hoverable:focus, + &.#{iv.$class-prefix}is-hoverable:focus-within, + &.#{iv.$class-prefix}is-hoverable:hover { + .#{iv.$class-prefix}navbar-dropdown { + display: block; + + .#{iv.$class-prefix}navbar.#{iv.$class-prefix}is-spaced &, + &.#{iv.$class-prefix}is-boxed { + opacity: 1; + pointer-events: auto; + transform: translateY(0); + } + } + } + } + + .#{iv.$class-prefix}navbar-menu { + flex-grow: 1; + flex-shrink: 0; + } + + .#{iv.$class-prefix}navbar-start { + justify-content: flex-start; + margin-inline-end: auto; + } + + .#{iv.$class-prefix}navbar-end { + justify-content: flex-end; + margin-inline-start: auto; + } + + .#{iv.$class-prefix}navbar-dropdown { + background-color: cv.getVar("navbar-dropdown-background-color"); + border-bottom-left-radius: cv.getVar("navbar-dropdown-radius"); + border-bottom-right-radius: cv.getVar("navbar-dropdown-radius"); + border-top-color: cv.getVar("navbar-dropdown-border-color"); + border-top-style: cv.getVar("navbar-dropdown-border-style"); + border-top-width: cv.getVar("navbar-dropdown-border-width"); + box-shadow: 0 0.5em 0.5em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.1 + ); + display: none; + font-size: 0.875rem; + inset-inline-start: 0; + min-width: 100%; + position: absolute; + top: 100%; + z-index: cv.getVar("navbar-dropdown-z"); + + .#{iv.$class-prefix}navbar-item { + padding: 0.375rem 1rem; + white-space: nowrap; + } + + a.#{iv.$class-prefix}navbar-item { + padding-inline-end: 3rem; + + &:not(.is-active, .is-selected) { + background-color: hsl( + #{cv.getVar("navbar-dropdown-item-h")}, + #{cv.getVar("navbar-dropdown-item-s")}, + calc( + #{cv.getVar("navbar-dropdown-item-background-l")} + #{cv.getVar( + "navbar-item-background-l-delta" + )} + ) + ); + color: hsl( + #{cv.getVar("navbar-dropdown-item-h")}, + #{cv.getVar("navbar-dropdown-item-s")}, + #{cv.getVar("navbar-dropdown-item-color-l")} + ); + } + } + + .#{iv.$class-prefix}navbar.#{iv.$class-prefix}is-spaced &, + &.#{iv.$class-prefix}is-boxed { + border-radius: cv.getVar("navbar-dropdown-boxed-radius"); + border-top: none; + box-shadow: cv.getVar("navbar-dropdown-boxed-shadow"); + display: block; + opacity: 0; + pointer-events: none; + top: calc(100% + (#{cv.getVar("navbar-dropdown-offset")})); + transform: translateY(-5px); + transition-duration: cv.getVar("duration"); + transition-property: opacity, transform; + } + + &.#{iv.$class-prefix}is-right { + left: auto; + right: 0; + } + } + + .#{iv.$class-prefix}navbar-divider { + display: block; + } + + .#{iv.$class-prefix}navbar > .#{iv.$class-prefix}container, + .#{iv.$class-prefix}container > .#{iv.$class-prefix}navbar { + .#{iv.$class-prefix}navbar-brand { + margin-inline-start: -0.75rem; + } + + .#{iv.$class-prefix}navbar-menu { + margin-inline-end: -0.75rem; + } + } + + // Fixed navbar + .#{iv.$class-prefix}navbar { + &.#{iv.$class-prefix}is-fixed-bottom-desktop, + &.#{iv.$class-prefix}is-fixed-top-desktop { + @include navbar-fixed; + } + + &.#{iv.$class-prefix}is-fixed-bottom-desktop { + bottom: 0; + + &.#{iv.$class-prefix}has-shadow { + box-shadow: 0 -0.125em 0.1875em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar( + "scheme-s" + )}, #{cv.getVar("scheme-invert-l")}, 0.1); + } + } + + &.#{iv.$class-prefix}is-fixed-top-desktop { + top: 0; + } + } + + html, + body { + &.#{iv.$class-prefix}has-navbar-fixed-top-desktop { + padding-top: cv.getVar("navbar-height"); + } + + &.#{iv.$class-prefix}has-navbar-fixed-bottom-desktop { + padding-bottom: cv.getVar("navbar-height"); + } + + &.#{iv.$class-prefix}has-spaced-navbar-fixed-top { + padding-top: calc( + #{cv.getVar("navbar-height")} + #{cv.getVar("navbar-padding-vertical")} * + 2 + ); + } + + &.#{iv.$class-prefix}has-spaced-navbar-fixed-bottom { + padding-bottom: calc( + #{cv.getVar("navbar-height")} + #{cv.getVar("navbar-padding-vertical")} * + 2 + ); + } + } +} + +// Combination + +.#{iv.$class-prefix}hero { + &.#{iv.$class-prefix}is-fullheight-with-navbar { + min-height: calc(100vh - #{cv.getVar("navbar-height")}); + } +} diff --git a/web/assets/css/sass/components/pagination.scss b/web/assets/css/sass/components/pagination.scss new file mode 100644 index 0000000..0634653 --- /dev/null +++ b/web/assets/css/sass/components/pagination.scss @@ -0,0 +1,379 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$pagination-margin: -0.25rem !default; +$pagination-min-width: cv.getVar("control-height") !default; + +$pagination-item-h: cv.getVar("scheme-h"); +$pagination-item-s: cv.getVar("scheme-s"); +$pagination-item-l: cv.getVar("scheme-main-l"); +$pagination-item-background-l-delta: 0%; +$pagination-item-hover-background-l-delta: cv.getVar( + "hover-background-l-delta" +); +$pagination-item-active-background-l-delta: cv.getVar( + "active-background-l-delta" +); +$pagination-item-border-l: cv.getVar("border-l"); +$pagination-item-border-l-delta: 0%; +$pagination-item-border-style: solid !default; +$pagination-item-border-width: cv.getVar("control-border-width") !default; +$pagination-item-hover-border-l-delta: cv.getVar("hover-border-l-delta"); +$pagination-item-active-border-l-delta: cv.getVar("active-border-l-delta"); +$pagination-item-focus-border-l-delta: cv.getVar("focus-border-l-delta"); +$pagination-item-color-l: cv.getVar("text-strong-l"); +$pagination-item-font-size: 1em !default; +$pagination-item-margin: 0.25rem !default; +$pagination-item-padding-left: 0.5em !default; +$pagination-item-padding-right: 0.5em !default; +$pagination-item-outer-shadow-h: 0; +$pagination-item-outer-shadow-s: 0%; +$pagination-item-outer-shadow-l: 20%; +$pagination-item-outer-shadow-a: 0.05; + +$pagination-selected-item-h: cv.getVar("link-h"); +$pagination-selected-item-s: cv.getVar("link-s"); +$pagination-selected-item-l: cv.getVar("link-l"); +$pagination-selected-item-background-l: cv.getVar("link-l"); +$pagination-selected-item-border-l: cv.getVar("link-l"); +$pagination-selected-item-color-l: cv.getVar("link-invert-l"); + +$pagination-nav-padding-left: 0.75em !default; +$pagination-nav-padding-right: 0.75em !default; + +$pagination-disabled-color: cv.getVar("text-weak") !default; +$pagination-disabled-background-color: cv.getVar("border") !default; +$pagination-disabled-border-color: cv.getVar("border") !default; + +$pagination-current-color: cv.getVar("link-invert") !default; +$pagination-current-background-color: cv.getVar("link") !default; +$pagination-current-border-color: cv.getVar("link") !default; + +$pagination-ellipsis-color: cv.getVar("text-weak") !default; + +$pagination-shadow-inset: inset 0 0.0625em 0.125em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.2 + ) !default; + +.#{iv.$class-prefix}pagination { + @include cv.register-vars( + ( + "pagination-margin": #{$pagination-margin}, + "pagination-min-width": #{$pagination-min-width}, + "pagination-item-h": #{$pagination-item-h}, + "pagination-item-s": #{$pagination-item-s}, + "pagination-item-l": #{$pagination-item-l}, + "pagination-item-background-l-delta": #{$pagination-item-background-l-delta}, + "pagination-item-hover-background-l-delta": #{$pagination-item-hover-background-l-delta}, + "pagination-item-active-background-l-delta": #{$pagination-item-active-background-l-delta}, + "pagination-item-border-style": #{$pagination-item-border-style}, + "pagination-item-border-width": #{$pagination-item-border-width}, + "pagination-item-border-l": #{$pagination-item-border-l}, + "pagination-item-border-l-delta": #{$pagination-item-border-l-delta}, + "pagination-item-hover-border-l-delta": #{$pagination-item-hover-border-l-delta}, + "pagination-item-active-border-l-delta": #{$pagination-item-active-border-l-delta}, + "pagination-item-focus-border-l-delta": #{$pagination-item-focus-border-l-delta}, + "pagination-item-color-l": #{$pagination-item-color-l}, + "pagination-item-font-size": #{$pagination-item-font-size}, + "pagination-item-margin": #{$pagination-item-margin}, + "pagination-item-padding-left": #{$pagination-item-padding-left}, + "pagination-item-padding-right": #{$pagination-item-padding-right}, + "pagination-item-outer-shadow-h": #{$pagination-item-outer-shadow-h}, + "pagination-item-outer-shadow-s": #{$pagination-item-outer-shadow-s}, + "pagination-item-outer-shadow-l": #{$pagination-item-outer-shadow-l}, + "pagination-item-outer-shadow-a": #{$pagination-item-outer-shadow-a}, + "pagination-nav-padding-left": #{$pagination-nav-padding-left}, + "pagination-nav-padding-right": #{$pagination-nav-padding-right}, + "pagination-disabled-color": #{$pagination-disabled-color}, + "pagination-disabled-background-color": #{$pagination-disabled-background-color}, + "pagination-disabled-border-color": #{$pagination-disabled-border-color}, + "pagination-current-color": #{$pagination-current-color}, + "pagination-current-background-color": #{$pagination-current-background-color}, + "pagination-current-border-color": #{$pagination-current-border-color}, + "pagination-ellipsis-color": #{$pagination-ellipsis-color}, + "pagination-shadow-inset": #{$pagination-shadow-inset}, + "pagination-selected-item-h": #{$pagination-selected-item-h}, + "pagination-selected-item-s": #{$pagination-selected-item-s}, + "pagination-selected-item-l": #{$pagination-selected-item-l}, + "pagination-selected-item-background-l": #{$pagination-selected-item-background-l}, + "pagination-selected-item-border-l": #{$pagination-selected-item-border-l}, + "pagination-selected-item-color-l": #{$pagination-selected-item-color-l}, + ) + ); +} + +.#{iv.$class-prefix}pagination { + @extend %block; + + font-size: cv.getVar("size-normal"); + margin: cv.getVar("pagination-margin"); + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } + + &.#{iv.$class-prefix}is-rounded { + .#{iv.$class-prefix}pagination-previous, + .#{iv.$class-prefix}pagination-next { + padding-left: 1em; + padding-right: 1em; + border-radius: cv.getVar("radius-rounded"); + } + + .#{iv.$class-prefix}pagination-link { + border-radius: cv.getVar("radius-rounded"); + } + } +} + +.#{iv.$class-prefix}pagination, +.#{iv.$class-prefix}pagination-list { + align-items: center; + display: flex; + justify-content: center; + text-align: center; +} + +.#{iv.$class-prefix}pagination-previous, +.#{iv.$class-prefix}pagination-next, +.#{iv.$class-prefix}pagination-link, +.#{iv.$class-prefix}pagination-ellipsis { + @extend %control; + @extend %unselectable; + color: hsl( + #{cv.getVar("pagination-item-h")}, + #{cv.getVar("pagination-item-s")}, + #{cv.getVar("pagination-item-color-l")} + ); + font-size: cv.getVar("pagination-item-font-size"); + justify-content: center; + margin: cv.getVar("pagination-item-margin"); + padding-left: cv.getVar("pagination-item-padding-left"); + padding-right: cv.getVar("pagination-item-padding-right"); + text-align: center; +} + +.#{iv.$class-prefix}pagination-previous, +.#{iv.$class-prefix}pagination-next, +.#{iv.$class-prefix}pagination-link { + background-color: hsl( + #{cv.getVar("pagination-item-h")}, + #{cv.getVar("pagination-item-s")}, + calc( + #{cv.getVar("pagination-item-background-l")} + #{cv.getVar( + "pagination-item-background-l-delta" + )} + ) + ); + border-color: hsl( + #{cv.getVar("pagination-item-h")}, + #{cv.getVar("pagination-item-s")}, + calc( + #{cv.getVar("pagination-item-border-l")} + #{cv.getVar( + "pagination-item-border-l-delta" + )} + ) + ); + border-style: cv.getVar("pagination-item-border-style"); + border-width: cv.getVar("pagination-item-border-width"); + box-shadow: + 0px 0.0625em 0.125em + hsla( + cv.getVar("pagination-item-outer-shadow-h"), + cv.getVar("pagination-item-outer-shadow-s"), + cv.getVar("pagination-item-outer-shadow-l"), + cv.getVar("pagination-item-outer-shadow-a") + ), + 0px 0.125em 0.25em + hsla( + cv.getVar("pagination-item-outer-shadow-h"), + cv.getVar("pagination-item-outer-shadow-s"), + cv.getVar("pagination-item-outer-shadow-l"), + cv.getVar("pagination-item-outer-shadow-a") + ); + color: hsl( + #{cv.getVar("pagination-item-h")}, + #{cv.getVar("pagination-item-s")}, + #{cv.getVar("pagination-item-color-l")} + ); + min-width: cv.getVar("pagination-min-width"); + transition-duration: cv.getVar("duration"); + transition-property: background-color, border-color, box-shadow, color; + + &:hover { + @include cv.register-vars( + ( + "pagination-item-background-l-delta": #{cv.getVar( + "pagination-item-hover-background-l-delta" + )}, + "pagination-item-border-l-delta": #{cv.getVar( + "pagination-item-hover-border-l-delta" + )}, + ) + ); + } + + &:focus { + @include cv.register-vars( + ( + "pagination-item-background-l-delta": #{cv.getVar( + "pagination-item-hover-background-l-delta" + )}, + "pagination-item-border-l-delta": #{cv.getVar( + "pagination-item-hover-border-l-delta" + )}, + ) + ); + } + + &:active { + box-shadow: cv.getVar("pagination-shadow-inset"); + } + + &[disabled], + &.#{iv.$class-prefix}is-disabled { + background-color: cv.getVar("pagination-disabled-background-color"); + border-color: cv.getVar("pagination-disabled-border-color"); + box-shadow: none; + color: cv.getVar("pagination-disabled-color"); + opacity: 0.5; + } +} + +.#{iv.$class-prefix}pagination-previous, +.#{iv.$class-prefix}pagination-next { + padding-left: cv.getVar("pagination-nav-padding-left"); + padding-right: cv.getVar("pagination-nav-padding-right"); + white-space: nowrap; +} + +.#{iv.$class-prefix}pagination-link { + &.#{iv.$class-prefix}is-current, + &.#{iv.$class-prefix}is-selected { + @include cv.register-vars( + ( + "pagination-item-h": #{cv.getVar("pagination-selected-item-h")}, + "pagination-item-s": #{cv.getVar("pagination-selected-item-s")}, + "pagination-item-l": #{cv.getVar("pagination-selected-item-l")}, + "pagination-item-background-l": #{cv.getVar( + "pagination-selected-item-background-l" + )}, + "pagination-item-border-l": #{cv.getVar( + "pagination-selected-item-border-l" + )}, + "pagination-item-color-l": #{cv.getVar( + "pagination-selected-item-color-l" + )}, + ) + ); + } +} + +.#{iv.$class-prefix}pagination-ellipsis { + color: cv.getVar("pagination-ellipsis-color"); + pointer-events: none; +} + +.#{iv.$class-prefix}pagination-list { + flex-wrap: wrap; + + li { + list-style: none; + } +} + +@include mx.mobile { + .#{iv.$class-prefix}pagination { + flex-wrap: wrap; + } + + .#{iv.$class-prefix}pagination-previous, + .#{iv.$class-prefix}pagination-next { + flex-grow: 1; + flex-shrink: 1; + } + + .#{iv.$class-prefix}pagination-list { + li { + flex-grow: 1; + flex-shrink: 1; + } + } +} + +@include mx.tablet { + .#{iv.$class-prefix}pagination-list { + flex-grow: 1; + flex-shrink: 1; + justify-content: flex-start; + order: 1; + } + + .#{iv.$class-prefix}pagination-previous, + .#{iv.$class-prefix}pagination-next, + .#{iv.$class-prefix}pagination-link, + .#{iv.$class-prefix}pagination-ellipsis { + margin-bottom: 0; + margin-top: 0; + } + + .#{iv.$class-prefix}pagination-previous { + order: 2; + } + + .#{iv.$class-prefix}pagination-next { + order: 3; + } + + .#{iv.$class-prefix}pagination { + justify-content: space-between; + margin-bottom: 0; + margin-top: 0; + + &.#{iv.$class-prefix}is-centered { + .#{iv.$class-prefix}pagination-previous { + order: 1; + } + + .#{iv.$class-prefix}pagination-list { + justify-content: center; + order: 2; + } + + .#{iv.$class-prefix}pagination-next { + order: 3; + } + } + + &.#{iv.$class-prefix}is-right { + .#{iv.$class-prefix}pagination-previous { + order: 1; + } + + .#{iv.$class-prefix}pagination-next { + order: 2; + } + + .#{iv.$class-prefix}pagination-list { + justify-content: flex-end; + order: 3; + } + } + } +} diff --git a/web/assets/css/sass/components/panel.scss b/web/assets/css/sass/components/panel.scss new file mode 100644 index 0000000..7d7d010 --- /dev/null +++ b/web/assets/css/sass/components/panel.scss @@ -0,0 +1,218 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$panel-margin: cv.getVar("block-spacing") !default; +$panel-item-border: 1px solid cv.getVar("border-weak") !default; +$panel-radius: cv.getVar("radius-large") !default; +$panel-shadow: cv.getVar("shadow") !default; + +$panel-heading-line-height: 1.25 !default; +$panel-heading-padding: 1em 1.25em !default; +$panel-heading-radius: cv.getVar("radius") !default; +$panel-heading-size: 1.25em !default; +$panel-heading-weight: cv.getVar("weight-bold") !default; + +$panel-tabs-font-size: 1em !default; +$panel-tab-border-bottom-color: cv.getVar("border") !default; +$panel-tab-border-bottom-style: solid !default; +$panel-tab-border-bottom-width: 1px !default; +$panel-tab-active-color: cv.getVar("link-active") !default; + +$panel-list-item-color: cv.getVar("text") !default; +$panel-list-item-hover-color: cv.getVar("link") !default; + +$panel-block-color: cv.getVar("text-strong") !default; +$panel-block-hover-background-color: cv.getVar("background") !default; +$panel-block-active-border-left-color: cv.getVar("link") !default; +$panel-block-active-color: cv.getVar("link-active") !default; +$panel-block-active-icon-color: cv.getVar("link") !default; + +$panel-icon-color: cv.getVar("text-weak") !default; +$panel-colors: dv.$colors !default; + +.#{iv.$class-prefix}panel { + @include cv.register-vars( + ( + "panel-margin": #{$panel-margin}, + "panel-item-border": #{$panel-item-border}, + "panel-radius": #{$panel-radius}, + "panel-shadow": #{$panel-shadow}, + "panel-heading-line-height": #{$panel-heading-line-height}, + "panel-heading-padding": #{$panel-heading-padding}, + "panel-heading-radius": #{$panel-heading-radius}, + "panel-heading-size": #{$panel-heading-size}, + "panel-heading-weight": #{$panel-heading-weight}, + "panel-tabs-font-size": #{$panel-tabs-font-size}, + "panel-tab-border-bottom-color": #{$panel-tab-border-bottom-color}, + "panel-tab-border-bottom-style": #{$panel-tab-border-bottom-style}, + "panel-tab-border-bottom-width": #{$panel-tab-border-bottom-width}, + "panel-tab-active-color": #{$panel-tab-active-color}, + "panel-list-item-color": #{$panel-list-item-color}, + "panel-list-item-hover-color": #{$panel-list-item-hover-color}, + "panel-block-color": #{$panel-block-color}, + "panel-block-hover-background-color": #{$panel-block-hover-background-color}, + "panel-block-active-border-left-color": #{$panel-block-active-border-left-color}, + "panel-block-active-color": #{$panel-block-active-color}, + "panel-block-active-icon-color": #{$panel-block-active-icon-color}, + "panel-icon-color": #{$panel-icon-color}, + ) + ); +} + +.#{iv.$class-prefix}panel { + @include cv.register-vars( + ( + "panel-h": #{cv.getVar("scheme-h")}, + "panel-s": #{cv.getVar("scheme-s")}, + "panel-color-l": #{cv.getVar("text-l")}, + "panel-heading-background-l": #{cv.getVar("text-l")}, + "panel-heading-color-l": #{cv.getVar("text-invert-l")}, + ) + ); + + border-radius: cv.getVar("panel-radius"); + box-shadow: cv.getVar("panel-shadow"); + font-size: cv.getVar("size-normal"); + + &:not(:last-child) { + margin-bottom: cv.getVar("panel-margin"); + } + + // Colors + @each $name, $components in $panel-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "panel-h": #{cv.getVar($name, "", "-h")}, + "panel-s": #{cv.getVar($name, "", "-s")}, + "panel-color-l": #{cv.getVar($name, "", "-l")}, + "panel-heading-background-l": #{cv.getVar($name, "", "-l")}, + "panel-heading-color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + } + } +} + +.#{iv.$class-prefix}panel-tabs, +.#{iv.$class-prefix}panel-block { + &:not(:last-child) { + border-bottom: cv.getVar("panel-item-border"); + } +} + +.#{iv.$class-prefix}panel-heading { + background-color: hsl( + cv.getVar("panel-h"), + cv.getVar("panel-s"), + cv.getVar("panel-heading-background-l") + ); + border-radius: cv.getVar("panel-radius") cv.getVar("panel-radius") 0 0; + color: hsl( + cv.getVar("panel-h"), + cv.getVar("panel-s"), + cv.getVar("panel-heading-color-l") + ); + font-size: cv.getVar("panel-heading-size"); + font-weight: cv.getVar("panel-heading-weight"); + line-height: cv.getVar("panel-heading-line-height"); + padding: cv.getVar("panel-heading-padding"); +} + +.#{iv.$class-prefix}panel-tabs { + align-items: flex-end; + display: flex; + font-size: cv.getVar("panel-tabs-font-size"); + justify-content: center; + + a { + border-bottom-color: cv.getVar("panel-tab-border-bottom-color"); + border-bottom-style: cv.getVar("panel-tab-border-bottom-style"); + border-bottom-width: cv.getVar("panel-tab-border-bottom-width"); + margin-bottom: calc(-1 * #{$panel-tab-border-bottom-width}); + padding: 0.75em; + + // Modifiers + &.#{iv.$class-prefix}is-active { + border-bottom-color: hsl( + cv.getVar("panel-h"), + cv.getVar("panel-s"), + cv.getVar("panel-color-l") + ); + color: cv.getVar("panel-tab-active-color"); + } + } +} + +.#{iv.$class-prefix}panel-list { + a { + color: cv.getVar("panel-list-item-color"); + + &:hover { + color: cv.getVar("panel-list-item-hover-color"); + } + } +} + +.#{iv.$class-prefix}panel-block { + align-items: center; + color: cv.getVar("panel-block-color"); + display: flex; + justify-content: flex-start; + padding: 0.75em 1em; + + input[type="checkbox"] { + margin-inline-end: 0.75em; + } + + & > .#{iv.$class-prefix}control { + flex-grow: 1; + flex-shrink: 1; + width: 100%; + } + + &.#{iv.$class-prefix}is-wrapped { + flex-wrap: wrap; + } + + &.#{iv.$class-prefix}is-active { + border-left-color: cv.getVar("panel-block-active-border-left-color"); + color: cv.getVar("panel-block-active-color"); + + .#{iv.$class-prefix}panel-icon { + color: hsl( + cv.getVar("panel-h"), + cv.getVar("panel-s"), + cv.getVar("panel-color-l") + ); + } + } + + &:last-child { + border-bottom-left-radius: cv.getVar("panel-radius"); + border-bottom-right-radius: cv.getVar("panel-radius"); + } +} + +a.#{iv.$class-prefix}panel-block, +label.#{iv.$class-prefix}panel-block { + cursor: pointer; + + &:hover { + background-color: cv.getVar("panel-block-hover-background-color"); + } +} + +.#{iv.$class-prefix}panel-icon { + @include mx.fa(1em, 1em); + color: cv.getVar("panel-icon-color"); + margin-inline-end: 0.75em; + + .#{iv.$class-prefix}fa { + font-size: inherit; + line-height: inherit; + } +} diff --git a/web/assets/css/sass/components/tabs.scss b/web/assets/css/sass/components/tabs.scss new file mode 100644 index 0000000..072282c --- /dev/null +++ b/web/assets/css/sass/components/tabs.scss @@ -0,0 +1,273 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$tabs-border-bottom-color: cv.getVar("border") !default; +$tabs-border-bottom-style: solid !default; +$tabs-border-bottom-width: 1px !default; +$tabs-link-color: cv.getVar("text") !default; +$tabs-link-hover-border-bottom-color: cv.getVar("text-strong") !default; +$tabs-link-hover-color: cv.getVar("text-strong") !default; +$tabs-link-active-border-bottom-color: cv.getVar("link-text") !default; +$tabs-link-active-color: cv.getVar("link-text") !default; +$tabs-link-padding: 0.5em 1em !default; + +$tabs-boxed-link-radius: cv.getVar("radius") !default; +$tabs-boxed-link-hover-background-color: cv.getVar("background") !default; +$tabs-boxed-link-hover-border-bottom-color: cv.getVar("border") !default; + +$tabs-boxed-link-active-background-color: cv.getVar("scheme-main") !default; +$tabs-boxed-link-active-border-color: cv.getVar("border") !default; +$tabs-boxed-link-active-border-bottom-color: transparent !default; + +$tabs-toggle-link-border-color: cv.getVar("border") !default; +$tabs-toggle-link-border-style: solid !default; +$tabs-toggle-link-border-width: 1px !default; +$tabs-toggle-link-hover-background-color: cv.getVar("background") !default; +$tabs-toggle-link-hover-border-color: cv.getVar("border-hover") !default; +$tabs-toggle-link-radius: cv.getVar("radius") !default; +$tabs-toggle-link-active-background-color: cv.getVar("link") !default; +$tabs-toggle-link-active-border-color: cv.getVar("link") !default; +$tabs-toggle-link-active-color: cv.getVar("link-invert") !default; + +.#{iv.$class-prefix}tabs { + @include cv.register-vars( + ( + "tabs-border-bottom-color": #{$tabs-border-bottom-color}, + "tabs-border-bottom-style": #{$tabs-border-bottom-style}, + "tabs-border-bottom-width": #{$tabs-border-bottom-width}, + "tabs-link-color": #{$tabs-link-color}, + "tabs-link-hover-border-bottom-color": #{$tabs-link-hover-border-bottom-color}, + "tabs-link-hover-color": #{$tabs-link-hover-color}, + "tabs-link-active-border-bottom-color": #{$tabs-link-active-border-bottom-color}, + "tabs-link-active-color": #{$tabs-link-active-color}, + "tabs-link-padding": #{$tabs-link-padding}, + "tabs-boxed-link-radius": #{$tabs-boxed-link-radius}, + "tabs-boxed-link-hover-background-color": #{$tabs-boxed-link-hover-background-color}, + "tabs-boxed-link-hover-border-bottom-color": #{$tabs-boxed-link-hover-border-bottom-color}, + "tabs-boxed-link-active-background-color": #{$tabs-boxed-link-active-background-color}, + "tabs-boxed-link-active-border-color": #{$tabs-boxed-link-active-border-color}, + "tabs-boxed-link-active-border-bottom-color": #{$tabs-boxed-link-active-border-bottom-color}, + "tabs-toggle-link-border-color": #{$tabs-toggle-link-border-color}, + "tabs-toggle-link-border-style": #{$tabs-toggle-link-border-style}, + "tabs-toggle-link-border-width": #{$tabs-toggle-link-border-width}, + "tabs-toggle-link-hover-background-color": #{$tabs-toggle-link-hover-background-color}, + "tabs-toggle-link-hover-border-color": #{$tabs-toggle-link-hover-border-color}, + "tabs-toggle-link-radius": #{$tabs-toggle-link-radius}, + "tabs-toggle-link-active-background-color": #{$tabs-toggle-link-active-background-color}, + "tabs-toggle-link-active-border-color": #{$tabs-toggle-link-active-border-color}, + "tabs-toggle-link-active-color": #{$tabs-toggle-link-active-color}, + ) + ); +} + +.#{iv.$class-prefix}tabs { + @extend %block; + @extend %unselectable; + @include mx.overflow-touch; + align-items: stretch; + display: flex; + font-size: cv.getVar("size-normal"); + justify-content: space-between; + overflow: hidden; + overflow-x: auto; + white-space: nowrap; + + a { + align-items: center; + border-bottom-color: cv.getVar("tabs-border-bottom-color"); + border-bottom-style: cv.getVar("tabs-border-bottom-style"); + border-bottom-width: cv.getVar("tabs-border-bottom-width"); + color: cv.getVar("tabs-link-color"); + display: flex; + justify-content: center; + margin-bottom: calc(-1 * #{cv.getVar("tabs-border-bottom-width")}); + padding: cv.getVar("tabs-link-padding"); + transition-duration: cv.getVar("duration"); + transition-property: background-color, border-color, color; + vertical-align: top; + + &:hover { + border-bottom-color: cv.getVar("tabs-link-hover-border-bottom-color"); + color: cv.getVar("tabs-link-hover-color"); + } + } + + li { + display: block; + + &.#{iv.$class-prefix}is-active { + a { + border-bottom-color: cv.getVar("tabs-link-active-border-bottom-color"); + color: cv.getVar("tabs-link-active-color"); + } + } + } + + ul { + align-items: center; + border-bottom-color: cv.getVar("tabs-border-bottom-color"); + border-bottom-style: cv.getVar("tabs-border-bottom-style"); + border-bottom-width: cv.getVar("tabs-border-bottom-width"); + display: flex; + flex-grow: 1; + flex-shrink: 0; + justify-content: flex-start; + + &.#{iv.$class-prefix}is-left { + padding-right: 0.75em; + } + + &.#{iv.$class-prefix}is-center { + flex: none; + justify-content: center; + padding-left: 0.75em; + padding-right: 0.75em; + } + + &.#{iv.$class-prefix}is-right { + justify-content: flex-end; + padding-left: 0.75em; + } + } + + .#{iv.$class-prefix}icon { + &:first-child { + margin-inline-end: 0.5em; + } + + &:last-child { + margin-inline-start: 0.5em; + } + } + + // Alignment + &.#{iv.$class-prefix}is-centered { + ul { + justify-content: center; + } + } + + &.#{iv.$class-prefix}is-right { + ul { + justify-content: flex-end; + } + } + + // Styles + &.#{iv.$class-prefix}is-boxed { + a { + border: 1px solid transparent; + border-start-start-radius: cv.getVar("tabs-boxed-link-radius"); + border-start-end-radius: cv.getVar("tabs-boxed-link-radius"); + + &:hover { + background-color: cv.getVar("tabs-boxed-link-hover-background-color"); + border-bottom-color: cv.getVar( + "tabs-boxed-link-hover-border-bottom-color" + ); + } + } + + li { + &.#{iv.$class-prefix}is-active { + a { + background-color: cv.getVar( + "tabs-boxed-link-active-background-color" + ); + border-color: cv.getVar("tabs-boxed-link-active-border-color"); + border-bottom-color: cv.getVar( + "tabs-boxed-link-active-border-bottom-color" + ) !important; + } + } + } + } + + &.#{iv.$class-prefix}is-fullwidth { + li { + flex-grow: 1; + flex-shrink: 0; + } + } + + &.#{iv.$class-prefix}is-toggle { + a { + border-color: cv.getVar("tabs-toggle-link-border-color"); + border-style: cv.getVar("tabs-toggle-link-border-style"); + border-width: cv.getVar("tabs-toggle-link-border-width"); + margin-bottom: 0; + position: relative; + + &:hover { + background-color: cv.getVar("tabs-toggle-link-hover-background-color"); + border-color: cv.getVar("tabs-toggle-link-hover-border-color"); + z-index: 2; + } + } + + li { + & + li { + margin-inline-start: calc( + -1 * #{cv.getVar("tabs-toggle-link-border-width")} + ); + } + + &:first-child a { + border-start-start-radius: cv.getVar("tabs-toggle-link-radius"); + border-end-start-radius: cv.getVar("tabs-toggle-link-radius"); + } + + &:last-child a { + border-start-end-radius: cv.getVar("tabs-toggle-link-radius"); + border-end-end-radius: cv.getVar("tabs-toggle-link-radius"); + } + + &.#{iv.$class-prefix}is-active { + a { + background-color: cv.getVar( + "tabs-toggle-link-active-background-color" + ); + border-color: cv.getVar("tabs-toggle-link-active-border-color"); + color: cv.getVar("tabs-toggle-link-active-color"); + z-index: 1; + } + } + } + + ul { + border-bottom: none; + } + + &.#{iv.$class-prefix}is-toggle-rounded { + li { + &:first-child a { + border-start-start-radius: cv.getVar("radius-rounded"); + border-end-start-radius: cv.getVar("radius-rounded"); + padding-inline-start: 1.25em; + } + + &:last-child a { + border-start-end-radius: cv.getVar("radius-rounded"); + border-end-end-radius: cv.getVar("radius-rounded"); + padding-inline-end: 1.25em; + } + } + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } +} diff --git a/web/assets/css/sass/elements/_index.scss b/web/assets/css/sass/elements/_index.scss new file mode 100644 index 0000000..68034bf --- /dev/null +++ b/web/assets/css/sass/elements/_index.scss @@ -0,0 +1,16 @@ +/* Bulma Elements */ +@charset "utf-8"; + +@forward "block"; +@forward "box"; +@forward "button"; +@forward "content"; +@forward "delete"; +@forward "icon"; +@forward "image"; +@forward "loader"; +@forward "notification"; +@forward "progress"; +@forward "table"; +@forward "tag"; +@forward "title"; diff --git a/web/assets/css/sass/elements/block.scss b/web/assets/css/sass/elements/block.scss new file mode 100644 index 0000000..34fee01 --- /dev/null +++ b/web/assets/css/sass/elements/block.scss @@ -0,0 +1,6 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; + +.#{iv.$class-prefix}block { + @extend %block; +} diff --git a/web/assets/css/sass/elements/box.scss b/web/assets/css/sass/elements/box.scss new file mode 100644 index 0000000..060f53a --- /dev/null +++ b/web/assets/css/sass/elements/box.scss @@ -0,0 +1,59 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; + +$box-background-color: cv.getVar("scheme-main") !default; +$box-color: cv.getVar("text") !default; +$box-radius: cv.getVar("radius-large") !default; +$box-shadow: cv.getVar("shadow") !default; +$box-padding: 1.25rem !default; + +$box-link-hover-shadow: + 0 0.5em 1em -0.125em hsla(#{cv.getVar("scheme-h")}, #{cv.getVar("scheme-s")}, #{cv.getVar( + "scheme-invert-l" + )}, 0.1), + 0 0 0 1px cv.getVar("link") !default; +$box-link-active-shadow: + inset 0 1px 2px + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.2 + ), + 0 0 0 1px cv.getVar("link") !default; + +.#{iv.$class-prefix}box { + @include cv.register-vars( + ( + "box-background-color": #{$box-background-color}, + "box-color": #{$box-color}, + "box-radius": #{$box-radius}, + "box-shadow": #{$box-shadow}, + "box-padding": #{$box-padding}, + "box-link-hover-shadow": #{$box-link-hover-shadow}, + "box-link-active-shadow": #{$box-link-active-shadow}, + ) + ); +} + +.#{iv.$class-prefix}box { + @extend %block; + background-color: cv.getVar("box-background-color"); + border-radius: cv.getVar("box-radius"); + box-shadow: cv.getVar("box-shadow"); + color: cv.getVar("box-color"); + display: block; + padding: cv.getVar("box-padding"); +} + +a.#{iv.$class-prefix}box { + &:hover, + &:focus { + box-shadow: cv.getVar("box-link-hover-shadow"); + } + + &:active { + box-shadow: cv.getVar("box-link-active-shadow"); + } +} diff --git a/web/assets/css/sass/elements/button.scss b/web/assets/css/sass/elements/button.scss new file mode 100644 index 0000000..f8d3ba8 --- /dev/null +++ b/web/assets/css/sass/elements/button.scss @@ -0,0 +1,640 @@ +@use "sass:list"; + +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$button-h: #{cv.getVar("scheme-h")}; +$button-s: #{cv.getVar("scheme-s")}; +$button-l: #{cv.getVar("scheme-main-l")}; +$button-background-l: #{cv.getVar("scheme-main-l")}; +$button-background-l-delta: 0%; +$button-hover-background-l-delta: #{cv.getVar("hover-background-l-delta")}; +$button-active-background-l-delta: #{cv.getVar("active-background-l-delta")}; +$button-color-l: #{cv.getVar("text-strong-l")}; +$button-border-l: #{cv.getVar("border-l")}; +$button-border-l-delta: 0%; +$button-hover-border-l-delta: #{cv.getVar("hover-border-l-delta")}; +$button-active-border-l-delta: #{cv.getVar("active-border-l-delta")}; +$button-focus-border-l-delta: #{cv.getVar("focus-border-l-delta")}; +$button-outer-shadow-h: 0; +$button-outer-shadow-s: 0%; +$button-outer-shadow-l: 20%; +$button-outer-shadow-a: 0.05; + +$button-weight: cv.getVar("weight-medium") !default; +$button-family: false !default; + +$button-border-color: cv.getVar("border") !default; +$button-border-style: solid !default; +$button-border-width: cv.getVar("control-border-width") !default; + +$button-padding-vertical: 0.5em !default; +$button-padding-horizontal: 1em !default; + +$button-focus-border-color: cv.getVar("link-focus-border") !default; +$button-focus-box-shadow-size: 0 0 0 0.125em !default; +$button-focus-box-shadow-color: hsla( + #{cv.getVar("link-h")}, + #{cv.getVar("link-s")}, + #{cv.getVar("link-on-scheme-l")}, + 0.25 +) !default; + +$button-active-color: cv.getVar("link-active") !default; +$button-active-border-color: cv.getVar("link-active-border") !default; + +$button-text-color: cv.getVar("text") !default; +$button-text-decoration: underline !default; +$button-text-hover-background-color: cv.getVar("background") !default; +$button-text-hover-color: cv.getVar("text-strong") !default; + +$button-ghost-background: none !default; +$button-ghost-border-color: transparent !default; +$button-ghost-color: cv.getVar("link-text") !default; +$button-ghost-decoration: none !default; +$button-ghost-hover-color: cv.getVar("link") !default; +$button-ghost-hover-decoration: underline !default; + +$button-disabled-background-color: cv.getVar("scheme-main") !default; +$button-disabled-border-color: cv.getVar("border") !default; +$button-disabled-shadow: none !default; +$button-disabled-opacity: 0.5 !default; + +$button-static-color: cv.getVar("text-weak") !default; +$button-static-background-color: cv.getVar("scheme-main-ter") !default; +$button-static-border-color: cv.getVar("border") !default; + +$button-colors: dv.$colors !default; +$button-responsive-sizes: ( + "mobile": ( + "small": calc(#{cv.getVar("size-small")} * 0.75), + "normal": calc(#{cv.getVar("size-small")} * 0.875), + "medium": cv.getVar("size-small"), + "large": cv.getVar("size-normal"), + ), + "tablet-only": ( + "small": calc(#{cv.getVar("size-small")} * 0.875), + "normal": cv.getVar("size-small"), + "medium": cv.getVar("size-normal"), + "large": cv.getVar("size-medium"), + ), +) !default; + +$no-palette: ("white", "black", "light", "dark"); + +.#{iv.$class-prefix}button { + @include cv.register-vars( + ( + "button-family": #{$button-family}, + "button-weight": #{$button-weight}, + "button-border-color": #{$button-border-color}, + "button-border-style": #{$button-border-style}, + "button-border-width": #{$button-border-width}, + "button-padding-vertical": #{$button-padding-vertical}, + "button-padding-horizontal": #{$button-padding-horizontal}, + "button-focus-border-color": #{$button-focus-border-color}, + "button-focus-box-shadow-size": #{$button-focus-box-shadow-size}, + "button-focus-box-shadow-color": #{$button-focus-box-shadow-color}, + "button-active-color": #{$button-active-color}, + "button-active-border-color": #{$button-active-border-color}, + "button-text-color": #{$button-text-color}, + "button-text-decoration": #{$button-text-decoration}, + "button-text-hover-background-color": #{$button-text-hover-background-color}, + "button-text-hover-color": #{$button-text-hover-color}, + "button-ghost-background": #{$button-ghost-background}, + "button-ghost-border-color": #{$button-ghost-border-color}, + "button-ghost-color": #{$button-ghost-color}, + "button-ghost-decoration": #{$button-ghost-decoration}, + "button-ghost-hover-color": #{$button-ghost-hover-color}, + "button-ghost-hover-decoration": #{$button-ghost-hover-decoration}, + "button-disabled-background-color": #{$button-disabled-background-color}, + "button-disabled-border-color": #{$button-disabled-border-color}, + "button-disabled-shadow": #{$button-disabled-shadow}, + "button-disabled-opacity": #{$button-disabled-opacity}, + "button-static-color": #{$button-static-color}, + "button-static-background-color": #{$button-static-background-color}, + "button-static-border-color": #{$button-static-border-color}, + ) + ); +} + +.#{iv.$class-prefix}button { + @include cv.register-vars( + ( + "button-h": #{$button-h}, + "button-s": #{$button-s}, + "button-l": #{$button-l}, + "button-background-l": #{$button-background-l}, + "button-background-l-delta": #{$button-background-l-delta}, + "button-hover-background-l-delta": #{$button-hover-background-l-delta}, + "button-active-background-l-delta": #{$button-active-background-l-delta}, + "button-color-l": #{$button-color-l}, + "button-border-l": #{$button-border-l}, + "button-border-l-delta": #{$button-border-l-delta}, + "button-hover-border-l-delta": #{$button-hover-border-l-delta}, + "button-active-border-l-delta": #{$button-active-border-l-delta}, + "button-focus-border-l-delta": #{$button-focus-border-l-delta}, + "button-outer-shadow-h": #{$button-outer-shadow-h}, + "button-outer-shadow-s": #{$button-outer-shadow-s}, + "button-outer-shadow-l": #{$button-outer-shadow-l}, + "button-outer-shadow-a": #{$button-outer-shadow-a}, + "loading-color": + hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + #{cv.getVar("button-color-l")} + ), + ) + ); + + @extend %control; + @extend %unselectable; + + background-color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + calc( + #{cv.getVar("button-background-l")} + #{cv.getVar( + "button-background-l-delta" + )} + ) + ); + border-color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + calc( + #{cv.getVar("button-border-l")} + #{cv.getVar("button-border-l-delta")} + ) + ); + border-style: cv.getVar("button-border-style"); + border-width: cv.getVar("button-border-width"); + box-shadow: + 0px 0.0625em 0.125em + hsla( + cv.getVar("button-outer-shadow-h"), + cv.getVar("button-outer-shadow-s"), + cv.getVar("button-outer-shadow-l"), + cv.getVar("button-outer-shadow-a") + ), + 0px 0.125em 0.25em + hsla( + cv.getVar("button-outer-shadow-h"), + cv.getVar("button-outer-shadow-s"), + cv.getVar("button-outer-shadow-l"), + cv.getVar("button-outer-shadow-a") + ); + color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + #{cv.getVar("button-color-l")} + ); + cursor: pointer; + font-weight: cv.getVar("button-weight"); + height: auto; + justify-content: center; + padding-bottom: calc( + #{cv.getVar("button-padding-vertical")} - #{cv.getVar( + "button-border-width" + )} + ); + padding-left: calc( + #{cv.getVar("button-padding-horizontal")} - #{cv.getVar( + "button-border-width" + )} + ); + padding-right: calc( + #{cv.getVar("button-padding-horizontal")} - #{cv.getVar( + "button-border-width" + )} + ); + padding-top: calc( + #{cv.getVar("button-padding-vertical")} - #{cv.getVar( + "button-border-width" + )} + ); + text-align: center; + white-space: nowrap; + + @if $button-family { + font-family: cv.getVar("button-family"); + } + + strong { + color: inherit; + } + + .#{iv.$class-prefix}icon { + &, + &.#{iv.$class-prefix}is-small, + &.#{iv.$class-prefix}is-medium, + &.#{iv.$class-prefix}is-large { + height: 1.5em; + width: 1.5em; + } + + &:first-child:not(:last-child) { + margin-inline-start: calc( + -0.5 * #{cv.getVar("button-padding-horizontal")} + ); + margin-inline-end: calc(#{cv.getVar("button-padding-horizontal")} * 0.25); + } + + &:last-child:not(:first-child) { + margin-inline-start: calc( + #{cv.getVar("button-padding-horizontal")} * 0.25 + ); + margin-inline-end: calc(-0.5 * #{cv.getVar("button-padding-horizontal")}); + } + + &:first-child:last-child { + margin-inline-start: calc( + -0.5 * #{cv.getVar("button-padding-horizontal")} + ); + margin-inline-end: calc(-0.5 * #{cv.getVar("button-padding-horizontal")}); + } + } + + // States + &:hover, + &.#{iv.$class-prefix}is-hovered { + @include cv.register-vars( + ( + "button-background-l-delta": #{cv.getVar( + "button-hover-background-l-delta" + )}, + "button-border-l-delta": #{cv.getVar("button-hover-border-l-delta")}, + ) + ); + } + + &:focus-visible, + &.#{iv.$class-prefix}is-focused { + @include cv.register-var("button-border-width", 1px); + + border-color: hsl( + #{cv.getVar("focus-h")}, + #{cv.getVar("focus-s")}, + #{cv.getVar("focus-l")} + ); + box-shadow: cv.getVar("focus-shadow-size") + hsla( + cv.getVar("focus-h"), + cv.getVar("focus-s"), + cv.getVar("focus-l"), + cv.getVar("focus-shadow-alpha") + ); + } + + &:active, + &.#{iv.$class-prefix}is-active { + @include cv.register-vars( + ( + "button-background-l-delta": #{cv.getVar( + "button-active-background-l-delta" + )}, + "button-border-l-delta": #{cv.getVar("button-active-border-l-delta")}, + "button-outer-shadow-a": 0, + ) + ); + } + + &[disabled], + fieldset[disabled] & { + background-color: cv.getVar("button-disabled-background-color"); + border-color: cv.getVar("button-disabled-border-color"); + box-shadow: cv.getVar("button-disabled-shadow"); + opacity: cv.getVar("button-disabled-opacity"); + } + + // Colors + @each $name, $pair in $button-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "button-h": #{cv.getVar($name, "", "-h")}, + "button-s": #{cv.getVar($name, "", "-s")}, + "button-l": #{cv.getVar($name, "", "-l")}, + "button-background-l": #{cv.getVar($name, "", "-l")}, + "button-border-l": #{cv.getVar($name, "", "-l")}, + "button-border-width": 0px, + "button-color-l": #{cv.getVar($name, "", "-invert-l")}, + "button-outer-shadow-a": 0, + ) + ); + + &:focus-visible, + &.#{iv.$class-prefix}is-focused { + @include cv.register-var("button-border-width", 1px); + } + + @if not list.index($no-palette, $name) { + &.#{iv.$class-prefix}is-light { + @include cv.register-vars( + ( + "button-background-l": #{cv.getVar("light-l")}, + "button-color-l": #{cv.getVar($name, "", "-light-invert-l")}, + ) + ); + } + + &.#{iv.$class-prefix}is-dark { + @include cv.register-vars( + ( + "button-background-l": #{cv.getVar("dark-l")}, + "button-color-l": #{cv.getVar($name, "", "-dark-invert-l")}, + ) + ); + } + } + + &.#{iv.$class-prefix}is-soft { + @include cv.register-vars( + ( + "button-background-l": #{cv.getVar("soft-l")}, + "button-color-l": #{cv.getVar("soft-invert-l")}, + ) + ); + } + + &.#{iv.$class-prefix}is-bold { + @include cv.register-vars( + ( + "button-background-l": #{cv.getVar("bold-l")}, + "button-color-l": #{cv.getVar("bold-invert-l")}, + ) + ); + } + + &[disabled], + fieldset[disabled] & { + background-color: cv.getVar($name); + border-color: cv.getVar($name); + box-shadow: none; + } + } + } + + // Styles + &.#{iv.$class-prefix}is-outlined { + @include cv.register-vars( + ( + "button-border-width": max(1px, 0.0625em), + ) + ); + + background-color: transparent; + border-color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + #{cv.getVar("button-l")} + ); + color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + #{cv.getVar("button-l")} + ); + + &:hover { + @include cv.register-vars( + ( + "button-border-width": max(2px, 0.125em), + "button-outer-shadow-alpha": 1, + ) + ); + } + + &:active { + @include cv.register-vars(()); + } + } + + &.#{iv.$class-prefix}is-inverted { + background-color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + calc( + #{cv.getVar("button-color-l")} + #{cv.getVar( + "button-background-l-delta" + )} + ) + ); + color: hsl( + #{cv.getVar("button-h")}, + #{cv.getVar("button-s")}, + #{cv.getVar("button-background-l")} + ); + } + + &.#{iv.$class-prefix}is-text { + background-color: transparent; + border-color: transparent; + color: cv.getVar("button-text-color"); + text-decoration: cv.getVar("button-text-decoration"); + + &:hover, + &.#{iv.$class-prefix}is-hovered { + background-color: cv.getVar("button-text-hover-background-color"); + color: cv.getVar("button-text-hover-color"); + } + + &:active, + &.#{iv.$class-prefix}is-active { + // background-color: bulmaDarken($button-text-hover-background-color, 5%); + color: cv.getVar("button-text-hover-color"); + } + + &[disabled], + fieldset[disabled] & { + background-color: transparent; + border-color: transparent; + box-shadow: none; + } + } + + &.#{iv.$class-prefix}is-ghost { + background: cv.getVar("button-ghost-background"); + border-color: cv.getVar("button-ghost-border-color"); + box-shadow: none; + color: cv.getVar("button-ghost-color"); + text-decoration: cv.getVar("button-ghost-decoration"); + + &:hover, + &.#{iv.$class-prefix}is-hovered { + color: cv.getVar("button-ghost-hover-color"); + text-decoration: cv.getVar("button-ghost-hover-decoration"); + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-small")}, + "control-radius": #{cv.getVar("radius-small")}, + ) + ); + } + + &.#{iv.$class-prefix}is-normal { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-normal")}, + "control-radius": #{cv.getVar("radius")}, + ) + ); + } + + &.#{iv.$class-prefix}is-medium { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-medium")}, + "control-radius": #{cv.getVar("radius-medium")}, + ) + ); + } + + &.#{iv.$class-prefix}is-large { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-large")}, + "control-radius": #{cv.getVar("radius-medium")}, + ) + ); + } + + // Modifiers + &.#{iv.$class-prefix}is-fullwidth { + display: flex; + width: 100%; + } + + &.#{iv.$class-prefix}is-loading { + box-shadow: none; + color: transparent !important; + pointer-events: none; + + &::after { + @extend %loader; + @include mx.center(1em); + position: absolute !important; + } + } + + &.#{iv.$class-prefix}is-static { + background-color: cv.getVar("button-static-background-color"); + border-color: cv.getVar("button-static-border-color"); + color: cv.getVar("button-static-color"); + box-shadow: none; + pointer-events: none; + } + + &.#{iv.$class-prefix}is-rounded { + border-radius: cv.getVar("radius-rounded"); + padding-left: calc(#{cv.getVar("button-padding-horizontal")} + 0.25em); + padding-right: calc(#{cv.getVar("button-padding-horizontal")} + 0.25em); + } +} + +.#{iv.$class-prefix}buttons { + @extend %block; + align-items: center; + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + justify-content: flex-start; + + // Sizes + &.#{iv.$class-prefix}are-small { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-small")}, + "control-radius": #{cv.getVar("radius-small")}, + ) + ); + } + + &.#{iv.$class-prefix}are-medium { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-medium")}, + "control-radius": #{cv.getVar("radius-medium")}, + ) + ); + } + + &.#{iv.$class-prefix}are-large { + @include cv.register-vars( + ( + "control-size": #{cv.getVar("size-large")}, + "control-radius": #{cv.getVar("radius-large")}, + ) + ); + } + + &.#{iv.$class-prefix}has-addons { + gap: 0; + + .#{iv.$class-prefix}button { + &:not(:first-child) { + border-end-start-radius: 0; + border-start-start-radius: 0; + } + + &:not(:last-child) { + border-end-end-radius: 0; + border-start-end-radius: 0; + margin-inline-end: -1px; + } + + &:hover, + &.#{iv.$class-prefix}is-hovered { + z-index: 2; + } + + &:focus, + &.#{iv.$class-prefix}is-focused, + &:active, + &.#{iv.$class-prefix}is-active, + &.#{iv.$class-prefix}is-selected { + z-index: 3; + + &:hover { + z-index: 4; + } + } + + &.#{iv.$class-prefix}is-expanded { + flex-grow: 1; + flex-shrink: 1; + } + } + } + + &.#{iv.$class-prefix}is-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}is-right { + justify-content: flex-end; + } +} + +@each $bp-name, $bp-sizes in $button-responsive-sizes { + @include mx.breakpoint($bp-name) { + @each $size, $value in $bp-sizes { + @if $size != "normal" { + .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive.#{iv.$class-prefix}is-#{$size} { + font-size: $value; + } + } @else { + .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive, + .#{iv.$class-prefix}button.#{iv.$class-prefix}is-responsive.#{iv.$class-prefix}is-normal { + font-size: $value; + } + } + } + } +} diff --git a/web/assets/css/sass/elements/content.scss b/web/assets/css/sass/elements/content.scss new file mode 100644 index 0000000..4acfa08 --- /dev/null +++ b/web/assets/css/sass/elements/content.scss @@ -0,0 +1,283 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$content-heading-color: #{cv.getVar("text-strong")} !default; +$content-heading-weight: #{cv.getVar("weight-extrabold")} !default; +$content-heading-line-height: 1.125 !default; + +$content-block-margin-bottom: 1em !default; + +$content-blockquote-background-color: #{cv.getVar("background")} !default; +$content-blockquote-border-left: 5px solid #{cv.getVar("border")} !default; +$content-blockquote-padding: 1.25em 1.5em !default; + +$content-pre-padding: 1.25em 1.5em !default; + +$content-table-cell-border: 1px solid #{cv.getVar("border")} !default; +$content-table-cell-border-width: 0 0 1px !default; +$content-table-cell-padding: 0.5em 0.75em !default; +$content-table-cell-heading-color: #{cv.getVar("text-strong")} !default; +$content-table-head-cell-border-width: 0 0 2px !default; +$content-table-head-cell-color: #{cv.getVar("text-strong")} !default; +$content-table-body-last-row-cell-border-bottom-width: 0 !default; +$content-table-foot-cell-border-width: 2px 0 0 !default; +$content-table-foot-cell-color: #{cv.getVar("text-strong")} !default; + +.#{iv.$class-prefix}content { + @include cv.register-vars( + ( + "content-heading-color": #{$content-heading-color}, + "content-heading-weight": #{$content-heading-weight}, + "content-heading-line-height": #{$content-heading-line-height}, + "content-block-margin-bottom": #{$content-block-margin-bottom}, + "content-blockquote-background-color": #{$content-blockquote-background-color}, + "content-blockquote-border-left": #{$content-blockquote-border-left}, + "content-blockquote-padding": #{$content-blockquote-padding}, + "content-pre-padding": #{$content-pre-padding}, + "content-table-cell-border": #{$content-table-cell-border}, + "content-table-cell-border-width": #{$content-table-cell-border-width}, + "content-table-cell-padding": #{$content-table-cell-padding}, + "content-table-cell-heading-color": #{$content-table-cell-heading-color}, + "content-table-head-cell-border-width": #{$content-table-head-cell-border-width}, + "content-table-head-cell-color": #{$content-table-head-cell-color}, + "content-table-body-last-row-cell-border-bottom-width": #{$content-table-body-last-row-cell-border-bottom-width}, + "content-table-foot-cell-border-width": #{$content-table-foot-cell-border-width}, + "content-table-foot-cell-color": #{$content-table-foot-cell-color}, + ) + ); +} + +.#{iv.$class-prefix}content { + @extend %block; + + // Inline + li + li { + margin-top: 0.25em; + } + + // Block + p, + dl, + ol, + ul, + blockquote, + pre, + table { + &:not(:last-child) { + margin-bottom: cv.getVar("content-block-margin-bottom"); + } + } + + h1, + h2, + h3, + h4, + h5, + h6 { + color: cv.getVar("content-heading-color"); + font-weight: cv.getVar("content-heading-weight"); + line-height: cv.getVar("content-heading-line-height"); + } + + h1 { + font-size: 2em; + margin-bottom: 0.5em; + + &:not(:first-child) { + margin-top: 1em; + } + } + + h2 { + font-size: 1.75em; + margin-bottom: 0.5714em; + + &:not(:first-child) { + margin-top: 1.1428em; + } + } + + h3 { + font-size: 1.5em; + margin-bottom: 0.6666em; + + &:not(:first-child) { + margin-top: 1.3333em; + } + } + + h4 { + font-size: 1.25em; + margin-bottom: 0.8em; + } + + h5 { + font-size: 1.125em; + margin-bottom: 0.8888em; + } + + h6 { + font-size: 1em; + margin-bottom: 1em; + } + + blockquote { + background-color: cv.getVar("content-blockquote-background-color"); + border-inline-start: cv.getVar("content-blockquote-border-left"); + padding: cv.getVar("content-blockquote-padding"); + } + + ol { + list-style-position: outside; + margin-inline-start: 2em; + margin-top: 1em; + + &:not([type]) { + list-style-type: decimal; + + &.#{iv.$class-prefix}is-lower-alpha { + list-style-type: lower-alpha; + } + + &.#{iv.$class-prefix}is-lower-roman { + list-style-type: lower-roman; + } + + &.#{iv.$class-prefix}is-upper-alpha { + list-style-type: upper-alpha; + } + + &.#{iv.$class-prefix}is-upper-roman { + list-style-type: upper-roman; + } + } + } + + ul { + list-style: disc outside; + margin-inline-start: 2em; + margin-top: 1em; + + ul { + list-style-type: circle; + margin-bottom: 0.25em; + margin-top: 0.25em; + + ul { + list-style-type: square; + } + } + } + + dd { + margin-inline-start: 2em; + } + + figure:not([class]) { + margin-left: 2em; + margin-right: 2em; + text-align: center; + + &:not(:first-child) { + margin-top: 2em; + } + + &:not(:last-child) { + margin-bottom: 2em; + } + + img { + display: inline-block; + } + + figcaption { + font-style: italic; + } + } + + pre { + @include mx.overflow-touch; + overflow-x: auto; + padding: cv.getVar("content-pre-padding"); + white-space: pre; + word-wrap: normal; + } + + sup, + sub { + font-size: 75%; + } + + table { + td, + th { + border: cv.getVar("content-table-cell-border"); + border-width: cv.getVar("content-table-cell-border-width"); + padding: cv.getVar("content-table-cell-padding"); + vertical-align: top; + } + + th { + color: cv.getVar("content-table-cell-heading-color"); + + &:not([align]) { + text-align: inherit; + } + } + + thead { + td, + th { + border-width: cv.getVar("content-table-head-cell-border-width"); + color: cv.getVar("content-table-head-cell-color"); + } + } + + tfoot { + td, + th { + border-width: cv.getVar("content-table-foot-cell-border-width"); + color: cv.getVar("content-table-foot-cell-color"); + } + } + + tbody { + tr { + &:last-child { + td, + th { + border-bottom-width: cv.getVar( + "content-table-body-last-row-cell-border-bottom-width" + ); + } + } + } + } + } + + .#{iv.$class-prefix}tabs { + li + li { + margin-top: 0; + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-normal { + font-size: cv.getVar("size-normal"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } +} diff --git a/web/assets/css/sass/elements/delete.scss b/web/assets/css/sass/elements/delete.scss new file mode 100644 index 0000000..fb9cb43 --- /dev/null +++ b/web/assets/css/sass/elements/delete.scss @@ -0,0 +1,6 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +.#{iv.$class-prefix}delete { + @include mx.delete; +} diff --git a/web/assets/css/sass/elements/icon.scss b/web/assets/css/sass/elements/icon.scss new file mode 100644 index 0000000..2df2638 --- /dev/null +++ b/web/assets/css/sass/elements/icon.scss @@ -0,0 +1,67 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; + +$icon-dimensions: 1.5rem !default; +$icon-dimensions-small: 1rem !default; +$icon-dimensions-medium: 2rem !default; +$icon-dimensions-large: 3rem !default; +$icon-text-spacing: 0.25em !default; + +.#{iv.$class-prefix}icon, +.#{iv.$class-prefix}icon-text { + @include cv.register-vars( + ( + "icon-dimensions": #{$icon-dimensions}, + "icon-dimensions-small": #{$icon-dimensions-small}, + "icon-dimensions-medium": #{$icon-dimensions-medium}, + "icon-dimensions-large": #{$icon-dimensions-large}, + "icon-text-spacing": #{$icon-text-spacing}, + ) + ); +} + +.#{iv.$class-prefix}icon { + align-items: center; + display: inline-flex; + flex-shrink: 0; + justify-content: center; + height: cv.getVar("icon-dimensions"); + transition-duration: cv.getVar("duration"); + transition-property: color; + width: cv.getVar("icon-dimensions"); + + // Sizes + &.#{iv.$class-prefix}is-small { + height: cv.getVar("icon-dimensions-small"); + width: cv.getVar("icon-dimensions-small"); + } + + &.#{iv.$class-prefix}is-medium { + height: cv.getVar("icon-dimensions-medium"); + width: cv.getVar("icon-dimensions-medium"); + } + + &.#{iv.$class-prefix}is-large { + height: cv.getVar("icon-dimensions-large"); + width: cv.getVar("icon-dimensions-large"); + } +} + +.#{iv.$class-prefix}icon-text { + align-items: flex-start; + color: inherit; + display: inline-flex; + flex-wrap: wrap; + gap: cv.getVar("icon-text-spacing"); + line-height: cv.getVar("icon-dimensions"); + vertical-align: top; + + .#{iv.$class-prefix}icon { + flex-grow: 0; + flex-shrink: 0; + } +} + +div.#{iv.$class-prefix}icon-text { + display: flex; +} diff --git a/web/assets/css/sass/elements/image.scss b/web/assets/css/sass/elements/image.scss new file mode 100644 index 0000000..8e5106e --- /dev/null +++ b/web/assets/css/sass/elements/image.scss @@ -0,0 +1,62 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/css-variables" as cv; +@use "../utilities/mixins" as mx; + +$dimensions: 16 24 32 48 64 96 128 !default; + +.#{iv.$class-prefix}image { + display: block; + position: relative; + + img { + display: block; + height: auto; + width: 100%; + + &.#{iv.$class-prefix}is-rounded { + border-radius: cv.getVar("radius-rounded"); + } + } + + &.#{iv.$class-prefix}is-fullwidth { + width: 100%; + } + + // Ratio + &.#{iv.$class-prefix}is-square { + img, + .#{iv.$class-prefix}has-ratio { + @include mx.overlay; + height: 100%; + width: 100%; + } + } + + &.#{iv.$class-prefix}is-square { + aspect-ratio: 1; + } + + @each $pair in iv.$aspect-ratios { + $w: nth($pair, 1); + $h: nth($pair, 2); + + &.#{iv.$class-prefix}is-#{$w}by#{$h} { + aspect-ratio: #{$w} / #{$h}; + + img, + .#{iv.$class-prefix}has-ratio { + @include mx.overlay; + height: 100%; + width: 100%; + } + } + } + + // Sizes + @each $dimension in $dimensions { + &.#{iv.$class-prefix}is-#{$dimension}x#{$dimension} { + height: $dimension * 1px; + width: $dimension * 1px; + } + } +} diff --git a/web/assets/css/sass/elements/loader.scss b/web/assets/css/sass/elements/loader.scss new file mode 100644 index 0000000..3cd1a26 --- /dev/null +++ b/web/assets/css/sass/elements/loader.scss @@ -0,0 +1,15 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; + +.#{iv.$class-prefix}loader { + animation: spinAround 500ms infinite linear; + border: 2px solid cv.getVar("border"); + border-radius: cv.getVar("radius-rounded"); + border-right-color: transparent; + border-top-color: transparent; + content: ""; + display: block; + height: 1em; + position: relative; + width: 1em; +} diff --git a/web/assets/css/sass/elements/notification.scss b/web/assets/css/sass/elements/notification.scss new file mode 100644 index 0000000..0e0df7e --- /dev/null +++ b/web/assets/css/sass/elements/notification.scss @@ -0,0 +1,105 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$notification-code-background-color: cv.getVar("scheme-main") !default; +$notification-radius: cv.getVar("radius") !default; +$notification-padding: 1.375em 1.5em !default; + +$notification-colors: dv.$colors !default; + +.#{iv.$class-prefix}notification { + @include cv.register-vars( + ( + "notification-h": #{cv.getVar("scheme-h")}, + "notification-s": #{cv.getVar("scheme-s")}, + "notification-background-l": #{cv.getVar("background-l")}, + "notification-color-l": #{cv.getVar("text-strong-l")}, + "notification-code-background-color": #{$notification-code-background-color}, + "notification-radius": #{$notification-radius}, + "notification-padding": #{$notification-padding}, + ) + ); +} + +.#{iv.$class-prefix}notification { + @extend %block; + + background-color: hsl( + cv.getVar("notification-h"), + cv.getVar("notification-s"), + cv.getVar("notification-background-l") + ); + border-radius: cv.getVar("notification-radius"); + color: hsl( + cv.getVar("notification-h"), + cv.getVar("notification-s"), + cv.getVar("notification-color-l") + ); + padding: cv.getVar("notification-padding"); + position: relative; + + a:not(.#{iv.$class-prefix}button):not(.#{iv.$class-prefix}dropdown-item) { + color: currentColor; + text-decoration: underline; + } + + strong { + color: currentColor; + } + + code, + pre { + background: cv.getVar("notification-code-background-color"); + } + + pre code { + background: transparent; + } + + & > .#{iv.$class-prefix}delete { + position: absolute; + inset-inline-end: 1rem; + top: 1rem; + } + + .#{iv.$class-prefix}title, + .#{iv.$class-prefix}subtitle, + .#{iv.$class-prefix}content { + color: currentColor; + } + + // Colors + @each $name, $pair in $notification-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "notification-h": #{cv.getVar($name, "", "-h")}, + "notification-s": #{cv.getVar($name, "", "-s")}, + "notification-background-l": #{cv.getVar($name, "", "-l")}, + "notification-color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + + &.#{iv.$class-prefix}is-light { + @include cv.register-vars( + ( + "notification-background-l": 90%, + "notification-color-l": #{cv.getVar($name, "", "-light-invert-l")}, + ) + ); + } + + &.#{iv.$class-prefix}is-dark { + @include cv.register-vars( + ( + "notification-background-l": 20%, + "notification-color-l": #{cv.getVar($name, "", "-dark-invert-l")}, + ) + ); + } + } + } +} diff --git a/web/assets/css/sass/elements/progress.scss b/web/assets/css/sass/elements/progress.scss new file mode 100644 index 0000000..2c38af4 --- /dev/null +++ b/web/assets/css/sass/elements/progress.scss @@ -0,0 +1,115 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$progress-bar-background-color: cv.getVar("border-weak") !default; +$progress-value-background-color: cv.getVar("text") !default; +$progress-border-radius: cv.getVar("radius-rounded") !default; + +$progress-indeterminate-duration: 1.5s !default; + +$progress-colors: dv.$colors !default; + +.#{iv.$class-prefix}progress { + @include cv.register-vars( + ( + "progress-border-radius": #{$progress-border-radius}, + "progress-bar-background-color": #{$progress-bar-background-color}, + "progress-value-background-color": #{$progress-value-background-color}, + "progress-indeterminate-duration": #{$progress-indeterminate-duration}, + ) + ); +} + +.#{iv.$class-prefix}progress { + @extend %block; + + appearance: none; + border: none; + border-radius: cv.getVar("progress-border-radius"); + display: block; + height: cv.getVar("size-normal"); + overflow: hidden; + padding: 0; + width: 100%; + + &::-webkit-progress-bar { + background-color: cv.getVar("progress-bar-background-color"); + } + + &::-webkit-progress-value { + background-color: cv.getVar("progress-value-background-color"); + } + + &::-moz-progress-bar { + background-color: cv.getVar("progress-value-background-color"); + } + + &::-ms-fill { + background-color: cv.getVar("progress-value-background-color"); + border: none; + } + + // Colors + @each $name, $pair in $progress-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-var( + "progress-value-background-color", + #{cv.getVar($name)} + ); + } + } + + &:indeterminate { + animation-duration: cv.getVar("progress-indeterminate-duration"); + animation-iteration-count: infinite; + animation-name: moveIndeterminate; + animation-timing-function: linear; + background-color: cv.getVar("progress-bar-background-color"); + background-image: linear-gradient( + to right, + cv.getVar("progress-value-background-color") 30%, + cv.getVar("progress-bar-background-color") 30% + ); + background-position: top left; + background-repeat: no-repeat; + background-size: 150% 150%; + + &::-webkit-progress-bar { + background-color: transparent; + } + + &::-moz-progress-bar { + background-color: transparent; + } + + &::-ms-fill { + animation-name: none; + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + height: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + height: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + height: cv.getVar("size-large"); + } +} + +@keyframes moveIndeterminate { + from { + background-position: 200% 0; + } + + to { + background-position: (-200%) 0; + } +} diff --git a/web/assets/css/sass/elements/table.scss b/web/assets/css/sass/elements/table.scss new file mode 100644 index 0000000..97b6e92 --- /dev/null +++ b/web/assets/css/sass/elements/table.scss @@ -0,0 +1,261 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$table-color: cv.getVar("text-strong") !default; +$table-background-color: cv.getVar("scheme-main") !default; + +$table-cell-border-color: cv.getVar("border") !default; +$table-cell-border-style: solid !default; +$table-cell-border-width: 0 0 1px !default; +$table-cell-padding: 0.5em 0.75em !default; +$table-cell-heading-color: cv.getVar("text-strong") !default; +$table-cell-text-align: left !default; + +$table-head-cell-border-width: 0 0 2px !default; +$table-head-cell-color: cv.getVar("text-strong") !default; +$table-foot-cell-border-width: 2px 0 0 !default; +$table-foot-cell-color: cv.getVar("text-strong") !default; + +$table-head-background-color: transparent !default; +$table-body-background-color: transparent !default; +$table-foot-background-color: transparent !default; + +$table-row-hover-background-color: cv.getVar("scheme-main-bis") !default; + +$table-row-active-background-color: cv.getVar("primary") !default; +$table-row-active-color: cv.getVar("primary-invert") !default; + +$table-striped-row-even-background-color: cv.getVar("scheme-main-bis") !default; +$table-striped-row-even-hover-background-color: cv.getVar( + "scheme-main-ter" +) !default; + +$table-colors: dv.$colors !default; + +.#{iv.$class-prefix}table { + @include cv.register-vars( + ( + "table-color": #{$table-color}, + "table-background-color": #{$table-background-color}, + "table-cell-border-color": #{$table-cell-border-color}, + "table-cell-border-style": #{$table-cell-border-style}, + "table-cell-border-width": #{$table-cell-border-width}, + "table-cell-padding": #{$table-cell-padding}, + "table-cell-heading-color": #{$table-cell-heading-color}, + "table-cell-text-align": #{$table-cell-text-align}, + "table-head-cell-border-width": #{$table-head-cell-border-width}, + "table-head-cell-color": #{$table-head-cell-color}, + "table-foot-cell-border-width": #{$table-foot-cell-border-width}, + "table-foot-cell-color": #{$table-foot-cell-color}, + "table-head-background-color": #{$table-head-background-color}, + "table-body-background-color": #{$table-body-background-color}, + "table-foot-background-color": #{$table-foot-background-color}, + "table-row-hover-background-color": #{$table-row-hover-background-color}, + "table-row-active-background-color": #{$table-row-active-background-color}, + "table-row-active-color": #{$table-row-active-color}, + "table-striped-row-even-background-color": #{$table-striped-row-even-background-color}, + "table-striped-row-even-hover-background-color": #{$table-striped-row-even-hover-background-color}, + ) + ); +} + +.#{iv.$class-prefix}table { + @extend %block; + + background-color: cv.getVar("table-background-color"); + color: cv.getVar("table-color"); + + td, + th { + background-color: cv.getVar("table-cell-background-color"); + border-color: cv.getVar("table-cell-border-color"); + border-style: cv.getVar("table-cell-border-style"); + border-width: cv.getVar("table-cell-border-width"); + color: cv.getVar("table-color"); + padding: cv.getVar("table-cell-padding"); + vertical-align: top; + + // Colors + @each $name, $pair in $table-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "table-color": #{cv.getVar($name, "", "-invert")}, + "table-cell-heading-color": #{cv.getVar($name, "", "-invert")}, + "table-cell-background-color": #{cv.getVar($name)}, + "table-cell-border-color": #{cv.getVar($name)}, + ) + ); + } + } + + // Modifiers + &.#{iv.$class-prefix}is-narrow { + white-space: nowrap; + width: 1%; + } + + &.#{iv.$class-prefix}is-selected { + background-color: cv.getVar("table-row-active-background-color"); + color: cv.getVar("table-row-active-color"); + + a, + strong { + color: currentColor; + } + } + + &.#{iv.$class-prefix}is-vcentered { + vertical-align: middle; + } + } + + th { + color: cv.getVar("table-cell-heading-color"); + + &:not([align]) { + text-align: cv.getVar("table-cell-text-align"); + } + } + + tr { + &.#{iv.$class-prefix}is-selected { + background-color: cv.getVar("table-row-active-background-color"); + color: cv.getVar("table-row-active-color"); + + a, + strong { + color: currentColor; + } + + td, + th { + border-color: cv.getVar("table-row-active-color"); + color: currentColor; + } + } + + @each $name, $pair in $table-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "table-color": #{cv.getVar($name, "", "-invert")}, + "table-cell-heading-color": #{cv.getVar($name, "", "-invert")}, + "table-cell-background-color": #{cv.getVar($name)}, + "table-cell-border-color": #{cv.getVar($name)}, + ) + ); + } + } + } + + thead { + background-color: cv.getVar("table-head-background-color"); + + td, + th { + border-width: cv.getVar("table-head-cell-border-width"); + color: cv.getVar("table-head-cell-color"); + } + } + + tfoot { + background-color: cv.getVar("table-foot-background-color"); + + td, + th { + border-width: cv.getVar("table-foot-cell-border-width"); + color: cv.getVar("table-foot-cell-color"); + } + } + + tbody { + background-color: cv.getVar("table-body-background-color"); + + tr { + &:last-child { + td, + th { + border-bottom-width: 0; + } + } + } + } + + // Modifiers + &.#{iv.$class-prefix}is-bordered { + td, + th { + border-width: 1px; + } + + tr { + &:last-child { + td, + th { + border-bottom-width: 1px; + } + } + } + } + + &.#{iv.$class-prefix}is-fullwidth { + width: 100%; + } + + &.#{iv.$class-prefix}is-hoverable { + tbody { + tr:not(.#{iv.$class-prefix}is-selected) { + &:hover { + background-color: cv.getVar("table-row-hover-background-color"); + } + } + } + + &.#{iv.$class-prefix}is-striped { + tbody { + tr:not(.#{iv.$class-prefix}is-selected) { + &:hover { + background-color: cv.getVar("table-row-hover-background-color"); + + &:nth-child(even) { + background-color: cv.getVar( + "table-striped-row-even-hover-background-color" + ); + } + } + } + } + } + } + + &.#{iv.$class-prefix}is-narrow { + td, + th { + padding: 0.25em 0.5em; + } + } + + &.#{iv.$class-prefix}is-striped { + tbody { + tr:not(.#{iv.$class-prefix}is-selected) { + &:nth-child(even) { + background-color: cv.getVar( + "table-striped-row-even-background-color" + ); + } + } + } + } +} + +.#{iv.$class-prefix}table-container { + @extend %block; + @include mx.overflow-touch; + overflow: auto; + overflow-y: hidden; + max-width: 100%; +} diff --git a/web/assets/css/sass/elements/tag.scss b/web/assets/css/sass/elements/tag.scss new file mode 100644 index 0000000..336fa97 --- /dev/null +++ b/web/assets/css/sass/elements/tag.scss @@ -0,0 +1,219 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$tag-h: cv.getVar("scheme-h"); +$tag-s: cv.getVar("scheme-s"); +$tag-background-l: cv.getVar("background-l"); +$tag-background-l-delta: 0%; +$tag-hover-background-l-delta: cv.getVar("hover-background-l-delta"); +$tag-active-background-l-delta: cv.getVar("active-background-l-delta"); +$tag-color-l: cv.getVar("text-l"); +$tag-radius: cv.getVar("radius") !default; +$tag-delete-margin: 1px !default; + +$tag-colors: dv.$colors !default; + +.#{iv.$class-prefix}tags { + @extend %block; + + align-items: center; + color: hsl(cv.getVar("tag-h"), cv.getVar("tag-s"), cv.getVar("tag-color-l")); + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + justify-content: flex-start; + + // Sizes + &.#{iv.$class-prefix}are-medium { + .#{iv.$class-prefix}tag:not(.#{iv.$class-prefix}is-normal):not( + .#{iv.$class-prefix}is-large + ) { + font-size: cv.getVar("size-normal"); + } + } + + &.#{iv.$class-prefix}are-large { + .#{iv.$class-prefix}tag:not(.#{iv.$class-prefix}is-normal):not( + .#{iv.$class-prefix}is-medium + ) { + font-size: cv.getVar("size-medium"); + } + } + + &.#{iv.$class-prefix}is-centered { + gap: 0.25rem; + justify-content: center; + } + + &.#{iv.$class-prefix}is-right { + justify-content: flex-end; + } + + &.#{iv.$class-prefix}has-addons { + gap: 0; + + .#{iv.$class-prefix}tag { + &:not(:first-child) { + border-start-start-radius: 0; // Top left + border-end-start-radius: 0; // Top right + } + + &:not(:last-child) { + border-start-end-radius: 0; // Bottom left + border-end-end-radius: 0; // Bottom right + } + } + } +} + +.#{iv.$class-prefix}tag { + @include cv.register-vars( + ( + "tag-h": #{$tag-h}, + "tag-s": #{$tag-s}, + "tag-background-l": #{$tag-background-l}, + "tag-background-l-delta": #{$tag-background-l-delta}, + "tag-hover-background-l-delta": #{$tag-hover-background-l-delta}, + "tag-active-background-l-delta": #{$tag-active-background-l-delta}, + "tag-color-l": #{$tag-color-l}, + "tag-radius": #{$tag-radius}, + "tag-delete-margin": #{$tag-delete-margin}, + ) + ); + + align-items: center; + background-color: hsl( + cv.getVar("tag-h"), + cv.getVar("tag-s"), + calc( + #{cv.getVar("tag-background-l")} + #{cv.getVar("tag-background-l-delta")} + ) + ); + border-radius: $tag-radius; + color: hsl(cv.getVar("tag-h"), cv.getVar("tag-s"), cv.getVar("tag-color-l")); + display: inline-flex; + font-size: cv.getVar("size-small"); + height: 2em; + justify-content: center; + line-height: 1.5; + padding-left: 0.75em; + padding-right: 0.75em; + white-space: nowrap; + + .#{iv.$class-prefix}delete { + margin-inline-start: 0.25rem; + margin-inline-end: -0.375rem; + } + + // Colors + @each $name, $pair in $tag-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "tag-h": #{cv.getVar($name, "", "-h")}, + "tag-s": #{cv.getVar($name, "", "-s")}, + "tag-background-l": #{cv.getVar($name, "", "-l")}, + "tag-color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + + &.#{iv.$class-prefix}is-light { + @include cv.register-vars( + ( + "tag-background-l": #{cv.getVar("light-l")}, + "tag-color-l": #{cv.getVar($name, "", "-light-invert-l")}, + ) + ); + } + } + } + + // Sizes + &.#{iv.$class-prefix}is-normal { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-normal"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-medium"); + } + + .#{iv.$class-prefix}icon { + &:first-child:not(:last-child) { + margin-inline-start: -0.375em; + margin-inline-end: 0.1875em; + } + + &:last-child:not(:first-child) { + margin-inline-start: 0.1875em; + margin-inline-end: -0.375em; + } + + &:first-child:last-child { + margin-inline-start: -0.375em; + margin-inline-end: -0.375em; + } + } + + // Modifiers + &.#{iv.$class-prefix}is-delete { + margin-inline-start: cv.getVar("tag-delete-margin"); + padding: 0; + position: relative; + width: 2em; + + &::before, + &::after { + background-color: currentColor; + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; + } + + &::before { + height: 1px; + width: 50%; + } + + &::after { + height: 50%; + width: 1px; + } + } + + &.#{iv.$class-prefix}is-rounded { + border-radius: cv.getVar("radius-rounded"); + } +} + +a.#{iv.$class-prefix}tag, +button.#{iv.$class-prefix}tag, +.#{iv.$class-prefix}tag.is-hoverable { + cursor: pointer; + + &:hover { + @include cv.register-vars( + ( + "tag-background-l-delta": #{cv.getVar("tag-hover-background-l-delta")}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "tag-background-l-delta": #{cv.getVar("tag-active-background-l-delta")}, + ) + ); + } +} diff --git a/web/assets/css/sass/elements/title.scss b/web/assets/css/sass/elements/title.scss new file mode 100644 index 0000000..b416689 --- /dev/null +++ b/web/assets/css/sass/elements/title.scss @@ -0,0 +1,128 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$title-color: cv.getVar("text-strong") !default; +$title-family: false !default; +$title-size: cv.getVar("size-3") !default; +$title-weight: cv.getVar("weight-extrabold") !default; +$title-line-height: 1.125 !default; +$title-strong-color: inherit !default; +$title-strong-weight: inherit !default; +$title-sub-size: 0.75em !default; +$title-sup-size: 0.75em !default; + +$subtitle-color: cv.getVar("text") !default; +$subtitle-family: false !default; +$subtitle-size: cv.getVar("size-5") !default; +$subtitle-weight: cv.getVar("weight-normal") !default; +$subtitle-line-height: 1.25 !default; +$subtitle-strong-color: cv.getVar("text-strong") !default; +$subtitle-strong-weight: cv.getVar("weight-semibold") !default; + +.#{iv.$class-prefix}title, +.#{iv.$class-prefix}subtitle { + @include cv.register-vars( + ( + "title-color": #{$title-color}, + "title-family": #{$title-family}, + "title-size": #{$title-size}, + "title-weight": #{$title-weight}, + "title-line-height": #{$title-line-height}, + "title-strong-color": #{$title-strong-color}, + "title-strong-weight": #{$title-strong-weight}, + "title-sub-size": #{$title-sub-size}, + "title-sup-size": #{$title-sup-size}, + "subtitle-color": #{$subtitle-color}, + "subtitle-family": #{$subtitle-family}, + "subtitle-size": #{$subtitle-size}, + "subtitle-weight": #{$subtitle-weight}, + "subtitle-line-height": #{$subtitle-line-height}, + "subtitle-strong-color": #{$subtitle-strong-color}, + "subtitle-strong-weight": #{$subtitle-strong-weight}, + ) + ); +} + +.#{iv.$class-prefix}title, +.#{iv.$class-prefix}subtitle { + @extend %block; + word-break: break-word; + + em, + span { + font-weight: inherit; + } + + sub { + font-size: cv.getVar("title-sub-size"); + } + + sup { + font-size: cv.getVar("title-sup-size"); + } + + .#{iv.$class-prefix}tag { + vertical-align: middle; + } +} + +.#{iv.$class-prefix}title { + color: cv.getVar("title-color"); + font-size: cv.getVar("title-size"); + font-weight: cv.getVar("title-weight"); + line-height: cv.getVar("title-line-height"); + + @if $title-family { + font-family: cv.getVar("title-family"); + } + + strong { + color: cv.getVar("title-strong-color"); + font-weight: cv.getVar("title-strong-weight"); + } + + &:not(.#{iv.$class-prefix}is-spaced):has(+ .#{iv.$class-prefix}subtitle) { + margin-bottom: 0; + } + + // Sizes + @each $size in dv.$sizes { + $i: index(dv.$sizes, $size); + + &.#{iv.$class-prefix}is-#{$i} { + font-size: $size; + } + } +} + +.#{iv.$class-prefix}subtitle { + color: cv.getVar("subtitle-color"); + font-size: cv.getVar("subtitle-size"); + font-weight: cv.getVar("subtitle-weight"); + line-height: cv.getVar("subtitle-line-height"); + + @if $subtitle-family { + font-family: cv.getVar("subtitle-family"); + } + + strong { + color: cv.getVar("subtitle-strong-color"); + font-weight: cv.getVar("subtitle-strong-weight"); + } + + &:not(.#{iv.$class-prefix}is-spaced):has(+ .#{iv.$class-prefix}title) { + margin-bottom: 0; + } + + // Sizes + @each $size in dv.$sizes { + $i: index(dv.$sizes, $size); + + &.#{iv.$class-prefix}is-#{$i} { + font-size: $size; + } + } +} diff --git a/web/assets/css/sass/form/_index.scss b/web/assets/css/sass/form/_index.scss new file mode 100644 index 0000000..7c1214d --- /dev/null +++ b/web/assets/css/sass/form/_index.scss @@ -0,0 +1,9 @@ +/* Bulma Form */ +@charset "utf-8"; + +@forward "shared"; +@forward "input-textarea"; +@forward "checkbox-radio"; +@forward "select"; +@forward "file"; +@forward "tools"; diff --git a/web/assets/css/sass/form/checkbox-radio.scss b/web/assets/css/sass/form/checkbox-radio.scss new file mode 100644 index 0000000..39dc530 --- /dev/null +++ b/web/assets/css/sass/form/checkbox-radio.scss @@ -0,0 +1,32 @@ +@use "shared"; +@use "../utilities/initial-variables" as iv; + +%checkbox-radio { + cursor: pointer; + display: inline-block; + line-height: 1.25; + position: relative; + + input { + cursor: pointer; + } + + &[disabled], + fieldset[disabled] &, + input[disabled] { + color: shared.$input-disabled-color; + cursor: not-allowed; + } +} + +.#{iv.$class-prefix}checkbox { + @extend %checkbox-radio; +} + +.#{iv.$class-prefix}radio { + @extend %checkbox-radio; + + & + .#{iv.$class-prefix}radio { + margin-inline-start: 0.5em; + } +} diff --git a/web/assets/css/sass/form/file.scss b/web/assets/css/sass/form/file.scss new file mode 100644 index 0000000..c75d4a1 --- /dev/null +++ b/web/assets/css/sass/form/file.scss @@ -0,0 +1,330 @@ +@use "shared"; +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/controls"; +@use "../utilities/extends"; + +$file-radius: cv.getVar("radius") !default; + +$file-h: cv.getVar("scheme-h"); +$file-s: cv.getVar("scheme-s"); +$file-background-l: cv.getVar("scheme-main-ter-l"); +$file-background-l-delta: 0%; +$file-hover-background-l-delta: -5%; +$file-active-background-l-delta: -10%; +$file-border-l: cv.getVar("border-l"); +$file-border-l-delta: 0%; +$file-hover-border-l-delta: -10%; +$file-active-border-l-delta: -20%; +$file-cta-color-l: cv.getVar("text-strong-l"); +$file-name-color-l: cv.getVar("text-strong-l"); +$file-color-l-delta: 0%; +$file-hover-color-l-delta: -5%; +$file-active-color-l-delta: -10%; + +$file-cta-color: cv.getVar("text") !default; +$file-cta-hover-color: cv.getVar("text-strong") !default; +$file-cta-active-color: cv.getVar("text-strong") !default; + +$file-name-border-color: cv.getVar("border") !default; +$file-name-border-style: solid !default; +$file-name-border-width: 1px 1px 1px 0 !default; +$file-name-max-width: 16em !default; + +$file-colors: shared.$form-colors !default; + +.#{iv.$class-prefix}file { + @extend %block; + @extend %unselectable; + + @include cv.register-vars( + ( + "file-radius": #{$file-radius}, + "file-name-border-color": #{$file-name-border-color}, + "file-name-border-style": #{$file-name-border-style}, + "file-name-border-width": #{$file-name-border-width}, + "file-name-max-width": #{$file-name-max-width}, + "file-h": #{$file-h}, + "file-s": #{$file-s}, + "file-background-l": #{$file-background-l}, + "file-background-l-delta": #{$file-background-l-delta}, + "file-hover-background-l-delta": #{$file-hover-background-l-delta}, + "file-active-background-l-delta": #{$file-active-background-l-delta}, + "file-border-l": #{$file-border-l}, + "file-border-l-delta": #{$file-border-l-delta}, + "file-hover-border-l-delta": #{$file-hover-border-l-delta}, + "file-active-border-l-delta": #{$file-active-border-l-delta}, + "file-cta-color-l": #{$file-cta-color-l}, + "file-name-color-l": #{$file-name-color-l}, + "file-color-l-delta": #{$file-color-l-delta}, + "file-hover-color-l-delta": #{$file-hover-color-l-delta}, + "file-active-color-l-delta": #{$file-active-color-l-delta}, + ) + ); + + align-items: stretch; + display: flex; + justify-content: flex-start; + position: relative; + + // Colors + @each $name, $pair in $file-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "file-h": #{cv.getVar($name, "", "-h")}, + "file-s": #{cv.getVar($name, "", "-s")}, + "file-background-l": #{cv.getVar($name, "", "-l")}, + "file-border-l": #{cv.getVar($name, "", "-l")}, + "file-cta-color-l": #{cv.getVar($name, "", "-invert-l")}, + "file-name-color-l": #{cv.getVar($name, "", "-on-scheme-l")}, + ) + ); + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-normal { + font-size: cv.getVar("size-normal"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + + .#{iv.$class-prefix}file-icon { + .#{iv.$class-prefix}fa { + font-size: 1.5rem; + } + } + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + + .#{iv.$class-prefix}file-icon { + .#{iv.$class-prefix}fa { + font-size: 2rem; + } + } + } + + // Modifiers + &.#{iv.$class-prefix}has-name { + .#{iv.$class-prefix}file-cta { + border-end-end-radius: 0; + border-start-end-radius: 0; + } + + .#{iv.$class-prefix}file-name { + border-end-start-radius: 0; + border-start-start-radius: 0; + } + + &.#{iv.$class-prefix}is-empty { + .#{iv.$class-prefix}file-cta { + border-radius: cv.getVar("file-radius"); + } + + .#{iv.$class-prefix}file-name { + display: none; + } + } + } + + &.#{iv.$class-prefix}is-boxed { + .#{iv.$class-prefix}file-label { + flex-direction: column; + } + + .#{iv.$class-prefix}file-cta { + flex-direction: column; + height: auto; + padding: 1em 3em; + } + + .#{iv.$class-prefix}file-name { + border-width: 0 1px 1px; + } + + .#{iv.$class-prefix}file-icon { + height: 1.5em; + width: 1.5em; + + .#{iv.$class-prefix}fa { + font-size: 1.5rem; + } + } + + &.#{iv.$class-prefix}is-small { + .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa { + font-size: 1rem; + } + } + + &.#{iv.$class-prefix}is-medium { + .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa { + font-size: 2rem; + } + } + + &.#{iv.$class-prefix}is-large { + .#{iv.$class-prefix}file-icon .#{iv.$class-prefix}fa { + font-size: 2.5rem; + } + } + + &.#{iv.$class-prefix}has-name { + .#{iv.$class-prefix}file-cta { + border-end-end-radius: 0; + border-end-start-radius: 0; + border-start-end-radius: cv.getVar("file-radius"); + border-start-start-radius: cv.getVar("file-radius"); + } + + .#{iv.$class-prefix}file-name { + border-end-end-radius: cv.getVar("file-radius"); + border-end-start-radius: cv.getVar("file-radius"); + border-start-end-radius: 0; + border-start-start-radius: 0; + border-width: 0 1px 1px; + } + } + } + + &.#{iv.$class-prefix}is-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}is-fullwidth { + .#{iv.$class-prefix}file-label { + width: 100%; + } + + .#{iv.$class-prefix}file-name { + flex-grow: 1; + max-width: none; + } + } + + &.#{iv.$class-prefix}is-right { + justify-content: flex-end; + + .#{iv.$class-prefix}file-cta { + border-radius: 0 cv.getVar("file-radius") cv.getVar("file-radius") 0; + } + + .#{iv.$class-prefix}file-name { + border-radius: cv.getVar("file-radius") 0 0 cv.getVar("file-radius"); + border-width: 1px 0 1px 1px; + order: -1; + } + } +} + +.#{iv.$class-prefix}file-label { + align-items: stretch; + display: flex; + cursor: pointer; + justify-content: flex-start; + overflow: hidden; + position: relative; + + &:hover { + @include cv.register-vars( + ( + "file-background-l-delta": #{cv.getVar("file-hover-background-l-delta")}, + "file-border-l-delta": #{cv.getVar("file-hover-border-l-delta")}, + "file-color-l-delta": #{cv.getVar("file-hover-color-l-delta")}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "file-background-l-delta": #{cv.getVar("file-active-background-l-delta")}, + "file-border-l-delta": #{cv.getVar("file-active-border-l-delta")}, + "file-color-l-delta": #{cv.getVar("file-active-color-l-delta")}, + ) + ); + } +} + +.#{iv.$class-prefix}file-input { + height: 100%; + left: 0; + opacity: 0; + outline: none; + position: absolute; + top: 0; + width: 100%; +} + +.#{iv.$class-prefix}file-cta, +.#{iv.$class-prefix}file-name { + @extend %control; + border-color: hsl( + cv.getVar("file-h"), + cv.getVar("file-s"), + calc(#{cv.getVar("file-border-l")} + #{cv.getVar("file-border-l-delta")}) + ); + border-radius: cv.getVar("file-radius"); + font-size: 1em; + padding-left: 1em; + padding-right: 1em; + white-space: nowrap; +} + +.#{iv.$class-prefix}file-cta { + background-color: hsl( + cv.getVar("file-h"), + cv.getVar("file-s"), + calc( + #{cv.getVar("file-background-l")} + #{cv.getVar( + "file-background-l-delta" + )} + ) + ); + color: hsl( + cv.getVar("file-h"), + cv.getVar("file-s"), + calc(#{cv.getVar("file-cta-color-l")} + #{cv.getVar("file-color-l-delta")}) + ); +} + +.#{iv.$class-prefix}file-name { + border-color: hsl( + cv.getVar("file-h"), + cv.getVar("file-s"), + calc(#{cv.getVar("file-border-l")} + #{cv.getVar("file-color-l-delta")}) + ); + border-style: cv.getVar("file-name-border-style"); + border-width: cv.getVar("file-name-border-width"); + color: hsl( + cv.getVar("file-h"), + cv.getVar("file-s"), + calc(#{cv.getVar("file-name-color-l")} + #{cv.getVar("file-color-l-delta")}) + ); + display: block; + max-width: cv.getVar("file-name-max-width"); + overflow: hidden; + text-align: inherit; + text-overflow: ellipsis; +} + +.#{iv.$class-prefix}file-icon { + align-items: center; + display: flex; + height: 1em; + justify-content: center; + margin-inline-end: 0.5em; + width: 1em; + + .#{iv.$class-prefix}fa { + font-size: 1rem; + } +} diff --git a/web/assets/css/sass/form/input-textarea.scss b/web/assets/css/sass/form/input-textarea.scss new file mode 100644 index 0000000..98adbe3 --- /dev/null +++ b/web/assets/css/sass/form/input-textarea.scss @@ -0,0 +1,123 @@ +@use "shared"; +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/controls"; + +$textarea-padding: cv.getVar("control-padding-horizontal") !default; +$textarea-max-height: 40em !default; +$textarea-min-height: 8em !default; + +$textarea-colors: shared.$form-colors !default; + +%input-textarea { + @extend %input; + + @include cv.register-vars( + ( + "input-h": #{cv.getVar("scheme-h")}, + "input-s": #{cv.getVar("scheme-s")}, + "input-border-style": solid, + "input-border-width": 1px, + "input-border-l": #{cv.getVar("border-l")}, + ) + ); + + box-shadow: shared.$input-shadow; + max-width: 100%; + width: 100%; + + &[readonly] { + box-shadow: none; + } + + // Colors + @each $name, $pair in $textarea-colors { + $color: nth($pair, 1); + + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "input-h": #{cv.getVar($name, "", "-h")}, + "input-s": #{cv.getVar($name, "", "-s")}, + "input-l": #{cv.getVar($name, "", "-l")}, + "input-focus-h": #{cv.getVar($name, "", "-h")}, + "input-focus-s": #{cv.getVar($name, "", "-s")}, + "input-focus-l": #{cv.getVar($name, "", "-l")}, + "input-border-l": #{cv.getVar($name, "", "-l")}, + ) + ); + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + @include controls.control-small; + } + + &.#{iv.$class-prefix}is-medium { + @include controls.control-medium; + } + + &.#{iv.$class-prefix}is-large { + @include controls.control-large; + } + + // Modifiers + &.#{iv.$class-prefix}is-fullwidth { + display: block; + width: 100%; + } + + &.#{iv.$class-prefix}is-inline { + display: inline; + width: auto; + } +} + +.#{iv.$class-prefix}input { + @extend %input-textarea; + + &.#{iv.$class-prefix}is-rounded { + border-radius: cv.getVar("radius-rounded"); + padding-left: calc(#{controls.$control-padding-horizontal} + 0.375em); + padding-right: calc(#{controls.$control-padding-horizontal} + 0.375em); + } + + &.#{iv.$class-prefix}is-static { + background-color: transparent; + border-color: transparent; + box-shadow: none; + padding-left: 0; + padding-right: 0; + } +} + +.#{iv.$class-prefix}textarea { + @extend %input-textarea; + @include cv.register-vars( + ( + "textarea-padding": #{$textarea-padding}, + "textarea-max-height": #{$textarea-max-height}, + "textarea-min-height": #{$textarea-min-height}, + ) + ); + display: block; + max-width: 100%; + min-width: 100%; + padding: cv.getVar("textarea-padding"); + resize: vertical; + + &:not([rows]) { + max-height: cv.getVar("textarea-max-height"); + min-height: cv.getVar("textarea-min-height"); + } + + &[rows] { + height: initial; + } + + // Modifiers + &.#{iv.$class-prefix}has-fixed-size { + resize: none; + } +} diff --git a/web/assets/css/sass/form/select.scss b/web/assets/css/sass/form/select.scss new file mode 100644 index 0000000..b68861b --- /dev/null +++ b/web/assets/css/sass/form/select.scss @@ -0,0 +1,143 @@ +@use "shared"; +@use "../utilities/controls"; +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; + +$select-colors: shared.$form-colors !default; + +.#{iv.$class-prefix}select { + @include cv.register-vars( + ( + "input-h": #{cv.getVar("scheme-h")}, + "input-s": #{cv.getVar("scheme-s")}, + "input-border-style": solid, + "input-border-width": 1px, + "input-border-l": #{cv.getVar("border-l")}, + ) + ); + + display: inline-block; + max-width: 100%; + position: relative; + vertical-align: top; + + &:not(.#{iv.$class-prefix}is-multiple) { + height: shared.$input-height; + } + + &:not(.#{iv.$class-prefix}is-multiple):not(.#{iv.$class-prefix}is-loading) { + &::after { + @extend %arrow; + inset-inline-end: 1.125em; + z-index: 4; + } + } + + &.#{iv.$class-prefix}is-rounded { + select { + border-radius: cv.getVar("radius-rounded"); + padding-inline-start: 1em; + } + } + + select { + @extend %input; + cursor: pointer; + display: block; + font-size: 1em; + max-width: 100%; + outline: none; + + &::-ms-expand { + display: none; + } + + &[disabled]:hover, + fieldset[disabled] &:hover { + border-color: shared.$input-disabled-border-color; + } + + &:not([multiple]) { + padding-inline-end: 2.5em; + } + + &[multiple] { + height: auto; + padding: 0; + + option { + padding: 0.5em 1em; + } + } + } + + // Colors + @each $name, $pair in $select-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "input-h": #{cv.getVar($name, "", "-h")}, + "input-s": #{cv.getVar($name, "", "-s")}, + "input-l": #{cv.getVar($name, "", "-l")}, + "input-focus-h": #{cv.getVar($name, "", "-h")}, + "input-focus-s": #{cv.getVar($name, "", "-s")}, + "input-focus-l": #{cv.getVar($name, "", "-l")}, + "input-border-l": #{cv.getVar($name, "", "-l")}, + ) + ); + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + @include controls.control-small; + } + + &.#{iv.$class-prefix}is-medium { + @include controls.control-medium; + } + + &.#{iv.$class-prefix}is-large { + @include controls.control-large; + } + + // Modifiers + &.#{iv.$class-prefix}is-disabled { + &::after { + border-color: shared.$input-disabled-color !important; + opacity: 0.5; + } + } + + &.#{iv.$class-prefix}is-fullwidth { + width: 100%; + + select { + width: 100%; + } + } + + &.#{iv.$class-prefix}is-loading { + &::after { + @extend %loader; + inset-inline-end: 0.625em; + margin-top: 0; + position: absolute; + top: 0.625em; + transform: none; + } + + &.#{iv.$class-prefix}is-small:after { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium:after { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large:after { + font-size: cv.getVar("size-large"); + } + } +} diff --git a/web/assets/css/sass/form/shared.scss b/web/assets/css/sass/form/shared.scss new file mode 100644 index 0000000..14325eb --- /dev/null +++ b/web/assets/css/sass/form/shared.scss @@ -0,0 +1,172 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$form-colors: dv.$colors !default; + +$input-h: #{cv.getVar("scheme-h")} !default; +$input-s: #{cv.getVar("scheme-s")} !default; +$input-l: #{cv.getVar("scheme-main-l")} !default; +$input-border-l: cv.getVar("border-l") !default; +$input-border-l-delta: 0% !default; +$input-hover-border-l-delta: #{cv.getVar("hover-border-l-delta")} !default; +$input-active-border-l-delta: #{cv.getVar("active-border-l-delta")} !default; +$input-color-l: cv.getVar("text-strong-l") !default; +$input-background-l: cv.getVar("scheme-main-l") !default; +$input-background-l-delta: 0% !default; +$input-height: cv.getVar("control-height") !default; +$input-shadow: inset 0 0.0625em 0.125em + hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")}, + 0.05 + ) !default; +$input-placeholder-color: hsla( + #{cv.getVar("text-h")}, + #{cv.getVar("text-s")}, + #{cv.getVar("text-strong-l")}, + 0.3 +) !default; + +$input-focus-h: cv.getVar("focus-h") !default; +$input-focus-s: cv.getVar("focus-s") !default; +$input-focus-l: cv.getVar("focus-l") !default; +$input-focus-shadow-size: cv.getVar("focus-shadow-size") !default; +$input-focus-shadow-alpha: cv.getVar("focus-shadow-alpha") !default; + +$input-disabled-color: cv.getVar("text-weak") !default; +$input-disabled-background-color: cv.getVar("background") !default; +$input-disabled-border-color: cv.getVar("background") !default; +$input-disabled-placeholder-color: hsla( + #{cv.getVar("text-h")}, + #{cv.getVar("text-s")}, + #{cv.getVar("text-weak-l")}, + 0.3 +) !default; + +$input-arrow: cv.getVar("link") !default; + +$input-icon-color: cv.getVar("text-light") !default; +$input-icon-hover-color: cv.getVar("text-weak") !default; +$input-icon-focus-color: cv.getVar("link") !default; + +$input-radius: cv.getVar("radius") !default; + +.#{iv.$class-prefix}control, +.#{iv.$class-prefix}input, +.#{iv.$class-prefix}textarea, +.#{iv.$class-prefix}select select { + @include cv.register-vars( + ( + "input-h": #{$input-h}, + "input-s": #{$input-s}, + "input-l": #{$input-l}, + "input-border-l": #{$input-border-l}, + "input-border-l-delta": #{$input-border-l-delta}, + "input-hover-border-l-delta": #{$input-hover-border-l-delta}, + "input-active-border-l-delta": #{$input-active-border-l-delta}, + "input-focus-h": #{$input-focus-h}, + "input-focus-s": #{$input-focus-s}, + "input-focus-l": #{$input-focus-l}, + "input-focus-shadow-size": #{$input-focus-shadow-size}, + "input-focus-shadow-alpha": #{$input-focus-shadow-alpha}, + "input-color-l": #{$input-color-l}, + "input-background-l": #{$input-background-l}, + "input-background-l-delta": #{$input-background-l-delta}, + "input-height": #{$input-height}, + "input-shadow": #{$input-shadow}, + "input-placeholder-color": #{$input-placeholder-color}, + "input-disabled-color": #{$input-disabled-color}, + "input-disabled-background-color": #{$input-disabled-background-color}, + "input-disabled-border-color": #{$input-disabled-border-color}, + "input-disabled-placeholder-color": #{$input-disabled-placeholder-color}, + "input-arrow": #{$input-arrow}, + "input-icon-color": #{$input-icon-color}, + "input-icon-hover-color": #{$input-icon-hover-color}, + "input-icon-focus-color": #{$input-icon-focus-color}, + "input-radius": #{$input-radius}, + ) + ); +} + +@mixin input { + @extend %control; + background-color: hsl( + #{cv.getVar("input-h")}, + #{cv.getVar("input-s")}, + calc( + #{cv.getVar("input-background-l")} + #{cv.getVar( + "input-background-l-delta" + )} + ) + ); + border-color: hsl( + cv.getVar("input-h"), + cv.getVar("input-s"), + calc(#{cv.getVar("input-border-l")} + #{cv.getVar("input-border-l-delta")}) + ); + border-radius: cv.getVar("input-radius"); + color: hsl( + #{cv.getVar("input-h")}, + #{cv.getVar("input-s")}, + #{cv.getVar("input-color-l")} + ); + + @include mx.placeholder { + color: cv.getVar("input-placeholder-color"); + } + + &:hover, + &.#{iv.$class-prefix}is-hovered { + @include cv.register-vars( + ( + "input-border-l-delta": #{cv.getVar("input-hover-border-l-delta")}, + ) + ); + } + + &:active, + &.#{iv.$class-prefix}is-active { + @include cv.register-vars( + ( + "input-border-l-delta": #{cv.getVar("input-active-border-l-delta")}, + ) + ); + } + + &:focus, + &:focus-within, + &.#{iv.$class-prefix}is-focused { + border-color: hsl( + cv.getVar("input-focus-h"), + cv.getVar("input-focus-s"), + cv.getVar("input-focus-l") + ); + box-shadow: cv.getVar("input-focus-shadow-size") + hsla( + cv.getVar("input-focus-h"), + cv.getVar("input-focus-s"), + cv.getVar("input-focus-l"), + cv.getVar("input-focus-shadow-alpha") + ); + } + + &[disabled], + fieldset[disabled] & { + background-color: cv.getVar("input-disabled-background-color"); + border-color: cv.getVar("input-disabled-border-color"); + box-shadow: none; + color: cv.getVar("input-disabled-color"); + + @include mx.placeholder { + color: cv.getVar("input-disabled-placeholder-color"); + } + } +} + +%input { + @include input; +} diff --git a/web/assets/css/sass/form/tools.scss b/web/assets/css/sass/form/tools.scss new file mode 100644 index 0000000..a4f20bb --- /dev/null +++ b/web/assets/css/sass/form/tools.scss @@ -0,0 +1,341 @@ +@use "shared"; +@use "../utilities/controls"; +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$label-color: cv.getVar("text-strong") !default; +$label-weight: cv.getVar("weight-semibold") !default; + +$help-size: cv.getVar("size-small") !default; + +$label-colors: shared.$form-colors !default; + +.#{iv.$class-prefix}label { + color: $label-color; + display: block; + font-size: cv.getVar("size-normal"); + font-weight: $label-weight; + + &:not(:last-child) { + margin-bottom: 0.5em; + } + + // Sizes + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + } +} + +.#{iv.$class-prefix}help { + display: block; + font-size: $help-size; + margin-top: 0.25rem; + + @each $name, $pair in $label-colors { + &.#{iv.$class-prefix}is-#{$name} { + color: hsl( + #{cv.getVar($name, "", "-h")}, + #{cv.getVar($name, "", "-s")}, + #{cv.getVar($name, "", "-on-scheme-l")} + ); + } + } +} + +// Containers + +.#{iv.$class-prefix}field { + @include cv.register-vars( + ( + "block-spacing": 0.75rem, + ) + ); + + @extend %block; + + // Modifiers + &.#{iv.$class-prefix}has-addons { + display: flex; + justify-content: flex-start; + + .#{iv.$class-prefix}control { + &:not(:last-child) { + margin-inline-end: -1px; + } + + &:not(:first-child):not(:last-child) { + .#{iv.$class-prefix}button, + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + border-radius: 0; + } + } + + &:first-child:not(:only-child) { + .#{iv.$class-prefix}button, + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + // @include ltr { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + // } + } + } + + &:last-child:not(:only-child) { + .#{iv.$class-prefix}button, + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + // @include ltr { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + // } + } + } + + .#{iv.$class-prefix}button, + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + &:not([disabled]) { + &:hover, + &.#{iv.$class-prefix}is-hovered { + z-index: 2; + } + + &:focus, + &.#{iv.$class-prefix}is-focused, + &:active, + &.#{iv.$class-prefix}is-active { + z-index: 3; + + &:hover { + z-index: 4; + } + } + } + } + + &.#{iv.$class-prefix}is-expanded { + flex-grow: 1; + flex-shrink: 1; + } + } + + &.#{iv.$class-prefix}has-addons-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}has-addons-right { + justify-content: flex-end; + } + + &.#{iv.$class-prefix}has-addons-fullwidth { + .#{iv.$class-prefix}control { + flex-grow: 1; + flex-shrink: 0; + } + } + } + + &.#{iv.$class-prefix}is-grouped { + display: flex; + gap: 0.75rem; + justify-content: flex-start; + + & > .#{iv.$class-prefix}control { + flex-shrink: 0; + + &.#{iv.$class-prefix}is-expanded { + flex-grow: 1; + flex-shrink: 1; + } + } + + &.#{iv.$class-prefix}is-grouped-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}is-grouped-right { + justify-content: flex-end; + } + + &.#{iv.$class-prefix}is-grouped-multiline { + flex-wrap: wrap; + } + } + + &.#{iv.$class-prefix}is-horizontal { + @include mx.tablet { + display: flex; + } + } +} + +.#{iv.$class-prefix}field-label { + .#{iv.$class-prefix}label { + font-size: inherit; + } + + @include mx.mobile { + margin-bottom: 0.5rem; + } + + @include mx.tablet { + flex-basis: 0; + flex-grow: 1; + flex-shrink: 0; + margin-inline-end: 1.5rem; + text-align: right; + + &.#{iv.$class-prefix}is-small { + font-size: cv.getVar("size-small"); + padding-top: 0.375em; + } + + &.#{iv.$class-prefix}is-normal { + padding-top: 0.375em; + } + + &.#{iv.$class-prefix}is-medium { + font-size: cv.getVar("size-medium"); + padding-top: 0.375em; + } + + &.#{iv.$class-prefix}is-large { + font-size: cv.getVar("size-large"); + padding-top: 0.375em; + } + } +} + +.#{iv.$class-prefix}field-body { + .#{iv.$class-prefix}field .#{iv.$class-prefix}field { + margin-bottom: 0; + } + + @include mx.tablet { + display: flex; + flex-basis: 0; + flex-grow: 5; + flex-shrink: 1; + + .#{iv.$class-prefix}field { + margin-bottom: 0; + } + + & > .#{iv.$class-prefix}field { + flex-shrink: 1; + + &:not(.#{iv.$class-prefix}is-narrow) { + flex-grow: 1; + } + + &:not(:last-child) { + margin-inline-end: 0.75rem; + } + } + } +} + +.#{iv.$class-prefix}control { + box-sizing: border-box; + clear: both; + font-size: cv.getVar("size-normal"); + position: relative; + text-align: inherit; + + // Modifiers + &.#{iv.$class-prefix}has-icons-left, + &.#{iv.$class-prefix}has-icons-right { + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select { + &:hover { + & ~ .#{iv.$class-prefix}icon { + color: cv.getVar("input-icon-hover-color"); + } + } + + &:focus { + & ~ .#{iv.$class-prefix}icon { + color: cv.getVar("input-icon-focus-color"); + } + } + + &.#{iv.$class-prefix}is-small ~ .#{iv.$class-prefix}icon { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium ~ .#{iv.$class-prefix}icon { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large ~ .#{iv.$class-prefix}icon { + font-size: cv.getVar("size-large"); + } + } + + .#{iv.$class-prefix}icon { + color: cv.getVar("input-icon-color"); + height: cv.getVar("input-height"); + pointer-events: none; + position: absolute; + top: 0; + width: cv.getVar("input-height"); + z-index: 4; + } + } + + &.#{iv.$class-prefix}has-icons-left { + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + padding-left: cv.getVar("input-height"); + } + + .#{iv.$class-prefix}icon.#{iv.$class-prefix}is-left { + left: 0; + } + } + + &.#{iv.$class-prefix}has-icons-right { + .#{iv.$class-prefix}input, + .#{iv.$class-prefix}select select { + padding-right: cv.getVar("input-height"); + } + + .#{iv.$class-prefix}icon.#{iv.$class-prefix}is-right { + right: 0; + } + } + + &.#{iv.$class-prefix}is-loading { + &::after { + @extend %loader; + inset-inline-end: 0.75em; + position: absolute !important; + top: 0.75em; + z-index: 4; + } + + &.#{iv.$class-prefix}is-small:after { + font-size: cv.getVar("size-small"); + } + + &.#{iv.$class-prefix}is-medium:after { + font-size: cv.getVar("size-medium"); + } + + &.#{iv.$class-prefix}is-large:after { + font-size: cv.getVar("size-large"); + } + } +} diff --git a/web/assets/css/sass/grid/_index.scss b/web/assets/css/sass/grid/_index.scss new file mode 100644 index 0000000..70d64ca --- /dev/null +++ b/web/assets/css/sass/grid/_index.scss @@ -0,0 +1,5 @@ +/* Bulma Grid */ +@charset "utf-8"; + +@forward "columns"; +@forward "grid"; diff --git a/web/assets/css/sass/grid/columns-v2.scss b/web/assets/css/sass/grid/columns-v2.scss new file mode 100644 index 0000000..bfb3aa0 --- /dev/null +++ b/web/assets/css/sass/grid/columns-v2.scss @@ -0,0 +1,957 @@ +@use "sass:math"; +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$column-gap: 1.5rem !default; + +:root { + @include cv.register-vars( + ( + "column-gap": #{$column-gap}, + ) + ); +} + +.#{iv.$class-prefix}column { + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-narrow { + flex: none; + width: unset; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-full { + flex: none; + width: 100%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-three-quarters { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-two-thirds { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-half { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-third { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-quarter { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-fifth { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-two-fifths { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-three-fifths { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-four-fifths { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-three-quarters { + margin-inline-start: 75%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-two-thirds { + margin-inline-start: 66.6666%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-half { + margin-inline-start: 50%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-third { + margin-inline-start: 33.3333%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-quarter { + margin-inline-start: 25%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-fifth { + margin-inline-start: 20%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-two-fifths { + margin-inline-start: 40%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-three-fifths { + margin-inline-start: 60%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-four-fifths { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-#{$i} { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc(#{cv.getVar("column-gap")} / 2) + ); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-#{$i} { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + + @include mx.mobile { + &.#{iv.$class-prefix}is-narrow-mobile { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-mobile { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-mobile { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds-mobile { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half-mobile { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third-mobile { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter-mobile { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth-mobile { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths-mobile { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths-mobile { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths-mobile { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters-mobile { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-mobile { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-mobile { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-mobile { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-mobile { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-mobile { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-mobile { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-mobile { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-mobile { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-mobile { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-mobile { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.tablet { + &.#{iv.$class-prefix}is-narrow, + &.#{iv.$class-prefix}is-narrow-tablet { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full, + &.#{iv.$class-prefix}is-full-tablet { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters, + &.#{iv.$class-prefix}is-three-quarters-tablet { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds, + &.#{iv.$class-prefix}is-two-thirds-tablet { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half, + &.#{iv.$class-prefix}is-half-tablet { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third, + &.#{iv.$class-prefix}is-one-third-tablet { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter, + &.#{iv.$class-prefix}is-one-quarter-tablet { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth, + &.#{iv.$class-prefix}is-one-fifth-tablet { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths, + &.#{iv.$class-prefix}is-two-fifths-tablet { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths, + &.#{iv.$class-prefix}is-three-fifths-tablet { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths, + &.#{iv.$class-prefix}is-four-fifths-tablet { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters, + &.#{iv.$class-prefix}is-offset-three-quarters-tablet { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds, + &.#{iv.$class-prefix}is-offset-two-thirds-tablet { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half, + &.#{iv.$class-prefix}is-offset-half-tablet { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third, + &.#{iv.$class-prefix}is-offset-one-third-tablet { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter, + &.#{iv.$class-prefix}is-offset-one-quarter-tablet { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth, + &.#{iv.$class-prefix}is-offset-one-fifth-tablet { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths, + &.#{iv.$class-prefix}is-offset-two-fifths-tablet { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths, + &.#{iv.$class-prefix}is-offset-three-fifths-tablet { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths, + &.#{iv.$class-prefix}is-offset-four-fifths-tablet { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}, + &.#{iv.$class-prefix}is-#{$i}-tablet { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}, + &.#{iv.$class-prefix}is-offset-#{$i}-tablet { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.touch { + &.#{iv.$class-prefix}is-narrow-touch { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-touch { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-touch { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds-touch { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half-touch { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third-touch { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter-touch { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth-touch { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths-touch { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths-touch { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths-touch { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters-touch { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-touch { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-touch { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-touch { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-touch { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-touch { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-touch { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-touch { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-touch { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-touch { + flex: none; + width: math.percentage(math.div($i, 12)); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-touch { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.desktop { + &.#{iv.$class-prefix}is-narrow-desktop { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-desktop { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-desktop { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds-desktop { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half-desktop { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third-desktop { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter-desktop { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth-desktop { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths-desktop { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths-desktop { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths-desktop { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters-desktop { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-desktop { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-desktop { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-desktop { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-desktop { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-desktop { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-desktop { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-desktop { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-desktop { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-desktop { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-desktop { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.widescreen { + &.#{iv.$class-prefix}is-narrow-widescreen { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-widescreen { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-widescreen { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds-widescreen { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half-widescreen { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third-widescreen { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter-widescreen { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth-widescreen { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths-widescreen { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths-widescreen { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths-widescreen { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters-widescreen { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-widescreen { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-widescreen { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-widescreen { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-widescreen { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-widescreen { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-widescreen { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-widescreen { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-widescreen { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-widescreen { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-widescreen { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.fullhd { + &.#{iv.$class-prefix}is-narrow-fullhd { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-fullhd { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-fullhd { + flex: none; + width: calc(75% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-thirds-fullhd { + flex: none; + width: calc(66.6666% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-half-fullhd { + flex: none; + width: calc(50% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-third-fullhd { + flex: none; + width: calc(33.3333% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-quarter-fullhd { + flex: none; + width: calc(25% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-one-fifth-fullhd { + flex: none; + width: calc(20% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-two-fifths-fullhd { + flex: none; + width: calc(40% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-three-fifths-fullhd { + flex: none; + width: calc(60% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-four-fifths-fullhd { + flex: none; + width: calc(80% - calc(#{cv.getVar("column-gap")} / 2)); + } + + &.#{iv.$class-prefix}is-offset-three-quarters-fullhd { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-fullhd { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-fullhd { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-fullhd { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-fullhd { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-fullhd { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-fullhd { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-fullhd { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-fullhd { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-fullhd { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-fullhd { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } +} + +.#{iv.$class-prefix}columns { + @extend %block; + gap: cv.getVar("column-gap"); + + // Modifiers + &.#{iv.$class-prefix}is-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}is-gapless { + gap: 0; + } + + &.#{iv.$class-prefix}is-mobile { + display: flex; + } + + &.#{iv.$class-prefix}is-multiline { + flex-wrap: wrap; + } + + &.#{iv.$class-prefix}is-vcentered { + align-items: center; + } + + // Responsiveness + @include mx.tablet { + &:not(.#{iv.$class-prefix}is-desktop) { + display: flex; + } + } + + @include mx.desktop { + // Modifiers + &.#{iv.$class-prefix}is-desktop { + display: flex; + } + } + + &.#{iv.$class-prefix}is-variable { + @for $i from 0 through 8 { + &.#{iv.$class-prefix}is-#{$i} { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + + @include mx.mobile { + &.#{iv.$class-prefix}is-#{$i}-mobile { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.tablet { + &.#{iv.$class-prefix}is-#{$i}-tablet { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.tablet-only { + &.#{iv.$class-prefix}is-#{$i}-tablet-only { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.touch { + &.#{iv.$class-prefix}is-#{$i}-touch { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.desktop { + &.#{iv.$class-prefix}is-#{$i}-desktop { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.desktop-only { + &.#{iv.$class-prefix}is-#{$i}-desktop-only { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.widescreen { + &.#{iv.$class-prefix}is-#{$i}-widescreen { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.widescreen-only { + &.#{iv.$class-prefix}is-#{$i}-widescreen-only { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + + @include mx.fullhd { + &.#{iv.$class-prefix}is-#{$i}-fullhd { + @include cv.register-vars( + ( + "column-gap": #{$i * 0.25rem}, + ) + ); + } + } + } + } +} diff --git a/web/assets/css/sass/grid/columns.scss b/web/assets/css/sass/grid/columns.scss new file mode 100644 index 0000000..5f5f126 --- /dev/null +++ b/web/assets/css/sass/grid/columns.scss @@ -0,0 +1,877 @@ +@use "sass:math"; +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$column-gap: 0.75rem !default; + +:root { + @include cv.register-vars( + ( + "column-gap": #{$column-gap}, + ) + ); +} + +.#{iv.$class-prefix}column { + display: block; + flex-basis: 0; + flex-grow: 1; + flex-shrink: 1; + padding: $column-gap; + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-narrow { + flex: none; + width: unset; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-full { + flex: none; + width: 100%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-three-quarters { + flex: none; + width: 75%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-two-thirds { + flex: none; + width: 66.6666%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-half { + flex: none; + width: 50%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-third { + flex: none; + width: 33.3333%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-quarter { + flex: none; + width: 25%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-one-fifth { + flex: none; + width: 20%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-two-fifths { + flex: none; + width: 40%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-three-fifths { + flex: none; + width: 60%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-four-fifths { + flex: none; + width: 80%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-three-quarters { + margin-inline-start: 75%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-two-thirds { + margin-inline-start: 66.6666%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-half { + margin-inline-start: 50%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-third { + margin-inline-start: 0.3333%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-quarter { + margin-inline-start: 25%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-one-fifth { + margin-inline-start: 20%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-two-fifths { + margin-inline-start: 40%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-three-fifths { + margin-inline-start: 60%; + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-four-fifths { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-#{$i} { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc(#{cv.getVar("column-gap")} / 2) + ); + } + + .#{iv.$class-prefix}columns.#{iv.$class-prefix}is-mobile + > &.#{iv.$class-prefix}is-offset-#{$i} { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + + @include mx.mobile { + &.#{iv.$class-prefix}is-narrow-mobile { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-mobile { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-mobile { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds-mobile { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half-mobile { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third-mobile { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter-mobile { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth-mobile { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths-mobile { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths-mobile { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths-mobile { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters-mobile { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-mobile { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-mobile { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-mobile { + margin-inline-start: 0.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-mobile { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-mobile { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-mobile { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-mobile { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-mobile { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-mobile { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-mobile { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.tablet { + &.#{iv.$class-prefix}is-narrow, + &.#{iv.$class-prefix}is-narrow-tablet { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full, + &.#{iv.$class-prefix}is-full-tablet { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters, + &.#{iv.$class-prefix}is-three-quarters-tablet { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds, + &.#{iv.$class-prefix}is-two-thirds-tablet { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half, + &.#{iv.$class-prefix}is-half-tablet { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third, + &.#{iv.$class-prefix}is-one-third-tablet { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter, + &.#{iv.$class-prefix}is-one-quarter-tablet { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth, + &.#{iv.$class-prefix}is-one-fifth-tablet { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths, + &.#{iv.$class-prefix}is-two-fifths-tablet { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths, + &.#{iv.$class-prefix}is-three-fifths-tablet { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths, + &.#{iv.$class-prefix}is-four-fifths-tablet { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters, + &.#{iv.$class-prefix}is-offset-three-quarters-tablet { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds, + &.#{iv.$class-prefix}is-offset-two-thirds-tablet { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half, + &.#{iv.$class-prefix}is-offset-half-tablet { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third, + &.#{iv.$class-prefix}is-offset-one-third-tablet { + margin-inline-start: 0.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter, + &.#{iv.$class-prefix}is-offset-one-quarter-tablet { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth, + &.#{iv.$class-prefix}is-offset-one-fifth-tablet { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths, + &.#{iv.$class-prefix}is-offset-two-fifths-tablet { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths, + &.#{iv.$class-prefix}is-offset-three-fifths-tablet { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths, + &.#{iv.$class-prefix}is-offset-four-fifths-tablet { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}, + &.#{iv.$class-prefix}is-#{$i}-tablet { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}, + &.#{iv.$class-prefix}is-offset-#{$i}-tablet { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.touch { + &.#{iv.$class-prefix}is-narrow-touch { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-touch { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-touch { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds-touch { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half-touch { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third-touch { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter-touch { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth-touch { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths-touch { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths-touch { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths-touch { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters-touch { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-touch { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-touch { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-touch { + margin-inline-start: 0.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-touch { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-touch { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-touch { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-touch { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-touch { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-touch { + flex: none; + width: math.percentage(math.div($i, 12)); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-touch { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.desktop { + &.#{iv.$class-prefix}is-narrow-desktop { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-desktop { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-desktop { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds-desktop { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half-desktop { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third-desktop { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter-desktop { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth-desktop { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths-desktop { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths-desktop { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths-desktop { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters-desktop { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-desktop { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-desktop { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-desktop { + margin-inline-start: 0.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-desktop { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-desktop { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-desktop { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-desktop { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-desktop { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-desktop { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-desktop { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.widescreen { + &.#{iv.$class-prefix}is-narrow-widescreen { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-widescreen { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-widescreen { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds-widescreen { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half-widescreen { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third-widescreen { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter-widescreen { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth-widescreen { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths-widescreen { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths-widescreen { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths-widescreen { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters-widescreen { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-widescreen { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-widescreen { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-widescreen { + margin-inline-start: 0.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-widescreen { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-widescreen { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-widescreen { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-widescreen { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-widescreen { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-widescreen { + flex: none; + width: calc( + math.percentage(math.div($i, 12)) - calc( + #{cv.getVar("column-gap")} / 2 + ) + ); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-widescreen { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } + + @include mx.fullhd { + &.#{iv.$class-prefix}is-narrow-fullhd { + flex: none; + width: unset; + } + + &.#{iv.$class-prefix}is-full-fullhd { + flex: none; + width: 100%; + } + + &.#{iv.$class-prefix}is-three-quarters-fullhd { + flex: none; + width: 75%; + } + + &.#{iv.$class-prefix}is-two-thirds-fullhd { + flex: none; + width: 66.6666%; + } + + &.#{iv.$class-prefix}is-half-fullhd { + flex: none; + width: 50%; + } + + &.#{iv.$class-prefix}is-one-third-fullhd { + flex: none; + width: 33.3333%; + } + + &.#{iv.$class-prefix}is-one-quarter-fullhd { + flex: none; + width: 25%; + } + + &.#{iv.$class-prefix}is-one-fifth-fullhd { + flex: none; + width: 20%; + } + + &.#{iv.$class-prefix}is-two-fifths-fullhd { + flex: none; + width: 40%; + } + + &.#{iv.$class-prefix}is-three-fifths-fullhd { + flex: none; + width: 60%; + } + + &.#{iv.$class-prefix}is-four-fifths-fullhd { + flex: none; + width: 80%; + } + + &.#{iv.$class-prefix}is-offset-three-quarters-fullhd { + margin-inline-start: 75%; + } + + &.#{iv.$class-prefix}is-offset-two-thirds-fullhd { + margin-inline-start: 66.6666%; + } + + &.#{iv.$class-prefix}is-offset-half-fullhd { + margin-inline-start: 50%; + } + + &.#{iv.$class-prefix}is-offset-one-third-fullhd { + margin-inline-start: 33.3333%; + } + + &.#{iv.$class-prefix}is-offset-one-quarter-fullhd { + margin-inline-start: 25%; + } + + &.#{iv.$class-prefix}is-offset-one-fifth-fullhd { + margin-inline-start: 20%; + } + + &.#{iv.$class-prefix}is-offset-two-fifths-fullhd { + margin-inline-start: 40%; + } + + &.#{iv.$class-prefix}is-offset-three-fifths-fullhd { + margin-inline-start: 60%; + } + + &.#{iv.$class-prefix}is-offset-four-fifths-fullhd { + margin-inline-start: 80%; + } + + @for $i from 0 through 12 { + &.#{iv.$class-prefix}is-#{$i}-fullhd { + flex: none; + width: math.percentage(math.div($i, 12)); + } + + &.#{iv.$class-prefix}is-offset-#{$i}-fullhd { + margin-inline-start: math.percentage(math.div($i, 12)); + } + } + } +} + +.#{iv.$class-prefix}columns { + margin-inline-start: calc(-1 * #{cv.getVar("column-gap")}); + margin-inline-end: calc(-1 * #{cv.getVar("column-gap")}); + margin-top: calc(-1 * #{cv.getVar("column-gap")}); + + &:last-child { + margin-bottom: calc(-1 * #{cv.getVar("column-gap")}); + } + + &:not(:last-child) { + margin-bottom: calc(1.5rem - #{$column-gap}); + } + + // Modifiers + &.#{iv.$class-prefix}is-centered { + justify-content: center; + } + + &.#{iv.$class-prefix}is-gapless { + margin-inline-start: 0; + margin-inline-end: 0; + + margin-top: 0; + + & > .#{iv.$class-prefix}column { + margin: 0; + padding: 0 !important; + } + + &:not(:last-child) { + margin-bottom: 1.5rem; + } + + &:last-child { + margin-bottom: 0; + } + } + + &.#{iv.$class-prefix}is-mobile { + display: flex; + } + + &.#{iv.$class-prefix}is-multiline { + flex-wrap: wrap; + } + + &.#{iv.$class-prefix}is-vcentered { + align-items: center; + } + + // Responsiveness + @include mx.tablet { + &:not(.#{iv.$class-prefix}is-desktop) { + display: flex; + } + } + + @include mx.desktop { + // Modifiers + &.#{iv.$class-prefix}is-desktop { + display: flex; + } + } +} diff --git a/web/assets/css/sass/grid/grid.scss b/web/assets/css/sass/grid/grid.scss new file mode 100644 index 0000000..9c4191d --- /dev/null +++ b/web/assets/css/sass/grid/grid.scss @@ -0,0 +1,209 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$max-column-count: 12; +$grip-gap: 0.75rem; +$column-min-base: 1.5rem; + +@mixin fixed-grid-properties($suffix: "") { + @for $i from 1 through $max-column-count { + &.#{iv.$class-prefix}has-#{$i}-cols#{$suffix} { + .#{iv.$class-prefix}grid { + @include cv.register-var("grid-column-count", #{$i}); + } + } + } +} + +$grid-container-name: bulma-fixed-grid; + +.#{iv.$class-prefix}fixed-grid { + @extend %block; + container-name: $grid-container-name; + container-type: inline-size; + + .#{iv.$class-prefix}grid { + @include cv.register-vars( + ( + "grid-gap-count": calc(#{cv.getVar("grid-column-count")} - 1), + "grid-column-count": 2, + ) + ); + + grid-template-columns: repeat(cv.getVar("grid-column-count"), 1fr); + } + + @include fixed-grid-properties; + + @include mx.container-until($grid-container-name, iv.$tablet) { + @include fixed-grid-properties("-mobile"); + } + + @include mx.container-from($grid-container-name, iv.$tablet) { + @include fixed-grid-properties("-tablet"); + } + + @include mx.container-from($grid-container-name, iv.$desktop) { + @include fixed-grid-properties("-desktop"); + } + + @include mx.container-from($grid-container-name, iv.$widescreen) { + @include fixed-grid-properties("-widescreen"); + } + + @include mx.container-from($grid-container-name, iv.$fullhd) { + @include fixed-grid-properties("-fullhd"); + } + + &.#{iv.$class-prefix}has-auto-count { + .#{iv.$class-prefix}grid { + @include mx.container-until($grid-container-name, iv.$tablet) { + @include cv.register-var("grid-column-count", 2); + } + + @include mx.container-from($grid-container-name, iv.$tablet) { + @include cv.register-var("grid-column-count", 4); + } + + @include mx.container-from($grid-container-name, iv.$desktop) { + @include cv.register-var("grid-column-count", 8); + } + + @include mx.container-from($grid-container-name, iv.$widescreen) { + @include cv.register-var("grid-column-count", 12); + } + + @include mx.container-from($grid-container-name, iv.$fullhd) { + @include cv.register-var("grid-column-count", 16); + } + } + } +} + +.#{iv.$class-prefix}grid { + @include cv.register-vars( + ( + "grid-gap": $grip-gap, + "grid-column-min": 9rem, + "grid-cell-column-span": 1, + "grid-cell-row-span": 1, + ) + ); + + @extend %block; + display: grid; + gap: cv.getVar("grid-gap"); + column-gap: #{cv.getVarWithBackup("grid-column-gap", "grid-gap")}; + row-gap: #{cv.getVarWithBackup("grid-row-gap", "grid-gap")}; + grid-template-columns: repeat( + auto-fit, + minmax(#{cv.getVar("grid-column-min")}, 1fr) + ); + grid-template-rows: auto; + + &.is-auto-fill { + grid-template-columns: repeat( + auto-fill, + minmax(#{cv.getVar("grid-column-min")}, 1fr) + ); + } + + @for $i from 1 through 12 { + &.#{iv.$class-prefix}is-col-min-#{$i} { + @include cv.register-vars( + ( + "grid-column-min": #{$column-min-base * $i}, + ) + ); + } + } +} + +@mixin cell-properties($suffix: "") { + @for $i from 1 through $max-column-count { + $name: $i + $suffix; + + &.#{iv.$class-prefix}is-col-start-#{$name} { + @include cv.register-var("grid-cell-column-start", #{$i}); + } + + &.#{iv.$class-prefix}is-col-end-#{$name} { + @include cv.register-var("grid-cell-column-end", #{$i}); + } + + &.#{iv.$class-prefix}is-col-from-end-#{$name} { + @include cv.register-var("grid-cell-column-start", #{$i * -1}); + } + + &.#{iv.$class-prefix}is-col-span-#{$name} { + @include cv.register-var("grid-cell-column-span", #{$i}); + } + + &.#{iv.$class-prefix}is-row-start-#{$name} { + @include cv.register-var("grid-cell-row-start", #{$i}); + } + + &.#{iv.$class-prefix}is-row-end-#{$name} { + @include cv.register-var("grid-cell-row-end", #{$i}); + } + + &.#{iv.$class-prefix}is-row-from-end-#{$name} { + @include cv.register-var("grid-cell-row-start", #{$i * -1}); + } + + &.#{iv.$class-prefix}is-row-span-#{$name} { + @include cv.register-var("grid-cell-row-span", #{$i}); + } + } +} + +.#{iv.$class-prefix}cell { + grid-column-end: span cv.getVar("grid-cell-column-span"); + grid-column-start: cv.getVar("grid-cell-column-start"); + grid-row-end: span cv.getVar("grid-cell-row-span"); + grid-row-start: cv.getVar("grid-cell-row-start"); + + // Sizes + &.#{iv.$class-prefix}is-col-start-end { + @include cv.register-var("grid-cell-column-start", -1); + } + + &.#{iv.$class-prefix}is-row-start-end { + @include cv.register-var("grid-cell-row-start", -1); + } + + @include cell-properties; + @include mx.mobile { + @include cell-properties("-mobile"); + } + + @include mx.tablet { + @include cell-properties("-tablet"); + } + + @include mx.tablet-only { + @include cell-properties("-tablet-only"); + } + + @include mx.desktop { + @include cell-properties("-desktop"); + } + + @include mx.desktop-only { + @include cell-properties("-desktop-only"); + } + + @include mx.widescreen { + @include cell-properties("-widescreen"); + } + + @include mx.widescreen-only { + @include cell-properties("-widescreen-only"); + } + + @include mx.fullhd { + @include cell-properties("-fullhd"); + } +} diff --git a/web/assets/css/sass/helpers/_index.scss b/web/assets/css/sass/helpers/_index.scss new file mode 100644 index 0000000..4388647 --- /dev/null +++ b/web/assets/css/sass/helpers/_index.scss @@ -0,0 +1,15 @@ +/* Bulma Helpers */ +@charset "utf-8"; + +@forward "aspect-ratio"; +@forward "border"; +@forward "color"; +@forward "flexbox"; +@forward "float"; +@forward "gap"; +@forward "overflow"; +@forward "position"; +@forward "spacing"; +@forward "typography"; +@forward "visibility"; +@forward "other"; diff --git a/web/assets/css/sass/helpers/aspect-ratio.scss b/web/assets/css/sass/helpers/aspect-ratio.scss new file mode 100644 index 0000000..91e8c4c --- /dev/null +++ b/web/assets/css/sass/helpers/aspect-ratio.scss @@ -0,0 +1,10 @@ +@use "../utilities/initial-variables" as iv; + +@each $pair in iv.$aspect-ratios { + $w: nth($pair, 1); + $h: nth($pair, 2); + + .#{iv.$helpers-prefix}aspect-ratio-#{$w}by#{$h} { + aspect-ratio: #{$w} / #{$h}; + } +} diff --git a/web/assets/css/sass/helpers/border.scss b/web/assets/css/sass/helpers/border.scss new file mode 100644 index 0000000..500ea00 --- /dev/null +++ b/web/assets/css/sass/helpers/border.scss @@ -0,0 +1,15 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; + +$radii: ( + "small": "radius-small", + "normal": "radius", + "large": "radius-large", + "rounded": "radius-rounded", +); + +@each $name, $var in $radii { + .#{iv.$helpers-has-prefix}radius-#{$name} { + border-radius: cv.getVar($var); + } +} diff --git a/web/assets/css/sass/helpers/color.scss b/web/assets/css/sass/helpers/color.scss new file mode 100644 index 0000000..22feaad --- /dev/null +++ b/web/assets/css/sass/helpers/color.scss @@ -0,0 +1,364 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; + +$digits: ( + "00", + "05", + "10", + "15", + "20", + "25", + "30", + "35", + "40", + "45", + "50", + "55", + "60", + "65", + "70", + "75", + "80", + "85", + "90", + "95", + "100" +); + +.#{iv.$helpers-has-prefix}background { + background-color: cv.getVar("background"); +} + +@each $name, $color in dv.$colors { + $background: hsl( + #{cv.getVar($name, "", "-h")}, + #{cv.getVar($name, "", "-s")}, + calc(#{cv.getVar("background-l")} + #{cv.getVar("background-l-delta")}) + ); + + $color: hsl( + #{cv.getVar($name, "", "-h")}, + #{cv.getVar($name, "", "-s")}, + calc(#{cv.getVar("color-l")} + #{cv.getVar("color-l-delta")}) + ); + + [class*="#{iv.$helpers-prefix}color-#{$name}"], + [class*="#{iv.$helpers-has-prefix}text-#{$name}"] { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-l")}, + "color-l-delta": 0%, + ) + ); + color: $color !important; + } + + [class*="#{iv.$helpers-prefix}background-#{$name}"], + [class*="#{iv.$helpers-has-prefix}background-#{$name}"] { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-l")}, + "background-l-delta": 0%, + ) + ); + background-color: $background !important; + } + + // Invert + .#{iv.$helpers-prefix}color-#{$name}-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + } + + // On Scheme + .#{iv.$helpers-prefix}color-#{$name}-on-scheme, + .#{iv.$helpers-has-prefix}text-#{$name}-on-scheme { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-on-scheme-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-on-scheme, + .#{iv.$helpers-has-prefix}background-#{$name}-on-scheme { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-on-scheme-l")}, + ) + ); + } + + // Light + .#{iv.$helpers-prefix}color-#{$name}-light, + .#{iv.$helpers-has-prefix}text-#{$name}-light { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-light-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-light, + .#{iv.$helpers-has-prefix}background-#{$name}-light { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-light-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-light-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-light-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-light-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-light-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-light-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-light-invert-l")}, + ) + ); + } + + // Dark + .#{iv.$helpers-prefix}color-#{$name}-dark, + .#{iv.$helpers-has-prefix}text-#{$name}-dark { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-dark-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-dark, + .#{iv.$helpers-has-prefix}background-#{$name}-dark { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-dark-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-dark-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-dark-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-dark-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-dark-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-dark-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-dark-invert-l")}, + ) + ); + } + + // Soft/Bold + .#{iv.$helpers-prefix}color-#{$name}-soft, + .#{iv.$helpers-has-prefix}text-#{$name}-soft { + @include cv.register-vars( + ( + "color-l": #{cv.getVar("soft-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-soft, + .#{iv.$helpers-has-prefix}background-#{$name}-soft { + @include cv.register-vars( + ( + "background-l": #{cv.getVar("soft-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-bold, + .#{iv.$helpers-has-prefix}text-#{$name}-bold { + @include cv.register-vars( + ( + "color-l": #{cv.getVar("bold-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-bold, + .#{iv.$helpers-has-prefix}background-#{$name}-bold { + @include cv.register-vars( + ( + "background-l": #{cv.getVar("bold-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-soft-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-soft-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar("soft-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-soft-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-soft-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar("soft-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-bold-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-bold-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar("bold-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-bold-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-bold-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar("bold-invert-l")}, + ) + ); + } + + @each $digit in $digits { + .#{iv.$helpers-prefix}color-#{$name}-#{$digit}, + .#{iv.$helpers-has-prefix}text-#{$name}-#{$digit} { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-#{$digit}-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-#{$digit}, + .#{iv.$helpers-has-prefix}background-#{$name}-#{$digit} { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-#{$digit}-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}color-#{$name}-#{$digit}-invert, + .#{iv.$helpers-has-prefix}text-#{$name}-#{$digit}-invert { + @include cv.register-vars( + ( + "color-l": #{cv.getVar($name, "", "-#{$digit}-invert-l")}, + ) + ); + } + + .#{iv.$helpers-prefix}background-#{$name}-#{$digit}-invert, + .#{iv.$helpers-has-prefix}background-#{$name}-#{$digit}-invert { + @include cv.register-vars( + ( + "background-l": #{cv.getVar($name, "", "-#{$digit}-invert-l")}, + ) + ); + } + } + + // Hover + a.#{iv.$helpers-prefix}color-#{$name}, + button.#{iv.$helpers-prefix}color-#{$name}, + #{iv.$helpers-prefix}color-#{$name}.is-hoverable, + a.#{iv.$helpers-has-prefix}text-#{$name}, + button.#{iv.$helpers-has-prefix}text-#{$name}, + #{iv.$helpers-has-prefix}text-#{$name}.is-hoverable { + &:hover, + &:focus-visible { + @include cv.register-vars( + ( + "color-l-delta": #{cv.getVar("hover-color-l-delta")}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "color-l-delta": #{cv.getVar("active-color-l-delta")}, + ) + ); + } + } + + a.#{iv.$helpers-prefix}background-#{$name}, + button.#{iv.$helpers-prefix}background-#{$name}, + #{iv.$helpers-prefix}background-#{$name}.is-hoverable, + a.#{iv.$helpers-has-prefix}background-#{$name}, + button.#{iv.$helpers-has-prefix}background-#{$name}, + #{iv.$helpers-has-prefix}background-#{$name}.is-hoverable { + &:hover, + &:focus-visible { + @include cv.register-vars( + ( + "background-l-delta": #{cv.getVar("hover-background-l-delta")}, + ) + ); + } + + &:active { + @include cv.register-vars( + ( + "background-l-delta": #{cv.getVar("active-background-l-delta")}, + ) + ); + } + } + + // Palettes + .#{iv.$helpers-prefix}palette-#{$name} { + --h: #{cv.getVar($name, "", "-h")}; + --s: #{cv.getVar($name, "", "-s")}; + --l: #{cv.getVar($name, "", "-l")}; + --color: hsl(var(--h), var(--s), var(--l)); + + @each $digit in $digits { + --#{$digit}-l: #{cv.getVar($name, "", "-#{$digit}-l")}; + --color-#{$digit}: hsl(var(--h), var(--s), var(--#{$digit}-l)); + } + } +} + +@each $name, $shade in dv.$shades { + .#{iv.$helpers-prefix}color-#{$name}, + .#{iv.$helpers-has-prefix}text-#{$name} { + color: $shade !important; + } + + .#{iv.$helpers-prefix}background-#{$name}, + .#{iv.$helpers-has-prefix}background-#{$name} { + background-color: $shade !important; + } +} diff --git a/web/assets/css/sass/helpers/flexbox.scss b/web/assets/css/sass/helpers/flexbox.scss new file mode 100644 index 0000000..1265e99 --- /dev/null +++ b/web/assets/css/sass/helpers/flexbox.scss @@ -0,0 +1,62 @@ +@use "../utilities/initial-variables" as iv; + +$flex-direction-values: row, row-reverse, column, column-reverse; + +@each $value in $flex-direction-values { + .#{iv.$helpers-prefix}flex-direction-#{$value} { + flex-direction: $value !important; + } +} + +$flex-wrap-values: nowrap, wrap, wrap-reverse; + +@each $value in $flex-wrap-values { + .#{iv.$helpers-prefix}flex-wrap-#{$value} { + flex-wrap: $value !important; + } +} + +$justify-content-values: flex-start, flex-end, center, space-between, + space-around, space-evenly, start, end, left, right; + +@each $value in $justify-content-values { + .#{iv.$helpers-prefix}justify-content-#{$value} { + justify-content: $value !important; + } +} + +$align-content-values: flex-start, flex-end, center, space-between, space-around, + space-evenly, stretch, start, end, baseline; + +@each $value in $align-content-values { + .#{iv.$helpers-prefix}align-content-#{$value} { + align-content: $value !important; + } +} + +$align-items-values: stretch, flex-start, flex-end, center, baseline, start, end, + self-start, self-end; + +@each $value in $align-items-values { + .#{iv.$helpers-prefix}align-items-#{$value} { + align-items: $value !important; + } +} + +$align-self-values: auto, flex-start, flex-end, center, baseline, stretch; + +@each $value in $align-self-values { + .#{iv.$helpers-prefix}align-self-#{$value} { + align-self: $value !important; + } +} + +$flex-operators: grow, shrink; + +@each $operator in $flex-operators { + @for $i from 0 through 5 { + .#{iv.$helpers-prefix}flex-#{$operator}-#{$i} { + flex-#{$operator}: $i !important; + } + } +} diff --git a/web/assets/css/sass/helpers/float.scss b/web/assets/css/sass/helpers/float.scss new file mode 100644 index 0000000..6eecebe --- /dev/null +++ b/web/assets/css/sass/helpers/float.scss @@ -0,0 +1,28 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +.#{iv.$helpers-prefix}clearfix { + @include mx.clearfix; +} + +.#{iv.$helpers-prefix}float-left, +.#{iv.$helpers-prefix}pulled-left { + float: left !important; +} + +.#{iv.$helpers-prefix}float-right, +.#{iv.$helpers-prefix}pulled-right { + float: right !important; +} + +.#{iv.$helpers-prefix}float-none { + float: none !important; +} + +$clears: both left none right; + +@each $clear in $clears { + .#{iv.$helpers-prefix}clear-#{$clear} { + clear: $clear !important; + } +} diff --git a/web/assets/css/sass/helpers/gap.scss b/web/assets/css/sass/helpers/gap.scss new file mode 100644 index 0000000..cbff6c3 --- /dev/null +++ b/web/assets/css/sass/helpers/gap.scss @@ -0,0 +1,24 @@ +@use "sass:math"; +@use "sass:string"; +@use "../utilities/initial-variables" as iv; + +.#{iv.$helpers-prefix}gapless { + gap: 0 !important; +} + +$gaps: "gap", "column-gap", "row-gap"; +$gap-base: 0.5rem; + +@each $gap in $gaps { + @for $i from 0 through 8 { + .#{iv.$helpers-prefix}#{$gap}-#{$i} { + #{$gap}: ($gap-base * $i) !important; + } + + @if $i < 8 { + .#{iv.$helpers-prefix}#{$gap}-#{$i}\.5 { + #{$gap}: ($gap-base * $i + math.div($gap-base, 2)) !important; + } + } + } +} diff --git a/web/assets/css/sass/helpers/other.scss b/web/assets/css/sass/helpers/other.scss new file mode 100644 index 0000000..90e0edd --- /dev/null +++ b/web/assets/css/sass/helpers/other.scss @@ -0,0 +1,19 @@ +@use "../utilities/extends"; +@use "../utilities/initial-variables" as iv; + +.#{iv.$helpers-prefix}radiusless { + border-radius: 0 !important; +} + +.#{iv.$helpers-prefix}shadowless { + box-shadow: none !important; +} + +.#{iv.$helpers-prefix}clickable { + cursor: pointer !important; + pointer-events: all !important; +} + +.#{iv.$helpers-prefix}unselectable { + @extend %unselectable; +} diff --git a/web/assets/css/sass/helpers/overflow.scss b/web/assets/css/sass/helpers/overflow.scss new file mode 100644 index 0000000..f618600 --- /dev/null +++ b/web/assets/css/sass/helpers/overflow.scss @@ -0,0 +1,21 @@ +@use "../utilities/initial-variables" as iv; + +.#{iv.$helpers-prefix}clipped { + overflow: hidden !important; +} + +$overflows: auto clip hidden scroll visible; + +@each $overflow in $overflows { + .#{iv.$helpers-prefix}overflow-#{$overflow} { + overflow: $overflow !important; + } + + .#{iv.$helpers-prefix}overflow-x-#{$overflow} { + overflow-x: $overflow !important; + } + + .#{iv.$helpers-prefix}overflow-y-#{$overflow} { + overflow-y: $overflow !important; + } +} diff --git a/web/assets/css/sass/helpers/position.scss b/web/assets/css/sass/helpers/position.scss new file mode 100644 index 0000000..794b3d3 --- /dev/null +++ b/web/assets/css/sass/helpers/position.scss @@ -0,0 +1,19 @@ +@use "../utilities/extends"; +@use "../utilities/initial-variables" as iv; + +.#{iv.$helpers-prefix}overlay, +.#{iv.$helpers-prefix}overlay { + @extend %overlay; +} + +.#{iv.$helpers-prefix}relative { + position: relative !important; +} + +$positions: absolute fixed relative static sticky; + +@each $position in $positions { + .#{iv.$helpers-prefix}position-#{$position} { + position: $position !important; + } +} diff --git a/web/assets/css/sass/helpers/spacing.scss b/web/assets/css/sass/helpers/spacing.scss new file mode 100644 index 0000000..e825c6c --- /dev/null +++ b/web/assets/css/sass/helpers/spacing.scss @@ -0,0 +1,64 @@ +@use "../utilities/initial-variables" as iv; + +.marginless { + margin: 0 !important; +} + +.paddingless { + padding: 0 !important; +} + +$spacing-shortcuts: ( + "margin": "m", + "padding": "p", +) !default; +$spacing-directions: ( + "top": "t", + "right": "r", + "bottom": "b", + "left": "l", +) !default; +$spacing-horizontal: "x" !default; +$spacing-vertical: "y" !default; +$spacing-values: ( + "0": 0, + "1": 0.25rem, + "2": 0.5rem, + "3": 0.75rem, + "4": 1rem, + "5": 1.5rem, + "6": 3rem, + "auto": auto, +) !default; + +@each $property, $shortcut in $spacing-shortcuts { + @each $name, $value in $spacing-values { + // All directions + .#{$shortcut}-#{$name} { + #{$property}: $value !important; + } + + // Cardinal directions + @each $direction, $suffix in $spacing-directions { + .#{$shortcut}#{$suffix}-#{$name} { + #{$property}-#{$direction}: $value !important; + } + } + + // Horizontal axis + @if $spacing-horizontal != null { + .#{$shortcut}#{$spacing-horizontal}-#{$name} { + #{$property}-left: $value !important; + #{$property}-right: $value !important; + } + } + + // Vertical axis + @if $spacing-vertical != null { + .#{$shortcut}#{$spacing-vertical}-#{$name} { + #{$property}-top: $value !important; + #{$property}-bottom: $value !important; + } + } + } +} diff --git a/web/assets/css/sass/helpers/typography.scss b/web/assets/css/sass/helpers/typography.scss new file mode 100644 index 0000000..2f9d029 --- /dev/null +++ b/web/assets/css/sass/helpers/typography.scss @@ -0,0 +1,168 @@ +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +@mixin typography-size($target: "") { + @each $size in dv.$sizes { + $i: index(dv.$sizes, $size); + + .#{iv.$helpers-prefix}size-#{$i}#{if($target == "", "", "-" + $target)} { + font-size: $size !important; + } + } +} + +@include typography-size; + +@include mx.mobile { + @include typography-size("mobile"); +} + +@include mx.tablet { + @include typography-size("tablet"); +} + +@include mx.touch { + @include typography-size("touch"); +} + +@include mx.desktop { + @include typography-size("desktop"); +} + +@include mx.widescreen { + @include typography-size("widescreen"); +} + +@include mx.fullhd { + @include typography-size("fullhd"); +} + +$alignments: ( + "centered": "center", + "justified": "justify", + "left": "left", + "right": "right", +); + +@each $alignment, $text-align in $alignments { + .#{iv.$helpers-has-prefix}text-#{$alignment} { + text-align: #{$text-align} !important; + } +} + +@each $alignment, $text-align in $alignments { + @include mx.mobile { + .#{iv.$helpers-has-prefix}text-#{$alignment}-mobile { + text-align: #{$text-align} !important; + } + } + + @include mx.tablet { + .#{iv.$helpers-has-prefix}text-#{$alignment}-tablet { + text-align: #{$text-align} !important; + } + } + + @include mx.tablet-only { + .#{iv.$helpers-has-prefix}text-#{$alignment}-tablet-only { + text-align: #{$text-align} !important; + } + } + + @include mx.touch { + .#{iv.$helpers-has-prefix}text-#{$alignment}-touch { + text-align: #{$text-align} !important; + } + } + + @include mx.desktop { + .#{iv.$helpers-has-prefix}text-#{$alignment}-desktop { + text-align: #{$text-align} !important; + } + } + + @include mx.desktop-only { + .#{iv.$helpers-has-prefix}text-#{$alignment}-desktop-only { + text-align: #{$text-align} !important; + } + } + + @include mx.widescreen { + .#{iv.$helpers-has-prefix}text-#{$alignment}-widescreen { + text-align: #{$text-align} !important; + } + } + + @include mx.widescreen-only { + .#{iv.$helpers-has-prefix}text-#{$alignment}-widescreen-only { + text-align: #{$text-align} !important; + } + } + + @include mx.fullhd { + .#{iv.$helpers-has-prefix}text-#{$alignment}-fullhd { + text-align: #{$text-align} !important; + } + } +} + +.#{iv.$helpers-prefix}capitalized { + text-transform: capitalize !important; +} + +.#{iv.$helpers-prefix}lowercase { + text-transform: lowercase !important; +} + +.#{iv.$helpers-prefix}uppercase { + text-transform: uppercase !important; +} + +.#{iv.$helpers-prefix}italic { + font-style: italic !important; +} + +.#{iv.$helpers-prefix}underlined { + text-decoration: underline !important; +} + +.#{iv.$helpers-has-prefix}text-weight-light { + font-weight: iv.$weight-light !important; +} + +.#{iv.$helpers-has-prefix}text-weight-normal { + font-weight: iv.$weight-normal !important; +} + +.#{iv.$helpers-has-prefix}text-weight-medium { + font-weight: iv.$weight-medium !important; +} + +.#{iv.$helpers-has-prefix}text-weight-semibold { + font-weight: iv.$weight-semibold !important; +} + +.#{iv.$helpers-has-prefix}text-weight-bold { + font-weight: iv.$weight-bold !important; +} + +.#{iv.$helpers-prefix}family-primary { + font-family: dv.$family-primary !important; +} + +.#{iv.$helpers-prefix}family-secondary { + font-family: dv.$family-secondary !important; +} + +.#{iv.$helpers-prefix}family-sans-serif { + font-family: iv.$family-sans-serif !important; +} + +.#{iv.$helpers-prefix}family-monospace { + font-family: iv.$family-monospace !important; +} + +.#{iv.$helpers-prefix}family-code { + font-family: dv.$family-code !important; +} diff --git a/web/assets/css/sass/helpers/visibility.scss b/web/assets/css/sass/helpers/visibility.scss new file mode 100644 index 0000000..85124af --- /dev/null +++ b/web/assets/css/sass/helpers/visibility.scss @@ -0,0 +1,221 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +.#{iv.$helpers-prefix}display-none, +.#{iv.$helpers-prefix}hidden { + display: none !important; +} + +$displays: block flex inline inline-block inline-flex grid; + +@each $display in $displays { + .#{iv.$helpers-prefix}display-#{$display}, + .#{iv.$helpers-prefix}#{$display} { + display: $display !important; + } + + @include mx.mobile { + .#{iv.$helpers-prefix}display-#{$display}-mobile, + .#{iv.$helpers-prefix}#{$display}-mobile { + display: $display !important; + } + } + + @include mx.tablet { + .#{iv.$helpers-prefix}display-#{$display}-tablet, + .#{iv.$helpers-prefix}#{$display}-tablet { + display: $display !important; + } + } + + @include mx.tablet-only { + .#{iv.$helpers-prefix}display-#{$display}-tablet-only, + .#{iv.$helpers-prefix}#{$display}-tablet-only { + display: $display !important; + } + } + + @include mx.touch { + .#{iv.$helpers-prefix}display-#{$display}-touch, + .#{iv.$helpers-prefix}#{$display}-touch { + display: $display !important; + } + } + + @include mx.desktop { + .#{iv.$helpers-prefix}display-#{$display}-desktop, + .#{iv.$helpers-prefix}#{$display}-desktop { + display: $display !important; + } + } + + @include mx.desktop-only { + .#{iv.$helpers-prefix}display-#{$display}-desktop-only, + .#{iv.$helpers-prefix}#{$display}-desktop-only { + display: $display !important; + } + } + + @include mx.widescreen { + .#{iv.$helpers-prefix}display-#{$display}-widescreen, + .#{iv.$helpers-prefix}#{$display}-widescreen { + display: $display !important; + } + } + + @include mx.widescreen-only { + .#{iv.$helpers-prefix}display-#{$display}-widescreen-only, + .#{iv.$helpers-prefix}#{$display}-widescreen-only { + display: $display !important; + } + } + + @include mx.fullhd { + .#{iv.$helpers-prefix}display-#{$display}-fullhd, + .#{iv.$helpers-prefix}#{$display}-fullhd { + display: $display !important; + } + } +} + +.#{iv.$helpers-prefix}sr-only { + border: none !important; + clip: rect(0, 0, 0, 0) !important; + height: 0.01em !important; + overflow: hidden !important; + padding: 0 !important; + position: absolute !important; + white-space: nowrap !important; + width: 0.01em !important; +} + +@include mx.mobile { + .#{iv.$helpers-prefix}display-none-mobile, + .#{iv.$helpers-prefix}hidden-mobile { + display: none !important; + } +} + +@include mx.tablet { + .#{iv.$helpers-prefix}display-none-tablet, + .#{iv.$helpers-prefix}hidden-tablet { + display: none !important; + } +} + +@include mx.tablet-only { + .#{iv.$helpers-prefix}display-none-tablet-only, + .#{iv.$helpers-prefix}hidden-tablet-only { + display: none !important; + } +} + +@include mx.touch { + .#{iv.$helpers-prefix}display-none-touch, + .#{iv.$helpers-prefix}hidden-touch { + display: none !important; + } +} + +@include mx.desktop { + .#{iv.$helpers-prefix}display-none-desktop, + .#{iv.$helpers-prefix}hidden-desktop { + display: none !important; + } +} + +@include mx.desktop-only { + .#{iv.$helpers-prefix}display-none-desktop-only, + .#{iv.$helpers-prefix}hidden-desktop-only { + display: none !important; + } +} + +@include mx.widescreen { + .#{iv.$helpers-prefix}display-none-widescreen, + .#{iv.$helpers-prefix}hidden-widescreen { + display: none !important; + } +} + +@include mx.widescreen-only { + .#{iv.$helpers-prefix}display-none-widescreen-only, + .#{iv.$helpers-prefix}hidden-widescreen-only { + display: none !important; + } +} + +@include mx.fullhd { + .#{iv.$helpers-prefix}display-none-fullhd, + .#{iv.$helpers-prefix}hidden-fullhd { + display: none !important; + } +} + +.#{iv.$helpers-prefix}visibility-hidden, +.#{iv.$helpers-prefix}invisible { + visibility: hidden !important; +} + +@include mx.mobile { + .#{iv.$helpers-prefix}visibility-hidden-mobile, + .#{iv.$helpers-prefix}invisible-mobile { + visibility: hidden !important; + } +} + +@include mx.tablet { + .#{iv.$helpers-prefix}visibility-hidden-tablet, + .#{iv.$helpers-prefix}invisible-tablet { + visibility: hidden !important; + } +} + +@include mx.tablet-only { + .#{iv.$helpers-prefix}visibility-hidden-tablet-only, + .#{iv.$helpers-prefix}invisible-tablet-only { + visibility: hidden !important; + } +} + +@include mx.touch { + .#{iv.$helpers-prefix}visibility-hidden-touch, + .#{iv.$helpers-prefix}invisible-touch { + visibility: hidden !important; + } +} + +@include mx.desktop { + .#{iv.$helpers-prefix}visibility-hidden-desktop, + .#{iv.$helpers-prefix}invisible-desktop { + visibility: hidden !important; + } +} + +@include mx.desktop-only { + .#{iv.$helpers-prefix}visibility-hidden-desktop-only, + .#{iv.$helpers-prefix}invisible-desktop-only { + visibility: hidden !important; + } +} + +@include mx.widescreen { + .#{iv.$helpers-prefix}visibility-hidden-widescreen, + .#{iv.$helpers-prefix}invisible-widescreen { + visibility: hidden !important; + } +} + +@include mx.widescreen-only { + .#{iv.$helpers-prefix}visibility-hidden-widescreen-only, + .#{iv.$helpers-prefix}invisible-widescreen-only { + visibility: hidden !important; + } +} + +@include mx.fullhd { + .#{iv.$helpers-prefix}visibility-hidden-fullhd, + .#{iv.$helpers-prefix}invisible-fullhd { + visibility: hidden !important; + } +} diff --git a/web/assets/css/sass/layout/_index.scss b/web/assets/css/sass/layout/_index.scss new file mode 100644 index 0000000..c28494d --- /dev/null +++ b/web/assets/css/sass/layout/_index.scss @@ -0,0 +1,9 @@ +/* Bulma Components */ +@charset "utf-8"; + +@forward "container"; +@forward "footer"; +@forward "hero"; +@forward "level"; +@forward "media"; +@forward "section"; diff --git a/web/assets/css/sass/layout/container.scss b/web/assets/css/sass/layout/container.scss new file mode 100644 index 0000000..a04a1b8 --- /dev/null +++ b/web/assets/css/sass/layout/container.scss @@ -0,0 +1,51 @@ +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +$container-offset: 2 * iv.$gap !default; +$container-max-width: iv.$fullhd !default; + +.#{iv.$class-prefix}container { + flex-grow: 1; + margin: 0 auto; + position: relative; + width: 100%; + + &.#{iv.$class-prefix}is-fluid { + max-width: none !important; + padding-left: iv.$gap; + padding-right: iv.$gap; + width: 100%; + } + + @include mx.desktop { + max-width: iv.$desktop - $container-offset; + } + + @include mx.until-widescreen { + &.#{iv.$class-prefix}is-widescreen:not(.#{iv.$class-prefix}is-max-desktop) { + max-width: min(iv.$widescreen, $container-max-width) - $container-offset; + } + } + + @include mx.until-fullhd { + &.#{iv.$class-prefix}is-fullhd:not(.#{iv.$class-prefix}is-max-desktop):not( + .#{iv.$class-prefix}is-max-widescreen + ) { + max-width: min(iv.$fullhd, $container-max-width) - $container-offset; + } + } + + @include mx.widescreen { + &:not(.#{iv.$class-prefix}is-max-desktop) { + max-width: min(iv.$widescreen, $container-max-width) - $container-offset; + } + } + + @include mx.fullhd { + &:not(.#{iv.$class-prefix}is-max-desktop):not( + .#{iv.$class-prefix}is-max-widescreen + ) { + max-width: min(iv.$fullhd, $container-max-width) - $container-offset; + } + } +} diff --git a/web/assets/css/sass/layout/footer.scss b/web/assets/css/sass/layout/footer.scss new file mode 100644 index 0000000..bc9b6c8 --- /dev/null +++ b/web/assets/css/sass/layout/footer.scss @@ -0,0 +1,23 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; + +$footer-background-color: cv.getVar("scheme-main-bis") !default; +$footer-color: false !default; +$footer-padding: 3rem 1.5rem 6rem !default; + +.#{iv.$class-prefix}footer { + @include cv.register-vars( + ( + "footer-background-color": #{$footer-background-color}, + "footer-color": #{$footer-color}, + "footer-padding": #{$footer-padding}, + ) + ); + + background-color: cv.getVar("footer-background-color"); + padding: cv.getVar("footer-padding"); + + @if $footer-color { + color: cv.getVar("footer-color"); + } +} diff --git a/web/assets/css/sass/layout/hero.scss b/web/assets/css/sass/layout/hero.scss new file mode 100644 index 0000000..3cd1cfd --- /dev/null +++ b/web/assets/css/sass/layout/hero.scss @@ -0,0 +1,270 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/extends"; +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +$hero-body-padding: 3rem 1.5rem !default; +$hero-body-padding-tablet: 3rem 3rem !default; +$hero-body-padding-small: 1.5rem !default; +$hero-body-padding-medium: 9rem 4.5rem !default; +$hero-body-padding-large: 18rem 6rem !default; + +$hero-gradient-h-offset: 5deg; +$hero-gradient-s-offset: 10%; +$hero-gradient-l-offset: 5%; + +$hero-colors: dv.$colors !default; + +// Main container +.#{iv.$class-prefix}hero { + @include cv.register-vars( + ( + "hero-body-padding": #{$hero-body-padding}, + "hero-body-padding-tablet": #{$hero-body-padding-tablet}, + "hero-body-padding-small": #{$hero-body-padding-small}, + "hero-body-padding-medium": #{$hero-body-padding-medium}, + "hero-body-padding-large": #{$hero-body-padding-large}, + ) + ); +} + +.#{iv.$class-prefix}hero { + align-items: stretch; + display: flex; + flex-direction: column; + justify-content: space-between; + + .#{iv.$class-prefix}navbar { + background: none; + } + + .#{iv.$class-prefix}tabs { + ul { + border-bottom: none; + } + } + + // Colors + @each $name, $pair in $hero-colors { + &.#{iv.$class-prefix}is-#{$name} { + @include cv.register-vars( + ( + "hero-h": #{cv.getVar($name, "", "-h")}, + "hero-s": #{cv.getVar($name, "", "-s")}, + "hero-background-l": #{cv.getVar($name, "", "-l")}, + "hero-color-l": #{cv.getVar($name, "", "-invert-l")}, + ) + ); + + $background-color: hsl( + #{cv.getVar("hero-h")}, + #{cv.getVar("hero-s")}, + #{cv.getVar("hero-background-l")} + ); + $color: hsl( + #{cv.getVar("hero-h")}, + #{cv.getVar("hero-s")}, + #{cv.getVar("hero-color-l")} + ); + + background-color: hsl( + #{cv.getVar("hero-h")}, + #{cv.getVar("hero-s")}, + #{cv.getVar("hero-background-l")} + ); + color: $color; + + .#{iv.$class-prefix}navbar { + @include cv.register-vars( + ( + "navbar-item-color": $color, + "navbar-item-hover-background-color": $color, + "navbar-item-hover-color": $background-color, + "navbar-item-active-background-color": $color, + "navbar-item-active-color": $background-color, + ) + ); + } + + .#{iv.$class-prefix}tabs { + @include cv.register-vars( + ( + "tabs-link-color": $color, + "tabs-boxed-link-active-background-color": $color, + "tabs-boxed-link-active-border-color": $background-color, + "tabs-link-active-color": $background-color, + ) + ); + } + + .#{iv.$class-prefix}subtitle { + @include cv.register-vars( + ( + "subtitle-color": $color, + "subtitle-strong-color": $color, + ) + ); + } + + .#{iv.$class-prefix}title { + @include cv.register-vars( + ( + "title-color": $color, + "title-strong-color": $color, + ) + ); + } + + // Modifiers + &.#{iv.$class-prefix}is-bold { + $gradient-top-left: hsl( + calc(#{cv.getVar("hero-h")} - $hero-gradient-h-offset), + calc(#{cv.getVar("hero-s")} + $hero-gradient-s-offset), + calc(#{cv.getVar("hero-background-l")} + $hero-gradient-l-offset) + ); + $gradient-middle: hsl( + #{cv.getVar("hero-h")}, + #{cv.getVar("hero-s")}, + #{cv.getVar("hero-background-l")} + ); + $gradient-bottom-right: hsl( + calc(#{cv.getVar("hero-h")} + $hero-gradient-h-offset), + calc(#{cv.getVar("hero-s")} - $hero-gradient-s-offset), + calc(#{cv.getVar("hero-background-l")} - $hero-gradient-l-offset) + ); + + background-image: linear-gradient( + 141deg, + $gradient-top-left 0%, + $gradient-middle 71%, + $gradient-bottom-right 100% + ); + + @include mx.mobile { + .#{iv.$class-prefix}navbar-menu { + background-image: linear-gradient( + 141deg, + $gradient-top-left 0%, + $color 71%, + $gradient-bottom-right 100% + ); + } + } + } + } + } + + // Sizes + &.#{iv.$class-prefix}is-small { + .#{iv.$class-prefix}hero-body { + padding: cv.getVar("hero-body-padding-small"); + } + } + + &.#{iv.$class-prefix}is-medium { + @include mx.tablet { + .#{iv.$class-prefix}hero-body { + padding: cv.getVar("hero-body-padding-medium"); + } + } + } + + &.#{iv.$class-prefix}is-large { + @include mx.tablet { + .#{iv.$class-prefix}hero-body { + padding: cv.getVar("hero-body-padding-large"); + } + } + } + + &.#{iv.$class-prefix}is-halfheight, + &.#{iv.$class-prefix}is-fullheight, + &.#{iv.$class-prefix}is-fullheight-with-navbar { + .#{iv.$class-prefix}hero-body { + align-items: center; + display: flex; + + & > .#{iv.$class-prefix}container { + flex-grow: 1; + flex-shrink: 1; + } + } + } + + &.#{iv.$class-prefix}is-halfheight { + min-height: 50vh; + } + + &.#{iv.$class-prefix}is-fullheight { + min-height: 100vh; + } +} + +// Components + +.#{iv.$class-prefix}hero-video { + @extend %overlay; + overflow: hidden; + + video { + left: 50%; + min-height: 100%; + min-width: 100%; + position: absolute; + top: 50%; + transform: translate3d(-50%, -50%, 0); + } + + // Modifiers + &.#{iv.$class-prefix}is-transparent { + opacity: 0.3; + } + + // Responsiveness + @include mx.mobile { + display: none; + } +} + +.#{iv.$class-prefix}hero-buttons { + margin-top: 1.5rem; + + // Responsiveness + @include mx.mobile { + .#{iv.$class-prefix}button { + display: flex; + + &:not(:last-child) { + margin-bottom: 0.75rem; + } + } + } + + @include mx.tablet { + display: flex; + justify-content: center; + + .#{iv.$class-prefix}button:not(:last-child) { + margin-inline-end: 1.5rem; + } + } +} + +// Containers + +.#{iv.$class-prefix}hero-head, +.#{iv.$class-prefix}hero-foot { + flex-grow: 0; + flex-shrink: 0; +} + +.#{iv.$class-prefix}hero-body { + flex-grow: 1; + flex-shrink: 0; + padding: cv.getVar("hero-body-padding"); + + @include mx.tablet { + padding: cv.getVar("hero-body-padding-tablet"); + } +} diff --git a/web/assets/css/sass/layout/level.scss b/web/assets/css/sass/layout/level.scss new file mode 100644 index 0000000..dbb5a47 --- /dev/null +++ b/web/assets/css/sass/layout/level.scss @@ -0,0 +1,107 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$level-item-spacing: calc(#{cv.getVar("block-spacing")} * 0.5) !default; + +.#{iv.$class-prefix}level { + @extend %block; + @include cv.register-var("level-item-spacing", #{$level-item-spacing}); + align-items: center; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: cv.getVar("level-item-spacing"); + + code { + border-radius: cv.getVar("radius"); + } + + img { + display: inline-block; + vertical-align: top; + } + + // Modifiers + &.#{iv.$class-prefix}is-mobile { + display: flex; + flex-direction: row; + + .#{iv.$class-prefix}level-left, + .#{iv.$class-prefix}level-right { + display: flex; + } + + .#{iv.$class-prefix}level-item { + &:not(.#{iv.$class-prefix}is-narrow) { + flex-grow: 1; + } + } + } + + // Responsiveness + @include mx.tablet { + display: flex; + flex-direction: row; + + & > .#{iv.$class-prefix}level-item { + &:not(.#{iv.$class-prefix}is-narrow) { + flex-grow: 1; + } + } + } +} + +.#{iv.$class-prefix}level-item { + align-items: center; + display: flex; + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + + .#{iv.$class-prefix}title, + .#{iv.$class-prefix}subtitle { + margin-bottom: 0; + } +} + +.#{iv.$class-prefix}level-left, +.#{iv.$class-prefix}level-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; + gap: $level-item-spacing; + + .#{iv.$class-prefix}level-item { + // Modifiers + &.#{iv.$class-prefix}is-flexible { + flex-grow: 1; + } + } +} + +.#{iv.$class-prefix}level-left { + align-items: center; + display: flex; + flex-direction: column; + justify-content: flex-start; + + // Responsiveness + @include mx.tablet { + flex-direction: row; + } +} + +.#{iv.$class-prefix}level-right { + align-items: center; + display: flex; + flex-direction: column; + justify-content: flex-end; + + // Responsiveness + @include mx.tablet { + flex-direction: row; + } +} diff --git a/web/assets/css/sass/layout/media.scss b/web/assets/css/sass/layout/media.scss new file mode 100644 index 0000000..e65ced8 --- /dev/null +++ b/web/assets/css/sass/layout/media.scss @@ -0,0 +1,106 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/extends"; +@use "../utilities/mixins" as mx; + +$media-border-color: hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("border-l")}, + 0.5 +) !default; +$media-border-size: 1px !default; +$media-spacing: 1rem !default; +$media-spacing-large: 1.5rem !default; +$media-content-spacing: 0.75rem !default; +$media-level-1-spacing: 0.75rem !default; +$media-level-1-content-spacing: 0.5rem !default; +$media-level-2-spacing: 0.5rem !default; + +.#{iv.$class-prefix}media { + @extend %block; + @include cv.register-vars( + ( + "media-border-color": #{$media-border-color}, + "media-border-size": #{$media-border-size}, + "media-spacing": #{$media-spacing}, + "media-spacing-large": #{$media-spacing-large}, + "media-content-spacing": #{$media-content-spacing}, + "media-level-1-spacing": #{$media-level-1-spacing}, + "media-level-1-content-spacing": #{$media-level-1-content-spacing}, + "media-level-2-spacing": #{$media-level-2-spacing}, + ) + ); + align-items: flex-start; + display: flex; + text-align: inherit; + + .#{iv.$class-prefix}content:not(:last-child) { + margin-bottom: cv.getVar("media-content-spacing"); + } + + .#{iv.$class-prefix}media { + border-top-color: cv.getVar("media-border-color"); + border-top-style: solid; + border-top-width: cv.getVar("media-border-size"); + display: flex; + padding-top: cv.getVar("media-level-1-spacing"); + + .#{iv.$class-prefix}content:not(:last-child), + .#{iv.$class-prefix}control:not(:last-child) { + margin-bottom: cv.getVar("media-level-1-content-spacing"); + } + + .#{iv.$class-prefix}media { + padding-top: cv.getVar("media-level-2-spacing"); + + & + .#{iv.$class-prefix}media { + margin-top: cv.getVar("media-level-2-spacing"); + } + } + } + + & + .#{iv.$class-prefix}media { + border-top-color: cv.getVar("media-border-color"); + border-top-style: solid; + border-top-width: cv.getVar("media-border-size"); + margin-top: cv.getVar("media-spacing"); + padding-top: cv.getVar("media-spacing"); + } + + // Sizes + &.#{iv.$class-prefix}is-large { + & + .#{iv.$class-prefix}media { + margin-top: cv.getVar("media-spacing-large"); + padding-top: cv.getVar("media-spacing-large"); + } + } +} + +.#{iv.$class-prefix}media-left, +.#{iv.$class-prefix}media-right { + flex-basis: auto; + flex-grow: 0; + flex-shrink: 0; +} + +.#{iv.$class-prefix}media-left { + margin-inline-end: cv.getVar("media-spacing"); +} + +.#{iv.$class-prefix}media-right { + margin-inline-start: cv.getVar("media-spacing"); +} + +.#{iv.$class-prefix}media-content { + flex-basis: auto; + flex-grow: 1; + flex-shrink: 1; + text-align: inherit; +} + +@include mx.mobile { + .#{iv.$class-prefix}media-content { + overflow-x: auto; + } +} diff --git a/web/assets/css/sass/layout/section.scss b/web/assets/css/sass/layout/section.scss new file mode 100644 index 0000000..9d9bd5a --- /dev/null +++ b/web/assets/css/sass/layout/section.scss @@ -0,0 +1,34 @@ +@use "../utilities/css-variables" as cv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/mixins" as mx; + +$section-padding: 3rem 1.5rem !default; +$section-padding-desktop: 3rem 3rem !default; +$section-padding-medium: 9rem 4.5rem !default; +$section-padding-large: 18rem 6rem !default; + +.#{iv.$class-prefix}section { + @include cv.register-vars( + ( + "section-padding": #{$section-padding}, + "section-padding-desktop": #{$section-padding-desktop}, + "section-padding-medium": #{$section-padding-medium}, + "section-padding-large": #{$section-padding-large}, + ) + ); + padding: cv.getVar("section-padding"); + + // Responsiveness + @include mx.desktop { + padding: cv.getVar("section-padding-desktop"); + + // Sizes + &.#{iv.$class-prefix}is-medium { + padding: cv.getVar("section-padding-medium"); + } + + &.#{iv.$class-prefix}is-large { + padding: cv.getVar("section-padding-large"); + } + } +} diff --git a/web/assets/css/sass/themes/_index.scss b/web/assets/css/sass/themes/_index.scss new file mode 100644 index 0000000..d4168f5 --- /dev/null +++ b/web/assets/css/sass/themes/_index.scss @@ -0,0 +1,35 @@ +/* Bulma Themes */ +@charset "utf-8"; + +@use "../utilities/css-variables" as cv; + +@use "light"; +@use "dark"; +@use "setup"; + +:root { + @include light.light-theme; + @include setup.setup-theme; +} + +// prefers-color-scheme: light +@include cv.system-theme($name: "light") { + @include light.light-theme; +} + +// prefers-color-scheme: dark +@include cv.system-theme($name: "dark") { + @include dark.dark-theme; +} + +// :root, [data-theme=light], .theme-light +@include cv.bulma-theme($name: "light") { + @include light.light-theme; + @include setup.setup-theme; +} + +// [data-theme=dark], .theme-dark +@include cv.bulma-theme($name: "dark") { + @include dark.dark-theme; + @include setup.setup-theme; +} diff --git a/web/assets/css/sass/themes/dark.scss b/web/assets/css/sass/themes/dark.scss new file mode 100644 index 0000000..65cf947 --- /dev/null +++ b/web/assets/css/sass/themes/dark.scss @@ -0,0 +1,56 @@ +@use "sass:list"; + +@use "../utilities/initial-variables" as iv; +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "setup"; + +// The main lightness of this theme +$scheme-main-l: 9%; +$background-l: 14%; +$text-l: 71%; + +// The main scheme color, used to make calculations +$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l); +$background: hsl(iv.$scheme-h, iv.$scheme-s, $background-l); +$text: hsl(iv.$scheme-h, iv.$scheme-s, $text-l); + +@mixin dark-theme { + @each $name, $color in dv.$colors { + $base: $color; + + @if type-of($color == "list") { + $base: list.nth($color, 1); + } + + @include cv.generate-on-scheme-colors($name, $base, $scheme-main); + } + + @include cv.register-vars( + ( + "scheme-brightness": "dark", + "scheme-main-l": $scheme-main-l, + "scheme-main-bis-l": $scheme-main-l + 2%, + "scheme-main-ter-l": $scheme-main-l + 4%, + "soft-l": iv.$dark-l, + "bold-l": iv.$light-l, + "soft-invert-l": iv.$light-l, + "bold-invert-l": iv.$dark-l, + "background-l": $background-l, + "border-weak-l": 21%, + "border-l": 24%, + "text-weak-l": 53%, + "text-l": $text-l, + "text-strong-l": 93%, + "text-title-l": 100%, + "hover-background-l-delta": 5%, + "active-background-l-delta": 10%, + "hover-border-l-delta": 10%, + "active-border-l-delta": 20%, + "hover-color-l-delta": 5%, + "active-color-l-delta": 10%, + ) + ); + + @include cv.register-hsl("shadow", white); +} diff --git a/web/assets/css/sass/themes/light.scss b/web/assets/css/sass/themes/light.scss new file mode 100644 index 0000000..67f94c7 --- /dev/null +++ b/web/assets/css/sass/themes/light.scss @@ -0,0 +1,145 @@ +@use "sass:list"; + +@use "../utilities/css-variables" as cv; +@use "../utilities/derived-variables" as dv; +@use "../utilities/initial-variables" as iv; +@use "../utilities/functions" as fn; +@use "setup"; + +// The main lightness of this theme +$scheme-main-l: 100%; + +// The main scheme color, used to make calculations +$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l); + +@mixin light-theme { + @include cv.register-vars( + ( + "scheme-h": iv.$scheme-h, + "scheme-s": iv.$scheme-s, + "light-l": iv.$light-l, + "light-invert-l": iv.$dark-l, + "dark-l": iv.$dark-l, + "dark-invert-l": iv.$light-l, + "soft-l": iv.$light-l, + "bold-l": iv.$dark-l, + "soft-invert-l": iv.$dark-l, + "bold-invert-l": iv.$light-l, + + // Deltas + "hover-background-l-delta": -5%, + "active-background-l-delta": -10%, + + "hover-border-l-delta": -10%, + "active-border-l-delta": -20%, + + "hover-color-l-delta": -5%, + "active-color-l-delta": -10%, + + "hover-shadow-a-delta": -0.05, + "active-shadow-a-delta": -0.1, + + // Light only + "scheme-brightness": "light", + "scheme-main-l": $scheme-main-l, + "scheme-main-bis-l": 98%, + "scheme-main-ter-l": 96%, + "background-l": 96%, + "border-weak-l": 93%, + "border-l": 86%, + "text-weak-l": 48%, + "text-l": 29%, + "text-strong-l": 21%, + "text-title-l": 14%, + "scheme-invert-ter-l": 14%, + "scheme-invert-bis-l": 7%, + "scheme-invert-l": 4%, + + // Typography + "family-primary": dv.$family-primary, + "family-secondary": dv.$family-secondary, + "family-code": dv.$family-code, + "size-small": dv.$size-small, + "size-normal": dv.$size-normal, + "size-medium": dv.$size-medium, + "size-large": dv.$size-large, + "weight-light": iv.$weight-light, + "weight-normal": iv.$weight-normal, + "weight-medium": iv.$weight-medium, + "weight-semibold": iv.$weight-semibold, + "weight-bold": iv.$weight-bold, + "weight-extrabold": iv.$weight-extrabold, + + // Other + "block-spacing": iv.$block-spacing, + "duration": 294ms, + "easing": ease-out, + "radius-small": iv.$radius-small, + "radius": iv.$radius, + "radius-medium": iv.$radius-medium, + "radius-large": iv.$radius-large, + "radius-rounded": 9999px, + "speed": 86ms, + + "loading-color": #{cv.getVar("border")}, + "burger-h": #{cv.getVar("link-h")}, + "burger-s": #{cv.getVar("link-s")}, + "burger-l": #{cv.getVar("link-l")}, + "burger-border-radius": 0.5em, + // Using px values to prevent half pixel issues + "burger-gap": 5px, + "burger-item-height": 2px, + "burger-item-width": 20px, + ) + ); + + // Colors + $no-palette: ("white", "black", "light", "dark"); + + @each $name, $color in dv.$colors { + $base: $color; + $invert: null; + $light: null; + $dark: null; + + @if type-of($color == "list") { + $base: list.nth($color, 1); + + @if list.length($color) > 3 { + $invert: list.nth($color, 2); + $light: list.nth($color, 3); + $dark: list.nth($color, 4); + } @else if list.length($color) > 1 { + $invert: list.nth($color, 2); + } + } + + @if list.index($no-palette, $name) { + @include cv.generate-basic-palette($name, $base, $invert); + } @else { + @include cv.generate-color-palette( + $name, + $base, + $scheme-main-l, + $invert, + $light, + $dark + ); + } + + @include cv.generate-on-scheme-colors($name, $base, $scheme-main); + } + + // Shades + @each $name, $shade in dv.$shades { + @include cv.register-var($name, $shade); + } + + @include cv.register-hsl("shadow", dv.$shadow-color); + + @each $size in dv.$sizes { + $i: index(dv.$sizes, $size); + $name: "size-#{$i}"; + @include cv.register-var($name, $size); + } +} diff --git a/web/assets/css/sass/themes/setup.scss b/web/assets/css/sass/themes/setup.scss new file mode 100644 index 0000000..6caddf7 --- /dev/null +++ b/web/assets/css/sass/themes/setup.scss @@ -0,0 +1,174 @@ +@use "../utilities/css-variables" as cv; + +@mixin setup-theme() { + @include cv.register-vars( + ( + // Computed + "scheme-main": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-main-l")} + ), + "scheme-main-bis": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-main-bis-l")} + ), + "scheme-main-ter": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-main-ter-l")} + ), + "background": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("background-l")} + ), + "background-hover": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + calc( + #{cv.getVar("background-l")} + #{cv.getVar( + "hover-background-l-delta" + )} + ) + ), + "background-active": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + calc( + #{cv.getVar("background-l")} + #{cv.getVar( + "active-background-l-delta" + )} + ) + ), + "border-weak": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("border-weak-l")} + ), + "border": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("border-l")} + ), + "border-hover": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + calc(#{cv.getVar("border-l")} + #{cv.getVar("hover-border-l-delta")}) + ), + "border-active": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + calc(#{cv.getVar("border-l")} + #{cv.getVar("active-border-l-delta")}) + ), + "text-weak": + hsl( + #{cv.getVar("text-h")}, + #{cv.getVar("text-s")}, + #{cv.getVar("text-weak-l")} + ), + "text": + hsl( + #{cv.getVar("text-h")}, + #{cv.getVar("text-s")}, + #{cv.getVar("text-l")} + ), + "text-strong": + hsl( + #{cv.getVar("text-h")}, + #{cv.getVar("text-s")}, + #{cv.getVar("text-strong-l")} + ), + "scheme-invert-ter": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-ter-l")} + ), + "scheme-invert-bis": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-bis-l")} + ), + "scheme-invert": + hsl( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("scheme-invert-l")} + ), + "link": + hsl( + #{cv.getVar("link-h")}, + #{cv.getVar("link-s")}, + #{cv.getVar("link-l")} + ), + "link-text": + hsl( + #{cv.getVar("link-h")}, + #{cv.getVar("link-s")}, + #{cv.getVar("link-on-scheme-l")} + ), + "link-text-hover": + hsl( + #{cv.getVar("link-h")}, + #{cv.getVar("link-s")}, + calc( + #{cv.getVar("link-on-scheme-l")} + #{cv.getVar( + "hover-color-l-delta" + )} + ) + ), + "link-text-active": + hsl( + #{cv.getVar("link-h")}, + #{cv.getVar("link-s")}, + calc( + #{cv.getVar("link-on-scheme-l")} + #{cv.getVar( + "active-color-l-delta" + )} + ) + ), + "focus-h": #{cv.getVar("link-h")}, + "focus-s": #{cv.getVar("link-s")}, + "focus-l": #{cv.getVar("link-l")}, + "focus-offset": 1px, + "focus-style": solid, + "focus-width": 2px, + "focus-shadow-size": 0 0 0 0.1875em, + "focus-shadow-alpha": 0.25, + "code": + hsl( + #{cv.getVar("danger-h")}, + #{cv.getVar("danger-s")}, + #{cv.getVar("danger-on-scheme-l")} + ), + "code-background": #{cv.getVar("background")}, + "pre": #{cv.getVar("text")}, + "pre-background": #{cv.getVar("background")}, + "shadow": ( + 0 0.5em 1em -0.125em hsla(#{cv.getVar("shadow-h")}, #{cv.getVar( + "shadow-s" + )}, #{cv.getVar("shadow-l")}, 0.1), + 0 0px 0 1px + hsla( + #{cv.getVar("shadow-h")}, + #{cv.getVar("shadow-s")}, + #{cv.getVar("shadow-l")}, + 0.02 + ) + ) + ) + ); +} diff --git a/web/assets/css/sass/utilities/_index.scss b/web/assets/css/sass/utilities/_index.scss new file mode 100644 index 0000000..12e06bc --- /dev/null +++ b/web/assets/css/sass/utilities/_index.scss @@ -0,0 +1,7 @@ +/* Bulma Utilities */ +@charset "utf-8"; + +@forward "initial-variables"; +@forward "functions"; +@forward "derived-variables"; +@forward "controls"; diff --git a/web/assets/css/sass/utilities/controls.scss b/web/assets/css/sass/utilities/controls.scss new file mode 100644 index 0000000..5ad16dd --- /dev/null +++ b/web/assets/css/sass/utilities/controls.scss @@ -0,0 +1,85 @@ +@use "css-variables" as cv; +@use "derived-variables" as dv; +@use "initial-variables" as iv; + +$control-radius: cv.getVar("radius") !default; +$control-radius-small: cv.getVar("radius-small") !default; + +$control-border-width: 1px !default; +$control-size: cv.getVar("size-normal") !default; + +$control-height: 2.5em !default; +$control-line-height: 1.5 !default; + +$control-padding-vertical: calc(0.5em - #{$control-border-width}) !default; +$control-padding-horizontal: calc(0.75em - #{$control-border-width}) !default; + +$control-focus-shadow-l: 50% !default; + +:root { + @include cv.register-vars( + ( + "control-radius": #{$control-radius}, + "control-radius-small": #{$control-radius-small}, + "control-border-width": #{$control-border-width}, + "control-height": #{$control-height}, + "control-line-height": #{$control-line-height}, + "control-padding-vertical": #{$control-padding-vertical}, + "control-padding-horizontal": #{$control-padding-horizontal}, + "control-size": #{$control-size}, + "control-focus-shadow-l": #{$control-focus-shadow-l}, + ) + ); +} + +@mixin control { + align-items: center; + appearance: none; + border-color: transparent; + border-style: solid; + border-width: cv.getVar("control-border-width"); + border-radius: cv.getVar("control-radius"); + box-shadow: none; + display: inline-flex; + font-size: cv.getVar("control-size"); + height: cv.getVar("control-height"); + justify-content: flex-start; + line-height: cv.getVar("control-line-height"); + padding-bottom: cv.getVar("control-padding-vertical"); + padding-left: cv.getVar("control-padding-horizontal"); + padding-right: cv.getVar("control-padding-horizontal"); + padding-top: cv.getVar("control-padding-vertical"); + position: relative; + transition-duration: cv.getVar("duration"); + transition-property: background-color, border-color, box-shadow, color; + vertical-align: top; + + // States + &:focus, + &:focus-visible, + &:focus-within, + &.#{iv.$class-prefix}is-focused, + &:active, + &.#{iv.$class-prefix}is-active { + outline: none; + } + + &[disabled], + fieldset[disabled] & { + cursor: not-allowed; + } +} + +// The controls sizes use mixins so they can be used at different breakpoints +@mixin control-small { + border-radius: $control-radius-small; + font-size: cv.getVar("size-small"); +} + +@mixin control-medium { + font-size: cv.getVar("size-medium"); +} + +@mixin control-large { + font-size: cv.getVar("size-large"); +} diff --git a/web/assets/css/sass/utilities/css-variables.scss b/web/assets/css/sass/utilities/css-variables.scss new file mode 100644 index 0000000..31feb61 --- /dev/null +++ b/web/assets/css/sass/utilities/css-variables.scss @@ -0,0 +1,425 @@ +@use "sass:color"; +@use "sass:list"; +@use "sass:map"; +@use "sass:math"; + +@use "initial-variables" as iv; +@use "functions" as fn; + +@function buildVarName($name, $prefix: "", $suffix: "") { + @return "--#{iv.$cssvars-prefix}#{$prefix}#{$name}#{$suffix}"; +} + +@function buildHslaString($name, $l, $a: 1) { + $lightness: getVar($name, "", "-l"); + @if ($l) { + $lightness: $l; + } + @return "hsla(#{getVar($name, '', '-h')}, #{getVar($name, '', '-s')}, #{$lightness}, #{$a})"; +} + +@function getVar($name, $prefix: "", $suffix: "") { + $varName: buildVarName($name, $prefix, $suffix); + @return var(#{$varName}); +} + +@function getVarWithBackup($name, $backup, $prefix: "", $suffix: "") { + $varName: buildVarName($name, $prefix, $suffix); + $backupName: buildVarName($backup, $prefix, $suffix); + @return var(#{$varName}, var(#{$backupName})); +} + +@function getRgbaVar($name, $alpha, $prefix: "", $suffix: "") { + $varName: buildVarName($name, $prefix, $suffix); + @return unquote("rgba(var(#{$varName}), #{$alpha})"); +} + +@mixin register-var($name, $value, $prefix: "", $suffix: "") { + $varName: buildVarName($name, $prefix, $suffix); + #{$varName}: #{$value}; +} + +@mixin register-vars($vars, $prefix: "", $suffix: "") { + @each $name, $value in $vars { + @include register-var($name, $value, $prefix, $suffix); + } +} + +@mixin register-rgb($name, $value) { + @include register-var( + $name, + (red($value), green($value), blue($value)), + "", + "-rgb" + ); +} + +@mixin register-hsl($name, $value) { + @include register-var($name, round(hue($value)), "", "-h"); + @include register-var($name, round(saturation($value)), "", "-s"); + @include register-var($name, round(lightness($value)), "", "-l"); +} + +@mixin generate-on-scheme-colors($name, $base, $scheme-main) { + // Accessibility Contrast System + $scheme-main-brightness: fn.bulmaColorBrightness($scheme-main); + $on-scheme-color: $base; + $fg-lum: fn.bulmaColorLuminance($on-scheme-color); + $bg-lum: fn.bulmaColorLuminance($scheme-main); + $ratio: 0; + $found-decent-color: false; + + @if ($fg-lum > $bg-lum) { + @for $i from 0 through 20 { + $ratio: math.div(($fg-lum + 0.05), ($bg-lum + 0.05)); + + @if $ratio > 5 { + $found-decent-color: true; + } @else { + $on-scheme-color: lighten($on-scheme-color, 5%); + $fg-lum: fn.bulmaColorLuminance($on-scheme-color); + } + } + } @else { + @for $i from 0 through 20 { + $ratio: math.div(($bg-lum + 0.05), ($fg-lum + 0.05)); + + @if $ratio > 5 { + $found-decent-color: true; + } @else { + $on-scheme-color: darken($on-scheme-color, 5%); + $fg-lum: fn.bulmaColorLuminance($on-scheme-color); + } + } + } + + $on-scheme-lightness: lightness($on-scheme-color); + @include register-var($name, $on-scheme-lightness, "", "-on-scheme-l"); + $on-scheme-l: getVar($name, "", "-on-scheme-l"); + @include register-var( + "#{$name}-on-scheme", + buildHslaString($name, $on-scheme-l) + ); +} + +@mixin v1-generate-on-scheme-colors($name, $base, $scheme-main) { + // Accessibility Contrast System + $scheme-main-brightness: fn.bulmaColorBrightness($scheme-main); + $on-scheme-color: $base; + + @if ($scheme-main-brightness == "bright") { + @while (fn.bulmaEnoughContrast($on-scheme-color, #fff) == false) { + // We're on a light background, so we'll darken the test color step by step. + $on-scheme-color: darken($on-scheme-color, 5%); + } + } @else { + @while (fn.bulmaEnoughContrast($on-scheme-color, #000) == false) { + // We're on a dark background, so we'll lighten the test color step by step. + $on-scheme-color: lighten($on-scheme-color, 5%); + } + } + + $on-scheme-lightness: lightness($on-scheme-color); + @include register-var($name, $on-scheme-lightness, "", "-on-scheme-l"); +} + +@mixin register-base-color($name, $base) { + $hsla: buildHslaString($name, getVar($name, "", "-l")); + @include register-var($name, $hsla); + @include register-var($name, $hsla, "", "-base"); // Just for reference + @include register-rgb($name, $base); + @include register-hsl($name, $base); +} + +@mixin generate-basic-palette($name, $base, $invert: null) { + @include register-base-color($name, $base); + + @if $invert { + @include register-var($name, lightness($invert), "", "-invert-l"); + @include register-var("#{$name}-invert", $invert); + } +} + +@mixin generate-color-palette( + $name, + $base, + $scheme-main-l: 100%, + $invert: null, + $light: null, + $dark: null +) { + $h: round(hue($base)); // Hue + $s: round(saturation($base)); // Saturation + $l: round(lightness($base)); // Lightness + $base-lum: fn.bulmaColorLuminance($base); + $l-base: round($l % 10); // Get lightness second digit: 53% -> 3% + $l-0: 0%; // 5% or less + $l-5: 5%; // More than 5% + $a: 1; // Alpha + $base-digits: "00"; + + // Calculate digits like "40" for the scheme-main + $scheme-l-0: 0%; + $scheme-l-base: round($scheme-main-l % 10); + $closest-5: math.round(math.div($scheme-main-l, 5)) * 5; + $pct-to-int: math.div($closest-5, 100%) * 100; + $scheme-main-digits: #{$pct-to-int}; + + // === STEP 1 === + // Register the base colors + @include register-base-color($name, $base); + + // === STEP 2 === + // Generating 20 shades of the color + + // 00: 0%, 1%, 2% + // 05: 3%, 4%, 5%, 6%, 7% + // 10: 8%, 9% + + @if ($l-base < 3%) { + $l-0: $l-base; + $l-5: $l-base + 5%; + } @else if ($l-base < 8%) { + // $l-0: math.max($l-base - 5%, 0%); + $l-0: $l-base - 5%; + $l-5: $l-base; + } @else { + // $l-0: math.max($l-base - 10%, 0%); + $l-0: $l-base - 10%; + $l-5: $l-base - 5%; + } + + $shades: (); + + @for $i from 0 through 9 { + // if $l-base = 3%, then we get 3%, 13%, 23%, 33% etc. + $color-l-0: math.max($l-0 + $i * 10, 0%); + + // if $l-base = 3%, then we get 8%, 18%, 28%, 38% etc. + $color-l-5: $l-5 + $i * 10; + + $shades: map.set($shades, "#{$i}0", $color-l-0); + $shades: map.set($shades, "#{$i}5", $color-l-5); + + @include register-var($name, $color-l-0, "", "-#{$i}0-l"); + @include register-var($name, $color-l-5, "", "-#{$i}5-l"); + + @if $color-l-0 == $l { + $base-digits: "#{$i}0"; + } @else if $color-l-5 == $l { + $base-digits: "#{$i}5"; + } + } + + $shades: map.set($shades, "100", 100%); + @include register-var($name, 100%, "", "-100-l"); + + // === STEP 3 === + // Find accessible color combinations + + $combos: (); + + @each $digits-bg, $bg-l in $shades { + $background: hsl($h, $s, $bg-l); + $bg-lum: fn.bulmaColorLuminance($background); + $bg-is-light: $bg-lum > 0.55; + $candidates: (); + $found: false; + + // If the background color is the base color + @if $bg-l == $l { + $base-digits: $digits-bg; + + // Even if the base color as a background + // doesn't have an appropriate foreground, + // we still add to the list of "valid" contrast combos for now. + @if $bg-is-light { + $combos: map.set($combos, $base-digits, "10"); + } @else { + $combos: map.set($combos, $base-digits, "100"); + } + } + + // We capture all contrast ratios for any given background + // using all foreground options + $current-best-digits: "00"; + $current-best-ratio: 0; + + @each $digits-fg, $fg-l in $shades { + $foreground: hsl($h, $s, $fg-l); + $ratio: 0; + $is-light-fg: false; + + // Source: https://www.w3.org/TR/WCAG20-TECHS/G17.html + $fg-lum: fn.bulmaColorLuminance($foreground); + + @if (lightness($foreground) > lightness($background)) { + $is-light-fg: true; + $ratio: math.div(($fg-lum + 0.05), ($bg-lum + 0.05)); + } @else { + $ratio: math.div(($bg-lum + 0.05), ($fg-lum + 0.05)); + } + + @if $ratio > 7 { + $candidates: list.append( + $candidates, + fn.bulmaStringToNumber($digits-fg) + ); + + @if ($is-light-fg) { + @if (not $found) { + // Store the background/foreground combination + $combos: map.set($combos, $digits-bg, $digits-fg); + $current-best-digits: $digits-fg; + $current-best-ratio: $ratio; + $found: true; + } + } @else { + $combos: map.set($combos, $digits-bg, $digits-fg); + $current-best-digits: $digits-fg; + $current-best-ratio: $ratio; + } + } + } + + // We haven't found a decent ratio + @each $digits-fg, $fg-l in $shades { + @if (map.has-key($combos, $digits-bg) == false) { + @if ($bg-is-light) { + // Light background so we set a dark foreground + $combos: map.set($combos, $digits-bg, "00"); + } @else { + // Dark background so we set a light foreground + $combos: map.set($combos, $digits-bg, "100"); + } + } + } + } + + // The output needs to be: + // --bulma-primary-invert-l: var(--bulma-primary-100-l); + + @each $bg, $fg in $combos { + // Just using this loop to register all 20 digits + $bg-l: getVar($name, "", "-#{$bg}-l"); + @include register-var("#{$name}-#{$bg}", buildHslaString($name, $bg-l)); + + // Register the lightness + @include register-var( + $name, + getVar($name, "", "-#{$fg}-l"), + "", + "-#{$bg}-invert-l" + ); + + // Resiter the color using that lightness + $bg-invert-l: getVar($name, "", "-#{$bg}-invert-l"); + @include register-var( + "#{$name}-#{$bg}-invert", + buildHslaString($name, $bg-invert-l) + ); + } + + // If an invert color is provided by the user + @if $invert { + @include register-var($name, lightness($invert), "", "-invert-l"); + @include register-var("#{$name}-invert", $invert); + } @else { + $base-invert-l-digits: map.get($combos, $base-digits); + @include register-var( + $name, + getVar($name, "", "-#{$base-invert-l-digits}-l"), + "", + "-invert-l" + ); + + $base-invert-l: getVar($name, "", "-invert-l"); + @include register-var( + "#{$name}-invert", + buildHslaString($name, $base-invert-l) + ); + } + + // Good color on light background (90% lightness) + @if $light and $dark { + @include register-var($name, lightness($light), "", "-light-l"); + @include register-var($name, lightness($light), "", "-dark-invert-l"); + @include register-var("#{$name}-light", $light); + @include register-var("#{$name}-dark-invert", $light); + + @include register-var($name, lightness($dark), "", "-dark-l"); + @include register-var($name, lightness($dark), "", "-light-invert-l"); + @include register-var("#{$name}-dark", $dark); + @include register-var("#{$name}-light-invert", $dark); + } @else { + @include register-var($name, getVar($name, "", "-90-l"), "", "-light-l"); + + $light-l: getVar($name, "", "-light-l"); + @include register-var("#{$name}-light", buildHslaString($name, $light-l)); + + $light-invert-l-digits: map.get($combos, "90"); + @include register-var( + $name, + getVar($name, "", "-#{$light-invert-l-digits}-l"), + "", + "-light-invert-l" + ); + + $light-invert-l: getVar($name, "", "-light-invert-l"); + @include register-var( + "#{$name}-light-invert", + buildHslaString($name, $light-invert-l) + ); + + // Good color on dark background (10% lightness) + @include register-var($name, getVar($name, "", "-10-l"), "", "-dark-l"); + + $dark-l: getVar($name, "", "-dark-l"); + @include register-var("#{$name}-dark", buildHslaString($name, $dark-l)); + + $dark-invert-l-digits: map.get($combos, "10"); + @include register-var( + $name, + getVar($name, "", "-#{$dark-invert-l-digits}-l"), + "", + "-dark-invert-l" + ); + + $dark-invert-l: getVar($name, "", "-dark-invert-l"); + @include register-var( + "#{$name}-dark-invert", + buildHslaString($name, $dark-invert-l) + ); + + // Soft and Bold colors + $soft-l: getVar("soft-l"); + $soft-invert-l: getVar("soft-invert-l"); + $bold-l: getVar("bold-l"); + $bold-invert-l: getVar("bold-invert-l"); + @include register-var("#{$name}-soft", buildHslaString($name, $soft-l)); + @include register-var("#{$name}-bold", buildHslaString($name, $bold-l)); + @include register-var( + "#{$name}-soft-invert", + buildHslaString($name, $soft-invert-l) + ); + @include register-var( + "#{$name}-bold-invert", + buildHslaString($name, $bold-invert-l) + ); + } +} + +@mixin bulma-theme($name) { + [data-#{iv.$class-prefix}theme="#{$name}"], + .#{iv.$class-prefix}theme-#{$name} { + @content; + } +} + +@mixin system-theme($name) { + @media (prefers-color-scheme: #{$name}) { + :root { + @content; + } + } +} diff --git a/web/assets/css/sass/utilities/derived-variables.scss b/web/assets/css/sass/utilities/derived-variables.scss new file mode 100644 index 0000000..6f1440d --- /dev/null +++ b/web/assets/css/sass/utilities/derived-variables.scss @@ -0,0 +1,112 @@ +@use "initial-variables" as iv; +@use "functions" as fn; + +// Scheme colors + +$scheme-main: iv.$white !default; +$scheme-main-bis: iv.$white-bis !default; +$scheme-main-ter: iv.$white-ter !default; +$scheme-invert: iv.$black !default; +$scheme-invert-bis: iv.$black-bis !default; +$scheme-invert-ter: iv.$black-ter !default; + +// Text colors + +$text: iv.$grey-dark !default; +$text-invert: fn.bulmaFindColorInvert($text) !default; +$text-weak: iv.$grey !default; +$text-strong: iv.$grey-darker !default; + +// Status colors + +$primary: iv.$turquoise !default; +$info: iv.$cyan !default; +$success: iv.$green !default; +$warning: iv.$yellow !default; +$danger: iv.$red !default; +$light: iv.$white-ter !default; +$dark: iv.$grey-darker !default; + +// Link colors + +$link: iv.$blue !default; + +// Decorative colors + +$background: iv.$white-ter !default; +$border: iv.$grey-lighter !default; +$border-weak: iv.$grey-lightest !default; + +// Code colors + +$code: iv.$red !default; +$code-background: $background !default; + +$pre: $text !default; +$pre-background: $background !default; + +// Typography + +$family-primary: iv.$family-sans-serif !default; +$family-secondary: iv.$family-sans-serif !default; +$family-code: iv.$family-monospace !default; + +$size-small: iv.$size-7 !default; +$size-normal: iv.$size-6 !default; +$size-medium: iv.$size-5 !default; +$size-large: iv.$size-4 !default; + +// Effects + +$shadow-color: iv.$black !default; + +// Lists and maps +$custom-colors: null !default; +$custom-shades: null !default; + +$colors: fn.mergeColorMaps( + ( + "white": ( + iv.$white, + iv.$black, + ), + "black": ( + iv.$black, + iv.$white, + ), + "light": ( + $light, + $dark, + ), + "dark": ( + $dark, + $light, + ), + "text": $text, + "primary": $primary, + "link": $link, + "info": $info, + "success": $success, + "warning": $warning, + "danger": $danger, + ), + $custom-colors +) !default; + +$shades: fn.mergeColorMaps( + ( + "black-bis": iv.$black-bis, + "black-ter": iv.$black-ter, + "grey-darker": iv.$grey-darker, + "grey-dark": iv.$grey-dark, + "grey": iv.$grey, + "grey-light": iv.$grey-light, + "grey-lighter": iv.$grey-lighter, + "white-ter": iv.$white-ter, + "white-bis": iv.$white-bis, + ), + $custom-shades +) !default; + +$sizes: iv.$size-1 iv.$size-2 iv.$size-3 iv.$size-4 iv.$size-5 iv.$size-6 + iv.$size-7 !default; diff --git a/web/assets/css/sass/utilities/extends.scss b/web/assets/css/sass/utilities/extends.scss new file mode 100644 index 0000000..42d05fe --- /dev/null +++ b/web/assets/css/sass/utilities/extends.scss @@ -0,0 +1,34 @@ +@use "controls"; +@use "mixins"; + +%arrow { + @include mixins.arrow; +} + +%block { + @include mixins.block; +} + +%control { + @include controls.control; +} + +%delete { + @include mixins.delete; +} + +%loader { + @include mixins.loader; +} + +%overlay { + @include mixins.overlay; +} + +%reset { + @include mixins.reset; +} + +%unselectable { + @include mixins.unselectable; +} diff --git a/web/assets/css/sass/utilities/functions.scss b/web/assets/css/sass/utilities/functions.scss new file mode 100644 index 0000000..f19dae0 --- /dev/null +++ b/web/assets/css/sass/utilities/functions.scss @@ -0,0 +1,258 @@ +@use "sass:list"; +@use "sass:math"; + +@function mergeColorMaps($bulma-colors, $custom-colors) { + // We return at least Bulma's hard-coded colors + $merged-colors: $bulma-colors; + + // We want a map as input + @if type-of($custom-colors) == "map" { + @each $name, $components in $custom-colors { + // The color name should be a string + // and the components either a single color + // or a colors list with at least one element + @if type-of($name) == + "string" and + (type-of($components) == "list" or type-of($components) == "color") and + length($components) >= + 1 + { + $color-base: null; + $color-invert: null; + $color-light: null; + $color-dark: null; + $value: null; + + // The param can either be a single color + // or a list of 2 colors + @if type-of($components) == "color" { + $color-base: $components; + $color-invert: bulmaFindColorInvert($color-base); + $color-light: bulmaFindLightColor($color-base); + $color-dark: bulmaFindDarkColor($color-base); + } @else if type-of($components) == "list" { + $color-base: list.nth($components, 1); + + // If Invert, Light and Dark are provided + @if length($components) > 3 { + $color-invert: list.nth($components, 2); + $color-light: list.nth($components, 3); + $color-dark: list.nth($components, 4); + + // If only Invert and Light are provided + } @else if length($components) > 2 { + $color-invert: list.nth($components, 2); + $color-light: list.nth($components, 3); + $color-dark: bulmaFindDarkColor($color-base); + + // If only Invert is provided + } @else { + $color-invert: list.nth($components, 2); + $color-light: bulmaFindLightColor($color-base); + $color-dark: bulmaFindDarkColor($color-base); + } + } + + $value: $color-base, $color-invert, $color-light, $color-dark; + + // We only want to merge the map if the color base is an actual color + @if type-of($color-base) == "color" { + // We merge this colors elements as map with Bulma's colors map + // (we can override them this way, no multiple definition for the same name) + // $merged-colors: map_merge($merged-colors, ($name: ($color-base, $color-invert, $color-light, $color-dark))) + $merged-colors: map_merge( + $merged-colors, + ( + $name: $value, + ) + ); + } + } + } + } + + @return $merged-colors; +} + +@function powerNumber($number, $exp) { + $value: 1; + + @if $exp > 0 { + @for $i from 1 through $exp { + $value: $value * $number; + } + } @else if $exp < 0 { + @for $i from 1 through -$exp { + $value: math.div($value, $number); + } + } + + @return $value; +} + +@function bulmaColorLuminance($color) { + @if type-of($color) != "color" { + @return 0.55; + } + + $color-rgb: ( + "red": red($color), + "green": green($color), + "blue": blue($color), + ); + + @each $name, $value in $color-rgb { + $adjusted: 0; + $value: math.div($value, 255); + + @if $value < 0.03928 { + $value: math.div($value, 12.92); + } @else { + $value: math.div($value + 0.055, 1.055); + $value: powerNumber($value, 2); + } + + $color-rgb: map-merge( + $color-rgb, + ( + $name: $value, + ) + ); + } + + @return map-get($color-rgb, "red") * 0.2126 + map-get($color-rgb, "green") * + 0.7152 + map-get($color-rgb, "blue") * 0.0722; +} + +@function bulmaFindColorInvert($color) { + @if bulmaColorLuminance($color) > 0.55 { + @return rgba(#000, 0.7); + } @else { + @return #fff; + } +} + +@function bulmaFindLightColor($color, $l: 96%) { + @if type-of($color) == "color" { + $l: 96%; + + @if lightness($color) > 96% { + $l: lightness($color); + } + + @return change-color($color, $lightness: $l); + } + + @return $background; +} + +@function bulmaFindDarkColor($color, $base-l: 29%) { + @if type-of($color) == "color" { + $luminance: bulmaColorLuminance($color); + $luminance-delta: 0.53 - $luminance; + $target-l: round($base-l + $luminance-delta * 53); + + @return change-color($color, $lightness: max($base-l, $target-l)); + } + + @return $text-strong; +} + +@function bulmaRgba($color, $alpha) { + @if type-of($color) != "color" { + @return $color; + } + + @return rgba($color, $alpha); +} + +@function bulmaDarken($color, $amount) { + @if type-of($color) != "color" { + @return $color; + } + + @return darken($color, $amount); +} + +@function bulmaLighten($color, $amount) { + @if type-of($color) != "color" { + @return $color; + } + + @return lighten($color, $amount); +} + +@function bulmaColorBrightness($n) { + $color-brightness: round( + (red($n) * 299) + (green($n) * 587) + (blue($n) * 114) / 1000 + ); + $light-color: round( + (red(#ffffff) * 299) + (green(#ffffff) * 587) + (blue(#ffffff) * 114) / 1000 + ); + + @if abs($color-brightness) < math.div($light-color, 2) { + @return "dark"; + } + + @return "bright"; +} + +@function bulmaEnoughContrast($foreground, $background) { + $r: (max(red($foreground), red($background))) - + (min(red($foreground), red($background))); + $g: (max(green($foreground), green($background))) - + (min(green($foreground), green($background))); + $b: (max(blue($foreground), blue($background))) - + (min(blue($foreground), blue($background))); + $sum-rgb: $r + $g + $b; + + @if $sum-rgb < 500 { + @return false; + } + + @return true; +} + +// By Cory Simmons https://corysimmons.com/ +@function bulmaStringToNumber($value) { + @if type-of($value) == "number" { + @return $value; + } @else if type-of($value) != "string" { + $_: log("Value for `to-number` should be a number or a string."); + } + + $result: 0; + $digits: 0; + $minus: str-slice($value, 1, 1) == "-"; + $numbers: ( + "0": 0, + "1": 1, + "2": 2, + "3": 3, + "4": 4, + "5": 5, + "6": 6, + "7": 7, + "8": 8, + "9": 9, + ); + + @for $i from if($minus, 2, 1) through str-length($value) { + $character: str-slice($value, $i, $i); + + @if not(index(map-keys($numbers), $character) or $character == ".") { + @return to-length(if($minus, -$result, $result), str-slice($value, $i)); + } + + @if $character == "." { + $digits: 1; + } @else if $digits == 0 { + $result: $result * 10 + map-get($numbers, $character); + } @else { + $digits: $digits * 10; + $result: $result + map-get($numbers, $character) / $digits; + } + } + + @return if($minus, -$result, $result); +} diff --git a/web/assets/css/sass/utilities/initial-variables.scss b/web/assets/css/sass/utilities/initial-variables.scss new file mode 100644 index 0000000..7bd4b53 --- /dev/null +++ b/web/assets/css/sass/utilities/initial-variables.scss @@ -0,0 +1,155 @@ +// Scheme Hue and Saturation + +$scheme-h: 221; +$scheme-s: 14%; +$dark-l: 20%; +$light-l: 90%; + +// Colors + +$black: hsl(221, 14%, 4%) !default; +$black-bis: hsl(221, 14%, 9%) !default; +$black-ter: hsl(221, 14%, 14%) !default; + +$grey-darker: hsl(221, 14%, 21%) !default; +$grey-dark: hsl(221, 14%, 29%) !default; +$grey: hsl(221, 14%, 48%) !default; +$grey-light: hsl(221, 14%, 71%) !default; +$grey-lighter: hsl(221, 14%, 86%) !default; +$grey-lightest: hsl(221, 14%, 93%) !default; + +$white-ter: hsl(221, 14%, 96%) !default; +$white-bis: hsl(221, 14%, 98%) !default; +$white: hsl(221, 14%, 100%) !default; + +$orange: hsl(14, 100%, 53%) !default; +$yellow: hsl(42, 100%, 53%) !default; +$green: hsl(153, 53%, 53%) !default; +$turquoise: hsl(171, 100%, 41%) !default; +$cyan: hsl(198, 100%, 70%) !default; +$blue: hsl(233, 100%, 63%) !default; +$purple: hsl(271, 100%, 71%) !default; +$red: hsl(348, 100%, 70%) !default; + +// Typography + +$family-sans-serif: "Inter", "SF Pro", "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Helvetica Neue", "Helvetica", "Arial", sans-serif !default; +$family-monospace: "Inconsolata", "Hack", "SF Mono", "Roboto Mono", + "Source Code Pro", "Ubuntu Mono", monospace !default; +$render-mode: optimizeLegibility !default; + +$size-1: 3rem !default; +$size-2: 2.5rem !default; +$size-3: 2rem !default; +$size-4: 1.5rem !default; +$size-5: 1.25rem !default; +$size-6: 1rem !default; +$size-7: 0.75rem !default; + +$weight-light: 300 !default; +$weight-normal: 400 !default; +$weight-medium: 500 !default; +$weight-semibold: 600 !default; +$weight-bold: 700 !default; +$weight-extrabold: 800 !default; + +// Spacing + +$block-spacing: 1.5rem !default; +$aspect-ratios: ( + (1, 1), + (5, 4), + (4, 3), + (3, 2), + (5, 3), + (16, 9), + (2, 1), + (3, 1), + (4, 5), + (3, 4), + (2, 3), + (3, 5), + (9, 16), + (1, 2), + (1, 3) +) !default; + +// Responsiveness + +// The container horizontal gap, which acts as the offset for breakpoints +$gap: 32px !default; + +// 960, 1152, and 1344 have been chosen because they are divisible by both 12 and 16 +$tablet: 769px !default; + +// 960px container + 4rem +$desktop: 960px + 2 * $gap !default; + +// 1152px container + 4rem +$widescreen: 1152px + 2 * $gap !default; +$widescreen-enabled: true !default; + +// 1344px container + 4rem +$fullhd: 1344px + 2 * $gap !default; +$fullhd-enabled: true !default; +$breakpoints: ( + "mobile": ( + "until": $tablet, + ), + "tablet": ( + "from": $tablet, + ), + "tablet-only": ( + "from": $tablet, + "until": $desktop, + ), + "touch": ( + "from": $desktop, + ), + "desktop": ( + "from": $desktop, + ), + "desktop-only": ( + "from": $desktop, + "until": $widescreen, + ), + "until-widescreen": ( + "until": $widescreen, + ), + "widescreen": ( + "from": $widescreen, + ), + "widescreen-only": ( + "from": $widescreen, + "until": $fullhd, + ), + "until-fullhd": ( + "until": $fullhd, + ), + "fullhd": ( + "from": $fullhd, + ), +) !default; + +// Miscellaneous + +$easing: ease-out !default; +$radius-small: 0.25rem !default; +$radius: 0.375rem !default; +$radius-medium: 0.5em !default; +$radius-large: 0.75rem !default; +$radius-rounded: 9999px !default; +$speed: 86ms !default; + +// Flags + +$variable-columns: true !default; +$rtl: false !default; + +// Prefixes + +$class-prefix: "" !default; +$cssvars-prefix: "bulma-" !default; +$helpers-prefix: "is-" !default; +$helpers-has-prefix: "has-" !default; diff --git a/web/assets/css/sass/utilities/mixins.scss b/web/assets/css/sass/utilities/mixins.scss new file mode 100644 index 0000000..20d87b6 --- /dev/null +++ b/web/assets/css/sass/utilities/mixins.scss @@ -0,0 +1,460 @@ +@use "initial-variables" as iv; +@use "css-variables" as cv; + +@mixin arrow($color: #{cv.getVar("link")}) { + border: 0.125em solid $color; + border-right: 0; + border-top: 0; + content: " "; + display: block; + height: 0.625em; + margin-top: -0.4375em; + pointer-events: none; + position: absolute; + top: 50%; + transform: rotate(-45deg); + transform-origin: center; + transition-duration: cv.getVar("duration"); + transition-property: border-color; + width: 0.625em; +} + +@mixin block($spacing: cv.getVar("block-spacing")) { + &:not(:last-child) { + margin-bottom: $spacing; + } +} + +@mixin center($width, $height: 0) { + position: absolute; + @if $height != 0 { + left: calc(50% - (#{$width} * 0.5)); + top: calc(50% - (#{$height} * 0.5)); + } @else { + left: calc(50% - (#{$width} * 0.5)); + top: calc(50% - (#{$width} * 0.5)); + } +} + +@mixin clearfix { + &::after { + clear: both; + content: " "; + display: table; + } +} + +@mixin delete { + @include cv.register-vars( + ( + "delete-dimensions": 1.25rem, + "delete-background-l": 0%, + "delete-background-alpha": 0.5, + "delete-color": #{cv.getVar("white")}, + ) + ); + + appearance: none; + background-color: hsla( + #{cv.getVar("scheme-h")}, + #{cv.getVar("scheme-s")}, + #{cv.getVar("delete-background-l")}, + #{cv.getVar("delete-background-alpha")} + ); + border: none; + border-radius: cv.getVar("radius-rounded"); + cursor: pointer; + pointer-events: auto; + display: inline-flex; + flex-grow: 0; + flex-shrink: 0; + font-size: 1em; + height: cv.getVar("delete-dimensions"); + max-height: cv.getVar("delete-dimensions"); + max-width: cv.getVar("delete-dimensions"); + min-height: cv.getVar("delete-dimensions"); + min-width: cv.getVar("delete-dimensions"); + outline: none; + position: relative; + vertical-align: top; + width: cv.getVar("delete-dimensions"); + + &::before, + &::after { + background-color: cv.getVar("delete-color"); + content: ""; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%) rotate(45deg); + transform-origin: center center; + } + + &::before { + height: 2px; + width: 50%; + } + + &::after { + height: 50%; + width: 2px; + } + + &:hover, + &:focus { + @include cv.register-var("delete-background-alpha", 0.4); + } + + &:active { + @include cv.register-var("delete-background-alpha", 0.5); + } + + // Sizes + &.#{iv.$class-prefix}is-small { + @include cv.register-var("delete-dimensions", 1rem); + } + + &.#{iv.$class-prefix}is-medium { + @include cv.register-var("delete-dimensions", 1.5rem); + } + + &.#{iv.$class-prefix}is-large { + @include cv.register-var("delete-dimensions", 2rem); + } +} + +@mixin fa($size, $dimensions) { + display: inline-block; + font-size: $size; + height: $dimensions; + line-height: $dimensions; + text-align: center; + vertical-align: top; + width: $dimensions; +} + +@mixin burger($dimensions) { + align-items: center; + appearance: none; + background: none; + border: none; + border-radius: cv.getVar("burger-border-radius"); + color: hsl( + cv.getVar("burger-h"), + cv.getVar("burger-s"), + cv.getVar("burger-l") + ); + cursor: pointer; + display: inline-flex; + flex-direction: column; + flex-shrink: 0; + height: $dimensions; + justify-content: center; + position: relative; + vertical-align: top; + width: $dimensions; + + span { + background-color: currentColor; + display: block; + height: cv.getVar("burger-item-height"); + left: calc(50% - calc(#{cv.getVar("burger-item-width")}) / 2); + position: absolute; + transform-origin: center; + transition-duration: cv.getVar("duration"); + transition-property: background-color, color, opacity, transform; + transition-timing-function: cv.getVar("easing"); + width: cv.getVar("burger-item-width"); + + &:nth-child(1), + &:nth-child(2) { + top: calc(50% - calc(#{cv.getVar("burger-item-height")}) / 2); + } + + &:nth-child(3) { + bottom: calc(50% + #{cv.getVar("burger-gap")}); + } + + &:nth-child(4) { + top: calc(50% + #{cv.getVar("burger-gap")}); + } + } + + &:hover { + background-color: hsla( + cv.getVar("burger-h"), + cv.getVar("burger-s"), + cv.getVar("burger-l"), + 0.1 + ); + } + + &:active { + background-color: hsla( + cv.getVar("burger-h"), + cv.getVar("burger-s"), + cv.getVar("burger-l"), + 0.2 + ); + } + + // Modifers + &.#{iv.$class-prefix}is-active { + span { + &:nth-child(1) { + transform: rotate(-45deg); + } + + &:nth-child(2) { + transform: rotate(45deg); + } + + &:nth-child(3), + &:nth-child(4) { + opacity: 0; + } + } + } +} + +@mixin overflow-touch { + -webkit-overflow-scrolling: touch; +} + +@mixin placeholder { + $placeholders: ":-moz" ":-webkit-input" "-moz" "-ms-input"; + + @each $placeholder in $placeholders { + &:#{$placeholder}-placeholder { + @content; + } + } +} + +@mixin reset { + appearance: none; + background: none; + border: none; + color: inherit; + font-family: inherit; + font-size: 1em; + margin: 0; + padding: 0; +} + +@mixin selection($current-selector: false) { + @if $current-selector { + &::-moz-selection { + @content; + } + &::selection { + @content; + } + } @else { + ::-moz-selection { + @content; + } + ::selection { + @content; + } + } +} + +// Responsiveness + +@mixin from($device) { + @media screen and (min-width: $device) { + @content; + } +} + +@mixin until($device) { + @media screen and (max-width: ($device - 1px)) { + @content; + } +} + +@mixin between($from, $until) { + @media screen and (min-width: $from) and (max-width: ($until - 1px)) { + @content; + } +} + +@mixin mobile { + @media screen and (max-width: (iv.$tablet - 1px)) { + @content; + } +} + +@mixin tablet { + @media screen and (min-width: iv.$tablet), print { + @content; + } +} + +@mixin tablet-only { + @media screen and (min-width: iv.$tablet) and (max-width: (iv.$desktop - 1px)) { + @content; + } +} + +@mixin touch { + @media screen and (max-width: (iv.$desktop - 1px)) { + @content; + } +} + +@mixin desktop { + @media screen and (min-width: iv.$desktop) { + @content; + } +} + +@mixin desktop-only { + @if iv.$widescreen-enabled { + @media screen and (min-width: iv.$desktop) and (max-width: (iv.$widescreen - 1px)) { + @content; + } + } +} + +@mixin until-widescreen { + @if iv.$widescreen-enabled { + @media screen and (max-width: (iv.$widescreen - 1px)) { + @content; + } + } +} + +@mixin widescreen { + @if iv.$widescreen-enabled { + @media screen and (min-width: iv.$widescreen) { + @content; + } + } +} + +@mixin widescreen-only { + @if iv.$widescreen-enabled and iv.$fullhd-enabled { + @media screen and (min-width: iv.$widescreen) and (max-width: (iv.$fullhd - 1px)) { + @content; + } + } +} + +@mixin until-fullhd { + @if iv.$fullhd-enabled { + @media screen and (max-width: (iv.$fullhd - 1px)) { + @content; + } + } +} + +@mixin fullhd { + @if iv.$fullhd-enabled { + @media screen and (min-width: iv.$fullhd) { + @content; + } + } +} + +@mixin breakpoint($name) { + $breakpoint: map-get(iv.$breakpoints, $name); + + @if $breakpoint { + $from: map-get($breakpoint, "from"); + $until: map-get($breakpoint, "until"); + + @if $from and $until { + @include between($from, $until) { + @content; + } + } @else if $from { + @include from($from) { + @content; + } + } @else if $until { + @include until($until) { + @content; + } + } + } +} + +@mixin container-from($name, $width) { + @container #{$name} (min-width: #{$width}) { + @content; + } +} + +@mixin container-until($name, $width) { + @container #{$name} (max-width: #{$width - 1px}) { + @content; + } +} + +@mixin ltr { + @if not iv.$rtl { + @content; + } +} + +@mixin rtl { + @if iv.$rtl { + @content; + } +} + +@mixin ltr-property($property, $spacing, $right: true) { + $normal: if($right, "right", "left"); + $opposite: if($right, "left", "right"); + + @if iv.$rtl { + #{$property}-#{$opposite}: $spacing; + } @else { + #{$property}-#{$normal}: $spacing; + } +} + +@mixin ltr-position($spacing, $right: true) { + $normal: if($right, "right", "left"); + $opposite: if($right, "left", "right"); + + @if iv.$rtl { + #{$opposite}: $spacing; + } @else { + #{$normal}: $spacing; + } +} + +// Placeholders + +@mixin unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +@mixin loader { + animation: spinAround 500ms infinite linear; + border: 2px solid cv.getVar("loading-color"); + border-radius: cv.getVar("radius-rounded"); + border-right-color: transparent; + border-top-color: transparent; + content: ""; + display: block; + height: 1em; + position: relative; + width: 1em; +} + +@mixin overlay($offset: 0) { + bottom: $offset; + left: $offset; + position: absolute; + right: $offset; + top: $offset; +}