feat: doocs

This commit is contained in:
2025-10-09 00:30:31 +02:00
parent 37b1d6dafc
commit aa054f8e27
67 changed files with 2347 additions and 2447 deletions

View File

@@ -0,0 +1,88 @@
<script setup lang="ts">
const { isLoading } = useLoadingIndicator()
const appear = ref(false)
const appeared = ref(false)
onMounted(() => {
setTimeout(() => {
appear.value = true
setTimeout(() => {
appeared.value = true
}, 1000)
}, 0)
})
</script>
<template>
<div
class="absolute w-full -top-px transition-all text-primary shrink-0"
:class="[
isLoading ? 'animate-pulse' : (appear ? '' : 'opacity-0'),
appeared ? 'duration-[400ms]': 'duration-1000'
]"
>
<svg
viewBox="0 0 1440 181"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none"
>
<mask
id="path-1-inside-1_414_5526"
fill="white"
>
<path d="M0 0H1440V181H0V0Z" />
</mask>
<path
d="M0 0H1440V181H0V0Z"
fill="url(#paint0_linear_414_5526)"
fill-opacity="0.22"
/>
<path
d="M0 2H1440V-2H0V2Z"
fill="url(#paint1_linear_414_5526)"
mask="url(#path-1-inside-1_414_5526)"
/>
<defs>
<linearGradient
id="paint0_linear_414_5526"
x1="720"
y1="0"
x2="720"
y2="181"
gradientUnits="userSpaceOnUse"
>
<stop stop-color="currentColor" />
<stop
offset="1"
stop-color="currentColor"
stop-opacity="0"
/>
</linearGradient>
<linearGradient
id="paint1_linear_414_5526"
x1="0"
y1="90.5"
x2="1440"
y2="90.5"
gradientUnits="userSpaceOnUse"
>
<stop
stop-color="currentColor"
stop-opacity="0"
/>
<stop
offset="0.395"
stop-color="currentColor"
/>
<stop
offset="1"
stop-color="currentColor"
stop-opacity="0"
/>
</linearGradient>
</defs>
</svg>
</div>
</template>

View File

@@ -0,0 +1,183 @@
<script setup lang="ts">
interface Star {
x: number
y: number
size: number
}
const props = withDefaults(defineProps<{
starCount?: number
color?: string
speed?: 'slow' | 'normal' | 'fast'
size?: { min: number, max: number }
}>(), {
starCount: 300,
color: 'var(--ui-primary)',
speed: 'normal',
size: () => ({
min: 1,
max: 2
})
})
// Generate random star positions and sizes
const generateStars = (count: number): Star[] => {
return Array.from({ length: count }, () => ({
x: Math.floor(Math.random() * 2000),
y: Math.floor(Math.random() * 2000),
size: typeof props.size === 'number'
? props.size
: Math.random() * (props.size.max - props.size.min) + props.size.min
}))
}
// Define speed configurations once
const speedMap = {
slow: { duration: 200, opacity: 0.5, ratio: 0.3 },
normal: { duration: 150, opacity: 0.75, ratio: 0.3 },
fast: { duration: 100, opacity: 1, ratio: 0.4 }
}
// Use a more efficient approach to generate and store stars
const stars = useState<{ slow: Star[], normal: Star[], fast: Star[] }>('stars', () => {
return {
slow: generateStars(Math.floor(props.starCount * speedMap.slow.ratio)),
normal: generateStars(Math.floor(props.starCount * speedMap.normal.ratio)),
fast: generateStars(Math.floor(props.starCount * speedMap.fast.ratio))
}
})
// Compute star layers with different speeds and opacities
const starLayers = computed(() => [
{ stars: stars.value.fast, ...speedMap.fast },
{ stars: stars.value.normal, ...speedMap.normal },
{ stars: stars.value.slow, ...speedMap.slow }
])
</script>
<template>
<div class="absolute pointer-events-none z-[-1] inset-y-0 inset-x-5 sm:inset-x-7 lg:inset-x-9 overflow-hidden">
<svg
class="absolute inset-0 pointer-events-none"
viewBox="0 0 1017 181"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g opacity="0.5">
<mask
id="path-1-inside-1_846_160841"
fill="white"
>
<path d="M0 0H1017V181H0V0Z" />
</mask>
<path
d="M0 0H1017V181H0V0Z"
fill="url(#paint0_radial_846_160841)"
fill-opacity="0.22"
/>
</g>
<defs>
<radialGradient
id="paint0_radial_846_160841"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(508.999 19.5) rotate(90.177) scale(161.501 509.002)"
>
<stop stop-color="var(--ui-primary)" />
<stop
offset="1"
stop-color="var(--ui-primary)"
stop-opacity="0"
/>
</radialGradient>
<linearGradient
id="paint1_linear_846_160841"
x1="10.9784"
y1="91"
x2="1017"
y2="90.502"
gradientUnits="userSpaceOnUse"
>
<stop
stop-color="var(--ui-primary)"
stop-opacity="0"
/>
<stop
offset="0.395"
stop-color="var(--ui-primary)"
/>
<stop
offset="1"
stop-color="var(--ui-primary)"
stop-opacity="0"
/>
</linearGradient>
</defs>
</svg>
<div class="stars size-full absolute inset-x-0 top-0">
<div
v-for="(layer, index) in starLayers"
:key="index"
class="star-layer"
:style="{
'--star-duration': `${layer.duration}s`,
'--star-opacity': layer.opacity,
'--star-color': color
}"
>
<div
v-for="(star, starIndex) in layer.stars"
:key="starIndex"
class="star absolute rounded-full"
:style="{
left: `${star.x}px`,
top: `${star.y}px`,
width: `${star.size}px`,
height: `${star.size}px`,
backgroundColor: 'var(--star-color)',
opacity: 'var(--star-opacity)'
}"
/>
</div>
</div>
</div>
</template>
<style scoped>
.stars {
left: 50%;
transform: translate(-50%);
-webkit-mask-image: linear-gradient(180deg,
rgba(217, 217, 217, 0) 0%,
rgba(217, 217, 217, 0.8) 25%,
#d9d9d9 50%,
rgba(217, 217, 217, 0.8) 75%,
rgba(217, 217, 217, 0) 100%);
mask-image: linear-gradient(180deg,
rgba(217, 217, 217, 0) 0%,
rgba(217, 217, 217, 0.8) 25%,
#d9d9d9 50%,
rgba(217, 217, 217, 0.8) 75%,
rgba(217, 217, 217, 0) 100%);
-webkit-mask-size: cover;
mask-size: cover;
}
.star-layer {
animation: risingStarsAnimation linear infinite;
animation-duration: var(--star-duration);
will-change: transform;
}
@keyframes risingStarsAnimation {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-2000px);
}
}
</style>