diff --git a/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss b/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss index 2ec7772b194..9f73810c4e4 100644 --- a/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss +++ b/addons/web/static/src/legacy/scss/bootstrap_overridden_frontend.scss @@ -5,11 +5,23 @@ // customization (eg. form-range) // gray-color-variables +$white: #fff !default; $gray-400: #ced4da !default; + +// color-variables +$blue: #0d6efd !default; + +// theme-color-variables +$primary: $blue !default; + // The contrast ratio to reach against white, to determine if color changes from "light" to "dark". Acceptable values for WCAG 2.0 are 3, 4.5 and 7. // See https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast $min-contrast-ratio: 3 !default; +// Body + +$body-bg: $white !default; // BS Default + // Components // // Define common padding and border radius sizes and more. @@ -37,6 +49,11 @@ $input-transition: background-color .05s ease-in-out, border-color .05s ease-in- $form-check-input-border: $border-width solid $gray-400 !default; $form-check-input-border-radius: 0 !default; +$form-range-track-height: .1rem !default; +$form-range-thumb-border: $border-width solid $primary !default; +$form-range-thumb-bg: $body-bg !default; +$form-range-thumb-active-bg: $primary !default; + // Figures // Inherit color for figure-caption, use text-muted on top of it if you want diff --git a/addons/website/static/lib/multirange/multirange_custom.js b/addons/website/static/lib/multirange/multirange_custom.js index 55b2f791c42..3e65be64315 100644 --- a/addons/website/static/lib/multirange/multirange_custom.js +++ b/addons/website/static/lib/multirange/multirange_custom.js @@ -76,62 +76,43 @@ class Multirange { this.input.step = this.step = options.step || this.input.step || 1; this.currency = options.currency || this.input.dataset.currency || ''; this.currencyPosition = options.currencyPosition || this.input.dataset.currencyPosition || 'after'; + const inputClasses = ["multirange", "d-inline-block", "p-0", "align-top"]; /* Wrap the input and add its ghost */ this.rangeDiv = document.createElement("div"); - this.rangeDiv.classList.add("multirange-wrapper"); + this.rangeDiv.classList.add("multirange-wrapper", "position-relative", "mb-5"); + this.countersWrapper = document.createElement("small"); + this.countersWrapper.classList.add("d-flex", "justify-content-between", "mt-2"); + this.rangeDiv.appendChild(this.countersWrapper); this.input.parentNode.insertBefore(this.rangeDiv, this.input.nextSibling); this.rangeDiv.appendChild(this.input); this.ghost = this.input.cloneNode(); this.rangeDiv.appendChild(this.ghost); - this.input.classList.add("multirange", "original"); - this.ghost.classList.add("multirange", "ghost"); + this.input.classList.add("original", "position-absolute", "w-100", "m-0", ...inputClasses); + this.ghost.classList.add("ghost", "position-relative", ...inputClasses); this.input.value = values[0] || this.min; this.ghost.value = values[1] || this.max; - this.inputTipLocator = document.createElement("div"); - this.inputTipLocator.classList.add("tip-locator"); - this.ghostTipLocator = document.createElement("div"); - this.ghostTipLocator.classList.add("tip-locator"); - this.rangeDiv.insertBefore(this.ghostTipLocator, this.input.nextSibling); - this.rangeDiv.insertBefore(this.inputTipLocator, this.ghost.nextSibling); this.leftCounter = document.createElement("span"); - this.leftCounter.classList.add("multirange-min"); + this.leftCounter.classList.add("multirange-min", "position-absolute", "opacity-75", "opacity-100-hover", "mt-1"); this.rightCounter = document.createElement("span"); - this.rightCounter.classList.add("multirange-max"); - this.tipLocatorOptions = { - container: this.rangeDiv, - html: true, - }; - $(this.inputTipLocator).popover(Object.assign( - this.tipLocatorOptions, - { - placement: 'top', - content: this.leftCounter - }) - ); - $(this.ghostTipLocator).popover(Object.assign( - this.tipLocatorOptions, - { - placement: 'bottom', - content: this.rightCounter - }) - ); + this.rightCounter.classList.add("multirange-max", "position-absolute", "opacity-75", "opacity-100-hover", "mt-1"); + this.rightCounter.style.right = 0; + this.countersWrapper.append(this.leftCounter, this.rightCounter); - $(this.inputTipLocator).add($(this.ghostTipLocator)).popover('show'); /* Add the counterInput */ if (this.rangeWithInput) { this.leftInput = document.createElement("input"); this.leftInput.type = "number"; - this.leftInput.style.display = "none"; + this.leftInput.classList.add("invisible", "form-control", "form-control-sm", "w-auto", "mb-2", "mb-lg-1"); this.leftInput.min = this.min; this.leftInput.max = this.max; this.leftInput.step = this.step; this.rightInput = this.leftInput.cloneNode(); - this.leftInput.classList.add("multirange-min"); - this.rightInput.classList.add("multirange-max"); + this.leftInput.classList.add("multirange-min", "invisible"); + this.rightInput.classList.add("multirange-max", "invisible"); this.leftCounter.parentNode.appendChild(this.leftInput); this.rightCounter.parentNode.appendChild(this.rightInput); @@ -221,19 +202,9 @@ class Multirange { update() { const low = 100 * (this.input.valueLow - this.min) / (this.max - this.min); const high = 100 * (this.input.valueHigh - this.min) / (this.max - this.min); - const tipOffsetLow = 8 - (low * 0.15); - const tipOffsetHigh = 8 - (high * 0.15); + this.rangeDiv.style.setProperty("--low", low + '%'); this.rangeDiv.style.setProperty("--high", high + '%'); - $(this.inputTipLocator).css({ - 'left': `calc(${low}% + (${tipOffsetLow}px))`, - 'top': '3px' - }); - $(this.ghostTipLocator).css({ - 'left': `calc(${high}% + (${tipOffsetHigh}px))`, - 'top': '18px' - }); - $(this.inputTipLocator).add($(this.ghostTipLocator)).popover('update'); this.counterInputUpdate(); } @@ -253,16 +224,17 @@ class Multirange { counter = this.leftCounter; input = this.leftInput; } - if (counter.style.display === "none") { + + if (counter.classList.contains("invisible")) { this.input.valueLow = this.leftInput.value; this.input.valueHigh = this.rightInput.value; this.dispatchNewValueEvent(); this.update(); - counter.style.display = ""; - input.style.display = "none"; + counter.classList.remove("invisible"); + input.classList.add("invisible"); } else { - counter.style.display = "none"; - input.style.display = ""; + counter.classList.add("invisible"); + input.classList.remove("invisible"); this.saveOldValues(); // Hack because firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1057858 window.setTimeout(function () { diff --git a/addons/website/static/lib/multirange/multirange_custom.scss b/addons/website/static/lib/multirange/multirange_custom.scss index c170b0f2724..ae34ad43a2d 100644 --- a/addons/website/static/lib/multirange/multirange_custom.scss +++ b/addons/website/static/lib/multirange/multirange_custom.scss @@ -2,84 +2,74 @@ // which can be found on https://github.com/LeaVerou/multirange. // The license file can be found in the same folder as this file. - input[type="range"][multiple] { +input[type="range"][multiple] { pointer-events: none; visibility: hidden; +} - &::-webkit-slider-thumb { - pointer-events: auto; - } - - &::-moz-range-thumb { - pointer-events: auto; - } - - &.reverse { - direction: rtl; - } - - &.multirange { - width: 100%; - padding: 0; - margin: 0; - display: inline-block; - vertical-align: top; - +.multirange-wrapper { + input[type="range"][multiple] { + visibility: initial; &::-webkit-slider-thumb { - height: 16px; - width: 16px; + pointer-events: auto; } - &.original { - position: absolute; + &::-moz-range-thumb { + pointer-events: auto; + } - &::-webkit-slider-thumb { + &.reverse { + direction: rtl; + } + + &.multirange { + &::-moz-range-track { + border-color: transparent; /* needed to switch Firefox to "styleable" control */ + } + + &.original::-webkit-slider-thumb { position: relative; z-index: 2; } - &::-moz-range-thumb { - transform: scale(1); /* Firefox doesn't apply position it seems */ - z-index: 1; + &.ghost { + + // Workaround to handle Firefox's lack of support of z-index rules + // for #shadow-root elements, see '&.original::-webkit-slider-thumb' + // rules. The entire @media query could be removed once Firefox + // will support the feature. + @media all and (min--moz-device-pixel-ratio:0) and (min-resolution: .001dpcm) { + + // Helper function to retrive the 'width' segment from a 'border' shorthand rule. + @function -get-border-width($input) { + @each $part in $input { + @if type-of($part) == number { + @return $part; + } + } + @return null; + } + + $-thumb-border-width: #{-get-border-width($form-range-thumb-border)}; + $-ghostGap: calc(#{$form-range-thumb-width} + (#{$-thumb-border-width} * 2)); + + margin-inline-start: $-ghostGap; + width: calc(100% - #{$-ghostGap}); + } + + &::-webkit-slider-runnable-track { + background: linear-gradient(to right, transparent var(--low), var(--primary) var(--low) var(--high), transparent 0) no-repeat 50% / 100% 100%; + } + + &::-moz-range-track { + background: linear-gradient(to right, transparent var(--low), var(--primary) var(--low) var(--high), transparent 0) no-repeat 50% / 100% 100%; + } } } - - &::-moz-range-track { - border-color: transparent; /* needed to switch Firefox to "styleable" control */ - } - - &.ghost { - border-radius: 45%; - position: relative; - background: var(--track-background); - --track-background: linear-gradient(to right, transparent var(--low), #{theme-color('primary')} var(--low) var(--high), transparent 0) no-repeat 50% / 100% 35%; - - &::-webkit-slider-runnable-track { - background: var(--track-background); - } - - &::-moz-range-track { - background: var(--track-background); - } - } - } -} - -.multirange-wrapper { - position: relative; - margin: 3rem 0; - visibility: hidden; - - input[type="range"][multiple] { - visibility: initial; } [x-out-of-boundaries] { display: none; } } - -.tip-locator { - position: absolute; -}