testing
1,960 bytes View directory
1
<script lang="ts">2
import { Spring } from 'svelte/motion';4
const count = new Spring(0);5
const offset = $derived(modulo(count.current, 1));7
function modulo(n: number, m: number) {8
// handle negative numbers9
return ((n % m) + m) % m;10
}11
</script>13
<div class="counter">14
<button onclick={() => (count.target -= 1)} aria-label="Decrease the counter by one">15
<svg aria-hidden="true" viewBox="0 0 1 1">16
<path d="M0,0.5 L1,0.5" />17
</svg>18
</button>20
<div class="counter-viewport">21
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">22
<strong class="hidden" aria-hidden="true">{Math.floor(count.current + 1)}</strong>23
<strong>{Math.floor(count.current)}</strong>24
</div>25
</div>27
<button onclick={() => (count.target += 1)} aria-label="Increase the counter by one">28
<svg aria-hidden="true" viewBox="0 0 1 1">29
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />30
</svg>31
</button>32
</div>34
<style>35
.counter {36
display: flex;37
border-top: 1px solid rgba(0, 0, 0, 0.1);38
border-bottom: 1px solid rgba(0, 0, 0, 0.1);39
margin: 1rem 0;40
}42
.counter button {43
width: 2em;44
padding: 0;45
display: flex;46
align-items: center;47
justify-content: center;48
border: 0;49
background-color: transparent;50
touch-action: manipulation;51
font-size: 2rem;52
}54
.counter button:hover {55
background-color: var(--color-bg-1);56
}58
svg {59
width: 25%;60
height: 25%;61
}63
path {64
vector-effect: non-scaling-stroke;65
stroke-width: 2px;66
stroke: #444;67
}69
.counter-viewport {70
width: 8em;71
height: 4em;72
overflow: hidden;73
text-align: center;74
position: relative;75
}77
.counter-viewport strong {78
position: absolute;79
display: flex;80
width: 100%;81
height: 100%;82
font-weight: 400;83
color: var(--color-theme-1);84
font-size: 4rem;85
align-items: center;86
justify-content: center;87
}89
.counter-digits {90
position: absolute;91
width: 100%;92
height: 100%;93
}95
.hidden {96
top: -100%;97
user-select: none;98
}99
</style>