chore(filters): filter card responsiveness; slider appearance and functionality

This commit is contained in:
2026-03-13 19:14:18 +01:00
parent 1bf7596b80
commit 45947cd491
2 changed files with 93 additions and 88 deletions
+83 -69
View File
@@ -1,6 +1,7 @@
<template>
<div class="filter-slider">
<div class="filter-slider-container">
<input
class="slider"
v-for="slider in sliderGroupsOptions[sliderGroup]"
type="range"
:name="slider.id"
@@ -10,6 +11,8 @@
:step="slider.step"
v-model="filters[slider.id]"
/>
<div class="slider-track" @click="moveCloserSliderToMousePos"></div>
</div>
</template>
@@ -25,90 +28,113 @@ const props = defineProps({
required: true
}
});
// Change slider value that's the closest one to the mouse position on the slider track click
function moveCloserSliderToMousePos(e: MouseEvent) {
const { clientX, target } = e;
const { minRange, maxRange, step } = sliderGroupsOptions[props.sliderGroup][0];
const boundingRect = (target as HTMLElement).getBoundingClientRect();
const mouseX = clientX - boundingRect.left;
const leftSliderValue = filters[sliderGroupsOptions[props.sliderGroup][0].id];
const rightSliderValue = filters[sliderGroupsOptions[props.sliderGroup][1].id];
let mouseValue = Math.round((maxRange - minRange) * (mouseX / boundingRect.width));
// Adjust mouse value to the closest step point (divide by 10, get rounded number, then multiply by step)
mouseValue = Math.round(mouseValue / step) * step;
let sliderIndex =
Math.abs(leftSliderValue - mouseValue) < Math.abs(rightSliderValue - mouseValue) ? 0 : 1;
filters[sliderGroupsOptions[props.sliderGroup][sliderIndex].id] = mouseValue;
}
</script>
<style lang="scss" scoped>
@use '../../styles/responsive';
.filter-slider {
.filter-slider-container {
position: relative;
padding: 0.5em;
height: 1.25em;
}
.filter-slider > input {
.slider-track {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 1em;
z-index: 10;
cursor: pointer;
background-color: #444;
transition: background-color 0.2s;
&:hover {
background-color: #4d4d4d;
}
}
.slider {
width: 100%;
height: 1.25em;
background: none;
outline: none;
border-radius: 1em;
padding: 0;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: 100;
pointer-events: none;
cursor: pointer;
-webkit-appearance: none;
appearance: none;
background: none;
border: none;
outline: none;
pointer-events: none;
&:focus-visible ~ * {
color: gold;
&:hover ~ .slider-track {
background-color: #4d4d4d;
}
&:focus-visible {
outline: 1px solid white;
}
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
pointer-events: all;
position: relative;
z-index: 100;
height: 20px;
width: 20px;
margin-top: -7px;
width: 1.25em;
height: 1.25em;
border-radius: 1em;
background: var(--clr-primary);
border-radius: 50%;
background-color: var(--clr-primary);
@include responsive.smallScreen {
width: 15px;
height: 15px;
margin-top: -5px;
}
pointer-events: all;
}
&::-moz-range-thumb {
pointer-events: all;
position: relative;
z-index: 10;
height: 1em;
width: 1em;
border-radius: 50%;
background-color: #333;
border: 3px solid var(--clr-primary);
cursor: pointer;
@include responsive.smallScreen {
width: 1em;
height: 1em;
}
}
&::-webkit-slider-runnable-track {
position: relative;
z-index: 1;
width: 100%;
height: 5px;
cursor: pointer;
width: 1.25em;
height: 1.25em;
border-radius: 1em;
background: var(--clr-primary);
pointer-events: all;
}
&:first-child::-webkit-slider-runnable-track {
background: var(--clr-primary);
}
// &:first-child::-webkit-slider-runnable-track {
// }
&::-moz-range-track {
position: relative;
@@ -121,20 +147,8 @@ const props = defineProps({
border-radius: 1em;
}
&:first-child::-moz-range-track {
background: var(--clr-primary);
}
&::-ms-track {
width: 100%;
height: 5px;
cursor: pointer;
background: none;
border-radius: 1em;
}
&:first-child::-ms-track {
background: white;
}
// &:first-child::-moz-range-track {
// background: var(--clr-primary);
// }
}
</style>
@@ -137,7 +137,7 @@
</section>
<section class="card_sliders">
<div class="slider-box" v-for="(sliderGroup, i) in sliderGroups" :key="i">
<div class="option-slider" v-for="(sliderGroup, i) in sliderGroups" :key="i">
<FilterSlider :sliderGroup="sliderGroup" />
<span class="slider-value">
@@ -593,38 +593,29 @@ h3.hours-section-header {
margin-top: 1em;
}
.slider-box {
.option-slider {
display: grid;
align-items: center;
grid-template-columns: 250px 100px 1fr;
gap: 0.25em;
margin-bottom: 1em;
&-value {
color: var(--clr-primary);
padding: 0.1em 0.2em;
text-align: center;
}
}
.slider-value {
color: var(--clr-primary);
padding: 0.1em 0.2em;
text-align: center;
font-weight: bold;
}
@include responsive.smallScreen {
.slider-box {
display: flex;
flex-wrap: wrap;
justify-content: center;
.option-slider {
grid-template-columns: 1fr;
}
&-input {
width: 90%;
}
&-content {
text-align: center;
}
.slider-content {
text-align: center;
}
.card_controls > button > p {