feat(ui): replace hourglass animation with pickaxe mining swing
Replace the dead hourglass CSS animation with a thematic pickaxe mining animation. The pickaxe swings from resting position up to -45deg then strikes down, mimicking a mining motion. Used in the generatingNdebit loading state; other loading states still use BounceDots pending review. Refs #33 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
de6a9559ff
commit
10fab86371
4 changed files with 106 additions and 18 deletions
86
apps/machine/src/components/PickaxeIcon.vue
Normal file
86
apps/machine/src/components/PickaxeIcon.vue
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<div class="relative" :style="{ width: size * 1.5 + 'px', height: size * 1.5 + 'px' }">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 13 13"
|
||||||
|
:width="size"
|
||||||
|
:height="size"
|
||||||
|
shape-rendering="crispEdges"
|
||||||
|
class="animate-pickaxe absolute"
|
||||||
|
:style="{ left: '50%', bottom: '30%' }"
|
||||||
|
>
|
||||||
|
<rect x="4" y="0" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="5" y="0" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="6" y="0" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="7" y="0" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="8" y="0" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="3" y="1" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="4" y="1" width="1" height="1" fill="rgb(28,233,201)" />
|
||||||
|
<rect x="5" y="1" width="1" height="1" fill="rgb(24,198,170)" />
|
||||||
|
<rect x="6" y="1" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="7" y="1" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="8" y="1" width="1" height="1" fill="rgb(24,198,170)" />
|
||||||
|
<rect x="9" y="1" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="10" y="1" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="11" y="1" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="4" y="2" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="5" y="2" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="6" y="2" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="7" y="2" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="8" y="2" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="9" y="2" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="10" y="2" width="1" height="1" fill="rgb(136,103,32)" />
|
||||||
|
<rect x="11" y="2" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="8" y="3" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="9" y="3" width="1" height="1" fill="rgb(24,198,170)" />
|
||||||
|
<rect x="10" y="3" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="11" y="3" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="7" y="4" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="8" y="4" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="9" y="4" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="10" y="4" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="11" y="4" width="1" height="1" fill="rgb(24,198,170)" />
|
||||||
|
<rect x="12" y="4" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="6" y="5" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="7" y="5" width="1" height="1" fill="rgb(136,103,32)" />
|
||||||
|
<rect x="8" y="5" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="10" y="5" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="11" y="5" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="12" y="5" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="5" y="6" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="6" y="6" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="7" y="6" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="10" y="6" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="11" y="6" width="1" height="1" fill="rgb(25,177,152)" />
|
||||||
|
<rect x="12" y="6" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="4" y="7" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="5" y="7" width="1" height="1" fill="rgb(136,103,32)" />
|
||||||
|
<rect x="6" y="7" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="10" y="7" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="11" y="7" width="1" height="1" fill="rgb(24,198,170)" />
|
||||||
|
<rect x="12" y="7" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="3" y="8" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="4" y="8" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="5" y="8" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="10" y="8" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="11" y="8" width="1" height="1" fill="rgb(28,233,201)" />
|
||||||
|
<rect x="12" y="8" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="2" y="9" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="3" y="9" width="1" height="1" fill="rgb(136,103,32)" />
|
||||||
|
<rect x="4" y="9" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="11" y="9" width="1" height="1" fill="rgb(10,62,53)" />
|
||||||
|
<rect x="1" y="10" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="2" y="10" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="3" y="10" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="0" y="11" width="1" height="1" fill="rgb(72,53,18)" />
|
||||||
|
<rect x="1" y="11" width="1" height="1" fill="rgb(136,103,32)" />
|
||||||
|
<rect x="2" y="11" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
<rect x="0" y="12" width="1" height="1" fill="rgb(104,77,25)" />
|
||||||
|
<rect x="1" y="12" width="1" height="1" fill="rgb(39,30,9)" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
withDefaults(defineProps<{ size?: number }>(), { size: 96 })
|
||||||
|
</script>
|
||||||
|
|
@ -526,31 +526,31 @@
|
||||||
animation: float 3s ease-in-out infinite;
|
animation: float 3s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pickaxe mining swing */
|
/* Pickaxe mining swing — overhead strike into ground */
|
||||||
@keyframes pickaxe {
|
@keyframes pickaxe {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(-135deg);
|
||||||
}
|
}
|
||||||
20% {
|
20% {
|
||||||
transform: rotate(15deg);
|
transform: rotate(-150deg);
|
||||||
}
|
}
|
||||||
40% {
|
40% {
|
||||||
transform: rotate(-60deg);
|
transform: rotate(-45deg);
|
||||||
}
|
}
|
||||||
45% {
|
45% {
|
||||||
transform: rotate(-30deg);
|
transform: rotate(-75deg);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: rotate(-30deg);
|
transform: rotate(-75deg);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(-135deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@utility animate-pickaxe {
|
@utility animate-pickaxe {
|
||||||
animation: pickaxe 0.8s ease-in-out infinite;
|
animation: pickaxe 0.8s ease-in-out infinite;
|
||||||
transform-origin: bottom right;
|
transform-origin: 0% 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import QRCode from '@/components/QRCode.vue'
|
import QRCode from '@/components/QRCode.vue'
|
||||||
import StepIndicator from '@/components/StepIndicator.vue'
|
import StepIndicator from '@/components/StepIndicator.vue'
|
||||||
|
import PickaxeIcon from '@/components/PickaxeIcon.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const atmStore = useAtmStore()
|
const atmStore = useAtmStore()
|
||||||
|
|
@ -196,7 +197,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice)
|
||||||
key="fetchingRate"
|
key="fetchingRate"
|
||||||
class="flex flex-1 flex-col items-center justify-center gap-6"
|
class="flex flex-1 flex-col items-center justify-center gap-6"
|
||||||
>
|
>
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-2xl text-muted-foreground">Fetching exchange rate...</p>
|
<p class="text-2xl text-muted-foreground">Fetching exchange rate...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -300,7 +301,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice)
|
||||||
key="generatingNdebit"
|
key="generatingNdebit"
|
||||||
class="flex flex-1 flex-col items-center justify-center gap-6"
|
class="flex flex-1 flex-col items-center justify-center gap-6"
|
||||||
>
|
>
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-2xl text-muted-foreground">Preparing your withdraw code...</p>
|
<p class="text-2xl text-muted-foreground">Preparing your withdraw code...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -326,7 +327,7 @@ const isProcessing = computed(() => atmStore.isPayingInvoice)
|
||||||
|
|
||||||
<!-- Waiting indicator -->
|
<!-- Waiting indicator -->
|
||||||
<div class="flex items-center gap-3 pt-2 lg:pt-4">
|
<div class="flex items-center gap-3 pt-2 lg:pt-4">
|
||||||
<span class="text-2xl animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="32" />
|
||||||
<p class="text-sm lg:text-xl text-muted-foreground">Waiting for wallet scan...</p>
|
<p class="text-sm lg:text-xl text-muted-foreground">Waiting for wallet scan...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -364,13 +365,13 @@ const isProcessing = computed(() => atmStore.isPayingInvoice)
|
||||||
class="flex w-full lg:w-[48%] flex-col items-center justify-center bg-foreground/5 p-4 lg:p-6"
|
class="flex w-full lg:w-[48%] flex-col items-center justify-center bg-foreground/5 p-4 lg:p-6"
|
||||||
>
|
>
|
||||||
<div v-if="isGeneratingLnurl && !context?.ndebitUri">
|
<div v-if="isGeneratingLnurl && !context?.ndebitUri">
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="currentQrValue">
|
<div v-else-if="currentQrValue">
|
||||||
<QRCode :value="currentQrValue" :size="380" />
|
<QRCode :value="currentQrValue" :size="380" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="flex flex-col items-center gap-4">
|
<div v-else class="flex flex-col items-center gap-4">
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-xl text-muted-foreground">Generating...</p>
|
<p class="text-xl text-muted-foreground">Generating...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { Badge } from '@/components/ui/badge'
|
||||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||||
import QRCode from '@/components/QRCode.vue'
|
import QRCode from '@/components/QRCode.vue'
|
||||||
import StepIndicator from '@/components/StepIndicator.vue'
|
import StepIndicator from '@/components/StepIndicator.vue'
|
||||||
|
import PickaxeIcon from '@/components/PickaxeIcon.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const atmStore = useAtmStore()
|
const atmStore = useAtmStore()
|
||||||
|
|
@ -162,7 +163,7 @@ function formatFiat(cents: number): string {
|
||||||
key="fetchingRate"
|
key="fetchingRate"
|
||||||
class="flex flex-1 flex-col items-center justify-center gap-6"
|
class="flex flex-1 flex-col items-center justify-center gap-6"
|
||||||
>
|
>
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-2xl text-muted-foreground">Fetching exchange rate...</p>
|
<p class="text-2xl text-muted-foreground">Fetching exchange rate...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -269,7 +270,7 @@ function formatFiat(cents: number): string {
|
||||||
key="generatingInvoice"
|
key="generatingInvoice"
|
||||||
class="flex flex-1 flex-col items-center justify-center gap-6"
|
class="flex flex-1 flex-col items-center justify-center gap-6"
|
||||||
>
|
>
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-2xl text-muted-foreground">Creating invoice...</p>
|
<p class="text-2xl text-muted-foreground">Creating invoice...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -296,7 +297,7 @@ function formatFiat(cents: number): string {
|
||||||
|
|
||||||
<!-- Waiting indicator -->
|
<!-- Waiting indicator -->
|
||||||
<div class="flex items-center gap-3 pt-2 lg:pt-4">
|
<div class="flex items-center gap-3 pt-2 lg:pt-4">
|
||||||
<span class="text-2xl animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="32" />
|
||||||
<p class="text-sm lg:text-xl text-muted-foreground">Waiting for payment...</p>
|
<p class="text-sm lg:text-xl text-muted-foreground">Waiting for payment...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -333,7 +334,7 @@ function formatFiat(cents: number): string {
|
||||||
<QRCode :value="context.invoice" :size="380" />
|
<QRCode :value="context.invoice" :size="380" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="flex flex-col items-center gap-4">
|
<div v-else class="flex flex-col items-center gap-4">
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-xl text-muted-foreground">Generating invoice...</p>
|
<p class="text-xl text-muted-foreground">Generating invoice...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -345,7 +346,7 @@ function formatFiat(cents: number): string {
|
||||||
key="dispensingCash"
|
key="dispensingCash"
|
||||||
class="flex flex-1 flex-col items-center justify-center gap-6"
|
class="flex flex-1 flex-col items-center justify-center gap-6"
|
||||||
>
|
>
|
||||||
<span class="text-[8vh] animate-pickaxe">⛏️</span>
|
<PickaxeIcon :size="96" />
|
||||||
<p class="text-2xl text-muted-foreground">Dispensing cash...</p>
|
<p class="text-2xl text-muted-foreground">Dispensing cash...</p>
|
||||||
<p class="text-xl text-muted-foreground">Please wait</p>
|
<p class="text-xl text-muted-foreground">Please wait</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue