count-wheel.vue
edited
1<script setup lang="ts">
2import { computed, ref, toRef, watch } from 'vue';
3
4import { formatCompactNumber } from '~/lib/intl/number';
5
6const props = defineProps<{
7 value: number;
8}>();
9
10const increasing = ref(false);
11const formatted = computed(() => formatCompactNumber(props.value));
12
13watch(toRef(props, 'value'), (next, prev) => {
14 increasing.value = next > prev;
15});
16</script>
17
18<template>
19 <span :class="$style.root">
20 <Transition
21 :enter-active-class="increasing ? $style.slideUpEnter : $style.slideDownEnter"
22 :leave-active-class="increasing ? $style.slideUpLeave : $style.slideDownLeave"
23 >
24 <div :key="formatted">{{ formatted }}</div>
25 </Transition>
26 </span>
27</template>
28
29<style module>
30.root {
31 display: inline-block;
32 position: relative;
33 overflow: hidden;
34 text-overflow: ellipsis;
35 white-space: nowrap;
36}
37
38.slideUpEnter {
39 animation: slideUpEnter 300ms ease;
40}
41
42.slideUpLeave {
43 position: absolute;
44 animation: slideUpLeave 300ms ease;
45}
46
47@keyframes slideUpEnter {
48 from {
49 transform: translateY(100%);
50 opacity: 0;
51 }
52 to {
53 transform: translateY(0);
54 opacity: 100%;
55 }
56}
57
58@keyframes slideUpLeave {
59 from {
60 transform: translateY(0);
61 opacity: 100%;
62 }
63 to {
64 transform: translateY(-100%);
65 opacity: 0%;
66 }
67}
68
69.slideDownEnter {
70 animation: slideDownEnter 300ms ease;
71}
72
73.slideDownLeave {
74 position: absolute;
75 animation: slideDownLeave 300ms ease;
76}
77
78@keyframes slideDownEnter {
79 from {
80 transform: translateY(-100%);
81 opacity: 0;
82 }
83 to {
84 transform: translateY(0);
85 opacity: 100%;
86 }
87}
88
89@keyframes slideDownLeave {
90 from {
91 transform: translateY(0);
92 opacity: 100%;
93 }
94 to {
95 transform: translateY(100%);
96 opacity: 0%;
97 }
98}
99</style>