Characters remaining
An example of creating a character counter with spring animations in Motion for Vue
Source code
<script setup>
import { ref, watch,computed } from 'vue'
import { motion, transform , useAnimate } from 'motion-v'
const value = ref('')
const maxLength = 12
const charactersRemaining = computed(() => maxLength - value.value.length)
const [counterRef, animate] = useAnimate()
const mapRemainingToColor = transform([2, 6], ['#ff008c', '#ccc'])
watch(charactersRemaining, (newVal) => {
if (newVal > 6) return
const mapRemainingToSpringVelocity = transform([0, 5], [50, 0])
animate(
counterRef.value,
{ scale: 1 },
{
type: 'spring',
velocity: mapRemainingToSpringVelocity(newVal),
stiffness: 700,
damping: 80,
}
)
})
</script>
<template>
<div class="container">
<input v-model="value" />
<div>
<motion.span
ref="counterRef"
:style="{
color: mapRemainingToColor(charactersRemaining),
willChange: 'transform',
}"
>
{{ charactersRemaining }}
</motion.span>
</div>
</div>
</template>
<style>
.container,
input {
position: relative;
font-size: 32px;
line-height: 1;
}
input {
background-color: var(--layer);
color: var(--white);
border: 2px solid var(--border);
border-radius: 10px;
padding: 20px;
padding-right: 70px;
width: 300px;
}
input:focus {
border-color: var(--hue-blue);
}
.container div {
color: #ccc;
background: linear-gradient(
to right,
rgba(255, 255, 255, 0) 0%,
var(--layer) 20%
);
position: absolute;
top: 50%;
right: 2px;
transform: translateY(-50%);
padding: 10px;
padding-right: 20px;
padding-left: 50px;
}
.container div span {
display: block;
}
</style>Related examples
Latest in Vue
Motion+
Unlock all 400+ examples
- Source code for every Plus example.
- Provide examples direct to your agent via Motion's MCP.
- Lifetime access to new examples and APIs.








