102 lines
3.1 KiB
Vue
102 lines
3.1 KiB
Vue
<template>
|
|
<div class="absolute inset-0 overflow-hidden pointer-events-none" :class="variant">
|
|
<!-- Animated gradient orbs -->
|
|
<div
|
|
v-for="(orb, index) in orbs"
|
|
:key="index"
|
|
class="absolute rounded-full blur-3xl animate-float"
|
|
:class="orb.color"
|
|
:style="{
|
|
width: orb.size,
|
|
height: orb.size,
|
|
top: orb.top,
|
|
left: orb.left,
|
|
right: orb.right,
|
|
bottom: orb.bottom,
|
|
animationDelay: `${index * 2}s`,
|
|
animationDuration: `${6 + index * 2}s`
|
|
}"
|
|
/>
|
|
|
|
<!-- Grid pattern -->
|
|
<div v-if="showGrid" class="absolute inset-0 dots-pattern opacity-20" />
|
|
|
|
<!-- Animated lines (for tech feel) -->
|
|
<svg v-if="showLines" class="absolute inset-0 w-full h-full opacity-10" xmlns="http://www.w3.org/2000/svg">
|
|
<defs>
|
|
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
<stop offset="0%" class="[stop-color:var(--color-primary-500)]" stop-opacity="0" />
|
|
<stop offset="50%" class="[stop-color:var(--color-primary-500)]" stop-opacity="1" />
|
|
<stop offset="100%" class="[stop-color:var(--color-primary-500)]" stop-opacity="0" />
|
|
</linearGradient>
|
|
</defs>
|
|
|
|
<!-- Horizontal animated lines -->
|
|
<g v-for="i in 3" :key="`h-${i}`">
|
|
<line
|
|
x1="0"
|
|
:y1="`${20 + i * 25}%`"
|
|
x2="100%"
|
|
:y2="`${20 + i * 25}%`"
|
|
stroke="url(#lineGradient)"
|
|
stroke-width="1"
|
|
class="animate-pulse-soft"
|
|
:style="{ animationDelay: `${i * 0.5}s` }"
|
|
/>
|
|
</g>
|
|
</svg>
|
|
|
|
<!-- Floating particles -->
|
|
<div v-if="showParticles" class="absolute inset-0">
|
|
<div
|
|
v-for="i in 12"
|
|
:key="`particle-${i}`"
|
|
class="absolute w-1 h-1 rounded-full bg-primary-400/30 animate-float"
|
|
:style="{
|
|
top: `${Math.random() * 100}%`,
|
|
left: `${Math.random() * 100}%`,
|
|
animationDelay: `${Math.random() * 5}s`,
|
|
animationDuration: `${4 + Math.random() * 4}s`
|
|
}"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
interface Props {
|
|
variant?: 'hero' | 'section' | 'cta'
|
|
showGrid?: boolean
|
|
showLines?: boolean
|
|
showParticles?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
variant: 'section',
|
|
showGrid: true,
|
|
showLines: false,
|
|
showParticles: false
|
|
})
|
|
|
|
const orbs = computed(() => {
|
|
switch (props.variant) {
|
|
case 'hero':
|
|
return [
|
|
{ size: '400px', top: '-100px', left: '-100px', color: 'bg-primary-500/20' },
|
|
{ size: '300px', top: '200px', right: '-50px', color: 'bg-success-500/15' },
|
|
{ size: '250px', bottom: '-50px', left: '30%', color: 'bg-primary-400/15' }
|
|
]
|
|
case 'cta':
|
|
return [
|
|
{ size: '300px', top: '-50px', right: '-100px', color: 'bg-white/10' },
|
|
{ size: '200px', bottom: '-50px', left: '-50px', color: 'bg-white/5' }
|
|
]
|
|
default:
|
|
return [
|
|
{ size: '200px', top: '10%', left: '-50px', color: 'bg-primary-500/10' },
|
|
{ size: '150px', bottom: '20%', right: '-30px', color: 'bg-success-500/10' }
|
|
]
|
|
}
|
|
})
|
|
</script>
|