ADD: Sexy slider animations

Dear god this was a huge pain in the ass to get right. Worth it 
This commit is contained in:
Robert Kossessa
2024-03-13 05:55:11 +01:00
parent 7bed719647
commit 23c905a71c
3 changed files with 48 additions and 3 deletions

View File

@@ -131,6 +131,7 @@
" "
/> />
<SliderThumb <SliderThumb
:class="{ 'transition-all': animateSliders }"
class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)" style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)"
> >
@@ -152,6 +153,7 @@
}" }"
/> />
<SliderThumb <SliderThumb
:class="{ 'transition-all': animateSliders }"
class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)" style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)"
> >
@@ -171,6 +173,7 @@
:style="{ background: `linear-gradient(90deg, black, ${valueSliderColor.hex()} 100%` }" :style="{ background: `linear-gradient(90deg, black, ${valueSliderColor.hex()} 100%` }"
/> />
<SliderThumb <SliderThumb
:class="{ 'transition-all': animateSliders }"
class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" class="flex h-6 w-8 cursor-pointer items-center justify-center rounded-[8px] border border-zinc-100 bg-zinc-300 text-zinc-600 hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)" style="box-shadow: -3px 0 15px 0 rgba(0, 0, 0, 0.6)"
> >
@@ -266,6 +269,17 @@ const valueSliderColor = computed(() => {
return Color.hsv(hueSliderModel.value[0], saturationSliderModel.value[0], 100) return Color.hsv(hueSliderModel.value[0], saturationSliderModel.value[0], 100)
}) })
const animateSliders = ref(false)
const disableAnimateSliders = useDebounceFn(() => {
animateSliders.value = false
}, 150)
const enableAnimateSliders = () => {
console.log('ANIMATE!!!')
animateSliders.value = true
disableAnimateSliders()
}
defineExpose({ enableAnimateSliders })
const hexInput = ref('FF0000') const hexInput = ref('FF0000')
const hueInput = ref('000') const hueInput = ref('000')
const saturationInput = ref('100') const saturationInput = ref('100')
@@ -280,6 +294,7 @@ function onSubmitHexInput() {
input = '#' + input input = '#' + input
} }
if (input.match(/^#[0-9A-F]{6}$/i)) { if (input.match(/^#[0-9A-F]{6}$/i)) {
enableAnimateSliders()
color.value = Color(input) color.value = Color(input)
} else shake() } else shake()
} }
@@ -290,6 +305,7 @@ function onSubmitHueInput() {
shake() shake()
return return
} }
enableAnimateSliders()
const newHue = Math.max(0, Math.min(input, 360)) const newHue = Math.max(0, Math.min(input, 360))
if (newHue === color.value.hue()) { if (newHue === color.value.hue()) {
updateInputs() updateInputs()
@@ -303,6 +319,7 @@ function onSubmitSaturationInput() {
shake() shake()
return return
} }
enableAnimateSliders()
const newSaturation = Math.max(0, Math.min(input, 100)) const newSaturation = Math.max(0, Math.min(input, 100))
if (newSaturation === color.value.saturationv()) { if (newSaturation === color.value.saturationv()) {
updateInputs() updateInputs()
@@ -316,6 +333,7 @@ function onSubmitValueInput() {
shake() shake()
return return
} }
enableAnimateSliders()
const newValue = Math.max(0, Math.min(input, 100)) const newValue = Math.max(0, Math.min(input, 100))
if (newValue === color.value.value()) { if (newValue === color.value.value()) {
updateInputs() updateInputs()
@@ -331,6 +349,7 @@ function onSubmitRGBInput() {
shake() shake()
return return
} }
enableAnimateSliders()
const newColor = Color.rgb(r, g, b) const newColor = Color.rgb(r, g, b)
if (newColor.hex() === color.value.hex()) { if (newColor.hex() === color.value.hex()) {
updateInputs() updateInputs()

View File

@@ -17,7 +17,12 @@
? 'hover:bg-zinc-800 text-muted-foreground mx-[1px]' ? 'hover:bg-zinc-800 text-muted-foreground mx-[1px]'
: 'text-black bg-zinc-300 hover:bg-zinc-200 border-x border-t border-zinc-100' : 'text-black bg-zinc-300 hover:bg-zinc-200 border-x border-t border-zinc-100'
" "
@click="currentOption = key" @click="
() => {
enableAnimateSliders()
currentOption = key
}
"
> >
{{ $t(option.titleKey) }} {{ $t(option.titleKey) }}
</button> </button>
@@ -29,10 +34,16 @@
class="h-6 flex-1 transition-colors" class="h-6 flex-1 transition-colors"
:class="{ 'color-tab': currentOption === key }" :class="{ 'color-tab': currentOption === key }"
:style="{ background: Color(option.colorNumber).hex() }" :style="{ background: Color(option.colorNumber).hex() }"
@click="currentOption = key" @click="
() => {
enableAnimateSliders()
currentOption = key
}
"
/> />
</div> </div>
<HSVInput <HSVInput
ref="hsvInput"
:color-number="options[currentOption].colorNumber" :color-number="options[currentOption].colorNumber"
@input="(colorNumber) => $emit('input', currentOption, colorNumber)" @input="(colorNumber) => $emit('input', currentOption, colorNumber)"
/> />
@@ -47,6 +58,8 @@ defineEmits(['input'])
const currentOption = ref(null) const currentOption = ref(null)
const hsvInput = ref(null)
const currentColorHex = computed(() => Color(props.options[currentOption.value].colorNumber).hex()) const currentColorHex = computed(() => Color(props.options[currentOption.value].colorNumber).hex())
const props = defineProps({ const props = defineProps({
@@ -69,6 +82,11 @@ const props = defineProps({
} }
}) })
function enableAnimateSliders() {
hsvInput.value.enableAnimateSliders()
}
defineExpose({ enableAnimateSliders })
onBeforeMount(() => { onBeforeMount(() => {
if (currentOption.value === null) currentOption.value = Object.keys(props.options)[0] if (currentOption.value === null) currentOption.value = Object.keys(props.options)[0]
}) })

View File

@@ -1,6 +1,7 @@
<template> <template>
<ConfigSection title="Key Colors" :icon-component="Palette"> <ConfigSection title="Key Colors" :icon-component="Palette">
<PaletteInput <PaletteInput
ref="paletteInput"
:options="keyColors" :options="keyColors"
@input=" @input="
(optionKey, colorNumber) => { (optionKey, colorNumber) => {
@@ -23,12 +24,14 @@ import PaletteInput from '@renderer/components/common/PaletteInput.vue'
import { useDeviceStore } from '@renderer/deviceStore' import { useDeviceStore } from '@renderer/deviceStore'
import { useAppStore } from '@renderer/appStore' import { useAppStore } from '@renderer/appStore'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { computed } from 'vue' import { computed, ref, watch } from 'vue'
const appStore = useAppStore() const appStore = useAppStore()
const deviceStore = useDeviceStore() const deviceStore = useDeviceStore()
const { keyColor } = storeToRefs(deviceStore) const { keyColor } = storeToRefs(deviceStore)
const paletteInput = ref(null)
const keyColors = computed({ const keyColors = computed({
get() { get() {
return { return {
@@ -51,4 +54,9 @@ const keyColors = computed({
} }
} }
}) })
watch(
() => appStore.selectedKey,
() => paletteInput.value.enableAnimateSliders()
)
</script> </script>