Fixed variable rate input needs to be wrapped in a fieldset /legend element and needs an associated label, on the input type range & 2 inputs type text.
<!-- Default -->
<div class="sds-range">
<div class="sds-range__body">
<input type="range" class="custom-range" id="range-input-1" value="12" min="10" max="24" aria-valuetext="12 sur 24 mois sélectionnés" aria-valuemin="10" aria-valuemax="24" aria-describedby="range-input-1-footer" />
</div>
<div class="sds-range__footer" id="range-input-1-footer">
<span class="sds-range__min">
<span>10</span>
</span>
<span class="sds-range__max">
<span>24</span>
</span>
</div>
</div>
<!-- Has Indicator -->
<div class="sds-range -rangeHasIndicator">
<div class="sds-range__body">
<input type="range" class="custom-range" id="range-input-indicator" value="12" min="10" max="24" aria-valuetext="12 sur 24 mois sélectionnés" aria-valuemin="10" aria-valuemax="24" aria-describedby="range-input-indicator-footer" />
<div class="sds-range__indicator" aria-hidden="true">
<span>12</span>
</div>
</div>
<div class="sds-range__footer" id="range-input-indicator-footer">
<span class="sds-range__min">
<span>10</span>
</span>
<span class="sds-range__max">
<span>24</span>
</span>
</div>
</div>
<!-- Fixed Variable Rate -->
<div class="sds-range -rangeHasRates">
<div class="sds-range__body">
<input type="range" class="custom-range" id="range-input-rate" value="17" min="10" max="24" aria-valuetext="17 sur 24 mois sélectionnés" aria-valuemin="10" aria-valuemax="24" aria-describedby="range-input-rate-footer" />
</div>
<div class="sds-range__footer" id="range-input-rate-footer">
<span class="sds-range__min">
<span>50%</span> <span>fixe</span>
</span>
<span class="sds-range__max">
<span>50%</span> <span>variable</span>
</span>
</div>
<div class="sds-range__rates">
<div class="row row-sm">
<div class="col-6">
<div class="sds-input">
<input id="" class="sds-input form-control" type="text" placeholder="Entrez une communication" value="250.000€" readonly>
</div>
</div>
<div class="col-6">
<div class="sds-input">
<input id="" class="sds-input form-control" type="text" placeholder="Entrez une communication" value="250.000€" readonly>
</div>
</div>
</div>
</div>
</div>
<!-- Disabled -->
<div class="sds-range -rangeHasIndicator">
<div class="sds-range__body">
<input type="range" disabled class="custom-range" id="range-input-disabled" value="3" min="0" max="15" aria-valuetext="3 sur 15 mois sélectionnés" aria-valuemin="0" aria-valuemax="15" aria-describedby="range-input-disabled-footer" />
<div class="sds-range__indicator" aria-hidden="true">
<span>3</span>
</div>
</div>
</div>
<div class="{{ namespace }}range{% for mod in modifiers %} {{ mod }}{% endfor %}{% for mod in classes %} {{ mod }}{% endfor %}">
<div class="{{ namespace }}range__body">
<input type="range"{% if disabled %} disabled{% endif %}
class="custom-range"
id="{{ id }}"
value="{{ currentValue }}"
min="{{ minValue }}"
max="{{ maxValue }}"
aria-valuetext="{{ currentValue }} sur {{ maxValue }} mois sélectionnés"
aria-valuemin="{{ minValue }}"
aria-valuemax="{{ maxValue }}"
aria-describedby="{{ id }}-footer" />
{% if hasIndicator %}
<div class="{{ namespace }}range__indicator" aria-hidden="true">
<span>{{ currentValue }}</span>{{ indicatorValueType }}
</div>
{% endif %}
</div>
{% if footer %}
<div class="{{ namespace }}range__footer" id="{{ id }}-footer">
<span class="{{ namespace }}range__min">
<span>{{ minValueText }}</span>{% if rate %} <span>fixe</span>{% endif %}
</span>
<span class="{{ namespace }}range__max">
<span>{{ maxValueText }}</span>{% if rate %} <span>variable</span>{% endif %}
</span>
</div>
{% endif %}
{% if rate %}
<div class="{{ namespace }}range__rates">
<div class="row row-sm">
<div class="col-6">
{% render "@input--readonly",{value: "250.000€"},true %}
</div>
<div class="col-6">
{% render "@input--readonly",{value: "250.000€"},true %}
</div>
</div>
</div>
{% endif %}
</div>
export default class RangeInput {
constructor() {
this.fillTrackColor();
}
fillTrackColor() {
const rangeInputs = document.querySelectorAll("input[type='range']");
function defineRangebehaviour (el) {
let styles = getComputedStyle(el);
let progressColor = styles.getPropertyValue('--custom-range-progress-color');
let trackColor = styles.getPropertyValue('--custom-range-track-color');
let percent = (100 * (el.value - el.min)) / (el.max - el.min) + "%";
let indicator = el.parentNode.querySelector(".sds-range__indicator span");
el.style.backgroundImage = `linear-gradient( to right, ${progressColor}, ${progressColor} ${percent}, ${trackColor} ${percent})`;
if(indicator) {
indicator.textContent = el.value;
indicator.parentNode.style.left = `calc(${percent})`;
indicator.parentNode.style.transform = `translateX(-${percent})`;
}
el.setAttribute("aria-valuetext", el.value + " sur " + el.max + " mois sélectionnés");
el.setAttribute("value", el.value);
}
rangeInputs.forEach((el, i) => {
defineRangebehaviour(el)
})
rangeInputs.forEach((el, i) => {
el.addEventListener("input", function () {
defineRangebehaviour(el)
});
})
}
}
/* variables specific to current element */
$element-specific-variables: "";
.#{$namespace}range {
/* are only defined without being declared anywhere because they are purely a JS hook */
--custom-range-progress-color: var(--comp-range-knob-background-color);
--custom-range-track-color: var(--comp-range-background-color);
/* Save root element context for easy access if nesting is needed */
$self: &;
/* properties of current element + media queries */
/* Pseudo Elements */
&::before {
}
&::after {
}
/*
Include elements that are linked to the current element but have to reside at the root level of the stylesheet
(e.g: keyframes)
*/
@at-root {
}
/* children - write selector in full in comments in order to facilitate search */
LABEL {
margin-bottom: 0;
}
&__body {
height: var(--comp-range-knob-height);
display: flex;
align-items: center;
position: relative;
}
&__indicator {
position: absolute;
top: calc(var(--comp-range-knob-height) * -1);
text-align: center;
white-space: nowrap;
@include custom-prop-fallback("color", "comp-range-knob-label-text-color");
@extend %textHelper;
}
&__footer {
display: flex;
justify-content: space-between;
margin-top: var(--ui-space-stack-static-500);
@include custom-prop-fallback("color", "comp-range-min-text-color");
@extend %textHelper;
}
&__rates {
margin-top: var(--ui-space-stack-static-500);
}
INPUT[type="range"] {
&[disabled] {
--custom-range-progress-color: var(--comp-range-disabled-knob-background-color);
--custom-range-track-color: var(--comp-range-disabled-background-color);
}
}
/* modifiers */
&.-rangeHasIndicator,
&.-hasIndicator {
padding-top: var(--comp-range-knob-height);
}
&.-rangeHasRates,
&.-rate {
--custom-range-progress-color: var(--comp-range-segment-fixed-background-color);
--custom-range-track-color: var(--comp-range-segment-variable-background-color);
#{$self}__min {
@include custom-prop-fallback("color", "comp-range-fixed-text-color");
}
#{$self}__max {
@include custom-prop-fallback("color", "comp-range-variable-text-color");
}
}
&.-rangeAlignToInput,
&.-alignToInput {
@extend .form-control;
border-bottom: 0;
display: flex;
width: 100%;
align-items: flex-end;
padding: 0;
#{$self}__body {
width: 100%;
}
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}