forked from platypush/platypush
[UI] Full restyle of Slider
component.
The component has been rewritten using only CSS 3 and no JS.
This commit is contained in:
parent
b785609eda
commit
80c2f0d8dd
10 changed files with 128 additions and 96 deletions
|
@ -67,7 +67,7 @@
|
|||
<div class="col-9">
|
||||
<Slider :range="colorConverter.ranges.hue" :disabled="loading"
|
||||
:value="animations.color_transition.hue_step"
|
||||
@mouseup="animations.color_transition.hue_step = parseFloat($event.target.value)" />
|
||||
@change="animations.color_transition.hue_step = parseFloat($event.target.value)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -78,7 +78,7 @@
|
|||
<div class="col-9">
|
||||
<Slider :range="colorConverter.ranges.sat" :disabled="loading"
|
||||
:value="animations.color_transition.sat_step"
|
||||
@mouseup="animations.color_transition.sat_step = parseFloat($event.target.value)" />
|
||||
@change="animations.color_transition.sat_step = parseFloat($event.target.value)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -89,7 +89,7 @@
|
|||
<div class="col-9">
|
||||
<Slider :range="colorConverter.ranges.bri" :disabled="loading"
|
||||
:value="animations.color_transition.bri_step"
|
||||
@mouseup="animations.color_transition.bri_step = parseFloat($event.target.value)" />
|
||||
@change="animations.color_transition.bri_step = parseFloat($event.target.value)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
<div class="col-11 control">
|
||||
<Slider :range="colorConverter.ranges.bri" :disabled="loading" :value="state.bri"
|
||||
@mouseup.stop="$emit(light ? 'set-light' : 'set-group', {brightness: parseInt($event.target.value)})" />
|
||||
@change.stop="$emit(light ? 'set-light' : 'set-group', {brightness: parseInt($event.target.value)})" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
<div class="col-11 control">
|
||||
<Slider :range="colorConverter.ranges.ct" :disabled="loading" :value="state.ct"
|
||||
@mouseup.stop="$emit(light ? 'set-light' : 'set-group', {temperature: parseInt($event.target.value)})" />
|
||||
@change.stop="$emit(light ? 'set-light' : 'set-group', {temperature: parseInt($event.target.value)})" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</div>
|
||||
<div class="col-s-8 col-m-10 time-bar">
|
||||
<Slider :value="elapsed" :range="[0, duration]" :disabled="!duration || status.state === 'stop'"
|
||||
@input="$emit('seek', $event.target.value)" />
|
||||
@change="$emit('seek', $event.target.value)" />
|
||||
</div>
|
||||
<div class="col-s-2 col-m-1 time">
|
||||
<span class="total-time"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<div class="col-11 volume-slider">
|
||||
<Slider :value="status.volume" :range="volumeRange" :disabled="status.volume == null"
|
||||
@input="$emit('set-volume', $event.target.value)" />
|
||||
@change="$emit('set-volume', $event.target.value)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -15,13 +15,9 @@
|
|||
:disabled="disabled"
|
||||
:value="value"
|
||||
ref="range"
|
||||
@input.stop="onUpdate"
|
||||
@change.stop="onUpdate">
|
||||
@input.stop="$emit('input', $event)"
|
||||
@change.stop="$emit('change', $event)">
|
||||
|
||||
<div class="track" :class="{'with-label': withLabel}">
|
||||
<div class="track-inner" ref="track"></div>
|
||||
</div>
|
||||
<div class="thumb" ref="thumb"></div>
|
||||
<span class="label" v-if="withLabel" v-text="value" ref="label"></span>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -29,8 +25,7 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
name: "Slider",
|
||||
emits: ['input', 'change', 'mouseup', 'mousedown', 'touchstart', 'touchend', 'keyup', 'keydown'],
|
||||
emits: ['input', 'change'],
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
|
@ -61,41 +56,13 @@ export default {
|
|||
default: false,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onUpdate(event) {
|
||||
this.update(event.target.value)
|
||||
this.$emit(event.type, {
|
||||
...event,
|
||||
target: {
|
||||
...event.target,
|
||||
value: this.$refs.range.value,
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
update(value) {
|
||||
const sliderWidth = this.$refs.range.clientWidth
|
||||
const percent = (value - this.range[0]) / (this.range[1] - this.range[0])
|
||||
const innerWidth = percent * sliderWidth
|
||||
const thumb = this.$refs.thumb
|
||||
|
||||
thumb.style.left = `${innerWidth - thumb.clientWidth / 2}px`
|
||||
this.$refs.thumb.style.transform = `translate(-${percent}%, -50%)`
|
||||
this.$refs.track.style.width = `${innerWidth}px`
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.value != null)
|
||||
this.update(this.value)
|
||||
this.$watch(() => this.value, (newValue) => this.update(newValue))
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$label-width: 3em;
|
||||
$thumb-height: 1em;
|
||||
$slider-height: 0.5em;
|
||||
|
||||
.slider-wrapper {
|
||||
width: 100%;
|
||||
|
@ -109,13 +76,114 @@ $label-width: 3em;
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.slider {
|
||||
input.slider {
|
||||
width: 100%;
|
||||
background: none;
|
||||
height: 1.5em;
|
||||
position: relative;
|
||||
border-radius: 0.5em;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
outline: none;
|
||||
overflow: hidden;
|
||||
transition: all ease 100ms;
|
||||
@include appearance(none);
|
||||
|
||||
&::-ms-tooltip {
|
||||
display: none;
|
||||
&:active {
|
||||
filter: brightness(80%);
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
filter: saturate(130%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
/* Chrome and friends */
|
||||
&::-webkit-slider-runnable-track {
|
||||
position: relative;
|
||||
border-radius: $slider-height;
|
||||
background: linear-gradient($slider-bg 0 0) scroll no-repeat center /
|
||||
100% calc(#{$slider-height} + 1px);
|
||||
}
|
||||
|
||||
&::-webkit-slider-runnable-track,
|
||||
&::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
transition: all ease 100ms;
|
||||
height: $thumb-height;
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
--clip-top: calc((#{$thumb-height} - #{$slider-height}) * 0.5);
|
||||
--clip-bottom: calc(#{$thumb-height} - var(--clip-top));
|
||||
--clip-further: calc(100% + 1px);
|
||||
|
||||
width: $thumb-height;
|
||||
background: $slider-progress-bg;
|
||||
box-shadow: calc(-100vmax - #{$thumb-height} + 2.5px) #{$slider-height} #{$slider-height} 100vmax #{$slider-progress-bg};
|
||||
border-radius: $thumb-height;
|
||||
cursor: grab;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(130%) blur(1px);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
clip-path: polygon(
|
||||
100% -1px,
|
||||
#{$slider-height} -1px,
|
||||
0 var(--clip-top),
|
||||
-100vmax var(--clip-top),
|
||||
-100vmax var(--clip-bottom),
|
||||
0 var(--clip-bottom),
|
||||
#{$slider-height} 100%,
|
||||
var(--clip-further) var(--clip-further)
|
||||
);
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
&::-moz-range-track {
|
||||
background: $slider-bg;
|
||||
position: relative;
|
||||
height: $slider-height;
|
||||
border-radius: 0.5em;
|
||||
box-shadow: inset 1px 0px 3px 0 $slider-track-shadow;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
$thumb-height: 1.125em;
|
||||
width: $thumb-height;
|
||||
height: $thumb-height;
|
||||
position: relative;
|
||||
background: $slider-thumb-bg;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
cursor: grabbing;
|
||||
transition: all ease 100ms;
|
||||
@include appearance(none);
|
||||
|
||||
&:hover {
|
||||
filter: brightness(130%) blur(1px);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: $slider-thumb-disabled-bg;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
&::-moz-range-progress {
|
||||
width: 100%;
|
||||
height: $slider-height;
|
||||
cursor: pointer;
|
||||
background: $slider-progress-bg;
|
||||
border-radius: 0.5em 0 0 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,10 +191,6 @@ $label-width: 3em;
|
|||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
&.with-label {
|
||||
width: calc(100% - $label-width);
|
||||
}
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
@ -137,47 +201,15 @@ $label-width: 3em;
|
|||
}
|
||||
}
|
||||
|
||||
.track {
|
||||
width: 100%;
|
||||
height: 0.75em;
|
||||
background: $slider-bg;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
border-radius: 0.5em;
|
||||
box-shadow: inset 1px 0px 3px 0 $slider-track-shadow;
|
||||
pointer-events: none;
|
||||
|
||||
.track-inner {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
background: $slider-progress-bg;
|
||||
border-radius: 0.5em 0 0 0.5em;
|
||||
}
|
||||
|
||||
&.with-label {
|
||||
width: calc(100% - $label-width);
|
||||
}
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 1.25em;
|
||||
height: 1.25em;
|
||||
background: $slider-thumb-bg;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translate(0%, -50%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 1px 0px 2px 0 $slider-thumb-shadow;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: $label-width;
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.with-label {
|
||||
width: calc(100% - $label-width);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
|
||||
<div class="value">
|
||||
<Slider :value="audioVolume" :range="[0, 100]"
|
||||
@input="onVolumeChange" />
|
||||
@change="onVolumeChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<div class="input" v-if="value?.min != null && value?.max != null">
|
||||
<div class="col-10">
|
||||
<Slider :range="[value.min, value.max]" with-range
|
||||
:value="value.value" @input="setValue" />
|
||||
:value="value.value" @change="setValue" />
|
||||
</div>
|
||||
<div class="col-2 value">
|
||||
<input type="number" :value="value.value" @change="setValue">
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
<div class="input">
|
||||
<Slider :range="[value.brightness_min, value.brightness_max]"
|
||||
:value="value.brightness" @input="setLight({brightness: $event.target.value})" />
|
||||
:value="value.brightness" @change="setLight({brightness: $event.target.value})" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -51,7 +51,7 @@
|
|||
</div>
|
||||
<div class="input">
|
||||
<Slider :range="[value.saturation_min, value.saturation_max]"
|
||||
:value="value.saturation" @input="setLight({saturation: $event.target.value})" />
|
||||
:value="value.saturation" @change="setLight({saturation: $event.target.value})" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -61,7 +61,7 @@
|
|||
</div>
|
||||
<div class="input">
|
||||
<Slider :range="[value.temperature_min, value.temperature_max]"
|
||||
:value="value.temperature" @input="setLight({temperature: $event.target.value})"/>
|
||||
:value="value.temperature" @change="setLight({temperature: $event.target.value})"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="col-s-12 col-m-9 controls">
|
||||
<div class="col-10 slider-container">
|
||||
<Slider :range="[0, 100]" :value="config.volume.percent"
|
||||
@mouseup="$emit('volume-change', {host: server.name, client: id, volume: $event.target.value})" />
|
||||
@change="$emit('volume-change', {host: server.name, client: id, volume: $event.target.value})" />
|
||||
</div>
|
||||
|
||||
<div class="col-2 switch pull-right">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div :class="{'col-6': hasIcon, 'col-7': !hasIcon}" v-text="name" />
|
||||
<div class="col-5 slider-container">
|
||||
<div class="slider">
|
||||
<SliderElement :value="value" :range="[parseFloat(min), parseFloat(max)]" @mouseup="run" />
|
||||
<SliderElement :value="value" :range="[parseFloat(min), parseFloat(max)]" @change="run" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue