Skip to content

Commit 3525bce

Browse files
committed
feat: animated location counter + original flag size
1 parent db2a6ed commit 3525bce

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

app/components/CountryBubbles.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ function createMarkerElement(country: CountryHotspot): HTMLElement {
148148
outline: 1.5px solid rgb(0 0 0 / 0.2); outline-offset: -1.5px;
149149
`
150150
151-
// Flag container with rounded corners
151+
// Flag container with rounded corners (original icon size, clipped)
152152
const flagContainer = document.createElement('span')
153-
flagContainer.style.cssText = 'flex-shrink: 0; width: 24px; height: 18px; border-radius: 4px; overflow: hidden; display: flex;'
153+
flagContainer.style.cssText = 'flex-shrink: 0; border-radius: 4px; overflow: hidden; display: flex;'
154154
155155
const textContainer = document.createElement('div')
156156
textContainer.style.cssText = 'display: flex; flex-direction: column; text-align: left;'
@@ -286,8 +286,8 @@ function flyToCountry(country: CountryHotspot) {
286286
<Icon name="i-tabler:navigation-filled" text-neutral-600 size-16 />
287287
</div>
288288
<!-- Flag with rounded corners -->
289-
<span rounded-4 flex shrink-0 h-18 w-24 overflow-hidden>
290-
<Icon :name="bubble.flagIcon" h-full w-full />
289+
<span rounded-4 flex shrink-0 overflow-hidden>
290+
<Icon :name="bubble.flagIcon" />
291291
</span>
292292
<div flex="~ col" text-left>
293293
<span text="14 neutral-900" lh-tight font-semibold>{{ bubble.name }}</span>

app/components/LocationCounter.vue

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
<script setup lang="ts">
22
import { consola } from 'consola'
3+
import { animate, useMotionValue } from 'motion-v'
34
45
const { mapInstance } = useMapControls()
56
const { locationCount, clusterCount } = useVisibleLocations()
67
const hasVisibleFeatures = computed(() => locationCount.value > 0 || clusterCount.value > 0)
78
const count = ref<number | null>(null)
89
const loading = ref(false)
910
11+
// Animated count using motion value
12+
const animatedCount = useMotionValue(0)
13+
const displayCount = ref(0)
14+
15+
watch(count, (newCount) => {
16+
if (newCount === null)
17+
return
18+
animate(animatedCount, newCount, {
19+
duration: 0.4,
20+
ease: 'easeOut',
21+
onUpdate: (latest: number) => {
22+
displayCount.value = Math.round(latest)
23+
},
24+
})
25+
}, { immediate: true })
26+
1027
const updateCount = useDebounceFn(async () => {
1128
if (!mapInstance.value)
1229
return
@@ -58,18 +75,33 @@ watch(mapInstance, (map) => {
5875
>
5976
<div
6077
v-if="hasVisibleFeatures && count !== null && count > 0"
61-
6278
flex pointer-events-none bottom-8 left-0 right-0 justify-center fixed z-10
6379
>
6480
<div
6581
bg="white/90 backdrop-blur"
6682
text="neutral-700 f-xs"
67-
6883
outline="~ 1.5 neutral/8 offset--1.5"
6984
font-medium px-8 py-3 rounded-full pointer-events-auto shadow-lg
7085
>
71-
There are {{ count }} locations in this area
86+
There are <span align-middle inline-flex h-16 items-center overflow-hidden><span :key="displayCount" class="animate-slide-in" inline-block tabular-nums>{{ displayCount }}</span></span> locations in this area
7287
</div>
7388
</div>
7489
</Transition>
7590
</template>
91+
92+
<style scoped>
93+
.animate-slide-in {
94+
animation: slideIn 0.3s ease-out;
95+
}
96+
97+
@keyframes slideIn {
98+
from {
99+
opacity: 0;
100+
transform: translateY(100%);
101+
}
102+
to {
103+
opacity: 1;
104+
transform: translateY(0);
105+
}
106+
}
107+
</style>

app/components/Search.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ async function handleItemClick(item: SearchItem) {
178178

179179
<ComboboxAnchor as="div" inset-x-0 top-0 absolute z-60>
180180
<div mt-12 px-12 w-screen relative>
181-
<ComboboxInput ref="search-input" v-model="searchQuery" outline="0.5 neutral-400" name="search" placeholder="Search here" v-bind="$attrs" text-neutral px-47 py-10 rounded-full bg-neutral-0 w-full shadow transition-colors />
182-
<button p-0 border-0 bg-transparent cursor-pointer translate-y-13.5 left-24 top-0 absolute @click="handleClose">
181+
<ComboboxInput ref="search-input" v-model="searchQuery" outline="0.5 neutral-400" name="search" placeholder="Search here" v-bind="$attrs" text-neutral px-47 pb-12 pt-10 rounded-full bg-neutral-0 w-full shadow transition-colors />
182+
<button p-0 border-0 bg-transparent cursor-pointer translate-y-13.5 left-28 top-0 absolute @click="handleClose">
183183
<Icon v-if="!isComboboxOpen" name="i-tabler:search" op-70 size-18 />
184184
<Icon v-else name="i-tabler:arrow-left" op-70 size-18 />
185185
</button>

0 commit comments

Comments
 (0)