Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #96 from ToBinio/snapping-slider
Browse files Browse the repository at this point in the history
add snappingPoints to slider
  • Loading branch information
Prospector authored Oct 11, 2023
2 parents 0ab17e1 + 3955b97 commit a260b6e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/components/slider.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const valueTwo = ref(0)

<DemoContainer>
<Slider v-model="value" :min="1000" :max="10000" :step="1000" unit="mb"/>
<Slider v-model="value" :min="1024" :max="32768" :step="1" :snapPoints='[2048,4096,8192,16384]' :snapRange='500' unit="mb"/>
<Slider v-model="valueTwo" :min="1000" :max="10000" :step="1000" unit="mb" :disabled="true"/>
</DemoContainer>

Expand Down
62 changes: 61 additions & 1 deletion lib/components/base/Slider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
<div class="root-container">
<div class="slider-component">
<div class="slide-container">
<div class="snap-points">
<div
class="snap-point"
:class="{ green: snapPoint <= currentValue }"
v-for="snapPoint in props.snapPoints"
v-bind:key="snapPoint"
:style="{ left: ((snapPoint - props.min) / (props.max - props.min)) * 100 + '%' }"
></div>
</div>
<input
ref="input"
v-model="currentValue"
Expand All @@ -19,7 +28,7 @@
'--min-value': min,
'--max-value': max,
}"
@input="onInput($refs.input.value)"
@input="onInputWithSnap($refs.input.value)"
/>
<div class="slider-range">
<span> {{ min }} {{ unit }} </span>
Expand Down Expand Up @@ -64,6 +73,14 @@ const props = defineProps({
type: Boolean,
default: true,
},
snapPoints: {
type: Array,
default: () => [],
},
snapRange: {
type: Number,
default: 100,
},
disabled: {
type: Boolean,
default: false,
Expand All @@ -88,9 +105,24 @@ const inputValueValid = (newValue) => {
} else {
currentValue.value = (parsedValue - (props.forceStep ? parsedValue % props.step : 0)).toString()
}
emit('update:modelValue', parseInt(currentValue.value))
}
const onInputWithSnap = (value) => {
let parsedValue = parseInt(value)
for (let snapPoint of props.snapPoints) {
const distance = Math.abs(snapPoint - parsedValue)
if (distance < props.snapRange) {
parsedValue = snapPoint
}
}
inputValueValid(parsedValue)
}
const onInput = (value) => {
inputValueValid(value)
}
Expand All @@ -111,11 +143,15 @@ const onInput = (value) => {
.slider-component,
.slide-container {
width: 100%;
position: relative;
}
.slider-component .slide-container .slider {
-webkit-appearance: none;
appearance: none;
position: relative;
border-radius: var(--radius-sm);
height: 0.25rem;
background: linear-gradient(
Expand Down Expand Up @@ -144,6 +180,7 @@ const onInput = (value) => {
}
.slider-component .slide-container .slider::-moz-range-thumb {
border: none;
width: 0.75rem;
height: 0.75rem;
background: var(--color-brand);
Expand All @@ -164,6 +201,29 @@ const onInput = (value) => {
transition: 0.2s;
}
.slider-component .slide-container .snap-points {
position: absolute;
width: calc(100% - 0.75rem);
left: calc(0.75rem / 2);
top: calc(1rem / 2);
.snap-point {
position: absolute;
width: 0.25rem;
height: 0.75rem;
border-radius: var(--radius-sm);
background-color: var(--color-base);
transform: translateX(calc(-0.25rem / 2));
&.green {
background-color: var(--color-brand);
}
}
}
.slider-input {
width: 6rem;
margin-left: 0.75rem;
Expand Down

0 comments on commit a260b6e

Please sign in to comment.