Skip to content

Commit

Permalink
feat: add meteors-component
Browse files Browse the repository at this point in the history
  • Loading branch information
selemondev committed Oct 8, 2024
1 parent 6856519 commit 3ccbc7a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,5 @@ import Demos from './src/components/Demos.vue'
<demo src="./src/example/retroGrid/Demo.vue" />

<demo src="./src/example/orbitingCircles/Demo.vue" />

<demo src="./src/example/meteors/Demo.vue" />
41 changes: 41 additions & 0 deletions docs/src/components/spark-ui/meteors/Meteors.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang='ts'>
import { ref, watch } from 'vue'
import { cn } from '../../../lib/utils'
interface MeteorsProps {
number?: number
}
const props = withDefaults(defineProps<MeteorsProps>(), {
number: 20,
})
const meteorStyles = ref()
watch(() => props.number, (val) => {
const styles = [...Array.of(val)].map(() => ({
top: -5,
left: `${Math.floor(Math.random() * window.innerWidth)}px`,
animationDelay: `${Math.random() * 1 + 0.2}s`,
animationDuration: `${Math.floor(Math.random() * 8 + 2)}s`,
}))
meteorStyles.value = styles
}, {
deep: true,
immediate: true,
})
</script>

<template>
<div v-for="(style, idx) in meteorStyles" :key="idx" class="absolute">
<span
:key="idx" :class="cn(
'pointer-events-none absolute left-1/2 top-1/2 size-0.5 rotate-[215deg] animate-meteor rounded-full bg-slate-500 shadow-[0_0_0_1px_#ffffff10]',
)" :style="style"
>
<div
class="pointer-events-none absolute top-1/2 -z-10 h-px w-[50px] -translate-y-1/2 bg-gradient-to-r from-slate-500 to-transparent"
/>
</span>
</div>
</template>
44 changes: 44 additions & 0 deletions docs/src/components/spark-ui/orbitingCircles/OrbitingCircles.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<script setup lang='ts'>
import { cn } from '../../../lib/utils'
interface OrbitingCirclesProps {
className?: string
reverse?: boolean
duration?: number
delay?: number
radius?: number
path?: boolean
};
const props = withDefaults(defineProps<OrbitingCirclesProps>(), {
duration: 20,
delay: 10,
radius: 50,
path: true,
})
const className = cn(
'absolute flex size-full animate-reverse transform-gpu animate-orbit items-center justify-center rounded-full border bg-none [animation-delay:calc(var(--delay)*1000ms)]',
props.className,
{ '[animate-direaction:reverse]': props.reverse },
)
</script>

<template>
<div v-if="props.path">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="pointer-events-none absolute inset-0 size-full">
<circle class="stroke-black/10 stroke-1 dark:stroke-white/10" cx="50%" cy="50%" :r="radius" fill="none" />
</svg>
</div>

<div
:style="{
'--duration': props.duration,
'--radius': props.radius,
'--delay': -props.delay,
}"
:class="className"
>
<slot />
</div>
</template>
19 changes: 19 additions & 0 deletions docs/src/example/meteors/Demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script setup lang='ts'>
import Meteors from './Meteors.vue'
</script>

<template>
<div
class="relative flex h-[450px] w-[500px] flex-col items-center justify-center overflow-hidden rounded-lg"
border
>
<div class="absolute top-10 inset-x-0">
<Meteors :number="30" />
</div>
<span
class="pointer-events-none whitespace-pre-wrap bg-gradient-to-b from-black to-gray-300/80 bg-clip-text text-center text-8xl font-semibold leading-none text-transparent"
>
Meteors
</span>
</div>
</template>
62 changes: 62 additions & 0 deletions docs/src/example/meteors/Meteors.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang='ts'>
import { ref, watch } from 'vue'
import { cn } from '../../lib/utils'
interface MeteorsProps {
number?: number
}
const props = withDefaults(defineProps<MeteorsProps>(), {
number: 20,
})
const meteorStyles = ref()
watch(() => props.number, (val) => {
const styles = [...Array.of(val)].map(() => ({
top: -5,
left: `${Math.floor(Math.random() * window.innerWidth)}px`,
animationDelay: `${Math.random() * 1 + 0.2}s`,
animationDuration: `${Math.floor(Math.random() * 8 + 2)}s`,
}))
meteorStyles.value = styles
}, {
deep: true,
immediate: true,
})
</script>

<template>
<div v-for="(style, idx) in meteorStyles" :key="idx" class="absolute">
<span
:key="idx" :class="cn(
'pointer-events-none absolute left-1/2 top-1/2 size-0.5 rotate-[215deg] animate-meteor rounded-full bg-slate-500 shadow-[0_0_0_1px_#ffffff10]',
)" :style="style"
>
<div
class="pointer-events-none absolute top-1/2 -z-10 h-px w-[50px] -translate-y-1/2 bg-gradient-to-r from-slate-500 to-transparent"
/>
</span>
</div>
</template>

<style scoped>
@keyframes Meteor {
0% {
transform: rotate(215deg) translateX(0);
opacity: 1;
}
70% {
opacity: 1;
}
100% {
transform: rotate(215deg) translateX(-500px);
opacity: 0;
}
}
.animate-meteor {
animation: Meteor 5s linear infinite;
}
</style>

0 comments on commit 3ccbc7a

Please sign in to comment.