Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 22 additions & 46 deletions docs/.vitepress/theme/Hero.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<script setup lang="ts">
import { Icon } from '@iconify/vue';
import RiveAnimation from '@components/shared/RiveAnimation.vue';
import { useData } from 'vitepress';
import heroAnimation from './assets/animations/640_x_630_vite_to_void_box_vertical_v3.riv';

const props = defineProps<{
background?: string;
}>();
if (typeof document !== 'undefined') {
const preload = document.createElement('link');
preload.rel = 'preload';
preload.href = heroAnimation;
preload.as = 'fetch';
preload.crossOrigin = 'anonymous';
document.head.appendChild(preload);
}
Comment on lines +6 to +13

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The preload link injection runs every time the component is created and will append duplicate <link> elements to document.head if the component remounts (e.g., during route navigation or hot reload). This causes DOM pollution and potential memory leaks.

Fix: Add a check to prevent duplicates or move this to onMounted with cleanup:

onMounted(() => {
  if (!document.querySelector(`link[href="${heroAnimation}"]`)) {
    const preload = document.createElement('link');
    preload.rel = 'preload';
    preload.href = heroAnimation;
    preload.as = 'fetch';
    preload.crossOrigin = 'anonymous';
    document.head.appendChild(preload);
  }
});
Suggested change
if (typeof document !== 'undefined') {
const preload = document.createElement('link');
preload.rel = 'preload';
preload.href = heroAnimation;
preload.as = 'fetch';
preload.crossOrigin = 'anonymous';
document.head.appendChild(preload);
}
onMounted(() => {
if (!document.querySelector(`link[href="${heroAnimation}"]`)) {
const preload = document.createElement('link');
preload.rel = 'preload';
preload.href = heroAnimation;
preload.as = 'fetch';
preload.crossOrigin = 'anonymous';
document.head.appendChild(preload);
}
});

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.


const { frontmatter } = useData();
</script>
Expand Down Expand Up @@ -45,50 +51,20 @@ const { frontmatter } = useData();
</div>
<div class="flex flex-col min-h-[22rem] sm:min-h-[30rem]">
<div
class="flex flex-col bg-cover bg-center"
:style="props.background ? { backgroundImage: `url(${props.background})` } : undefined"
class="relative px-10 pb-10 md:pt-10 h-full flex flex-col justify-center overflow-clip"
role="img"
aria-label="Animation showing a Vite app becoming a Void app"
>
<div
class="relative px-10 pb-10 md:pt-10 h-full flex flex-col justify-center overflow-clip"
>
<slot name="hero-image">
<img
v-if="frontmatter.hero.image?.src"
:src="frontmatter.hero.image.src"
:alt="frontmatter.hero.image.alt"
class="max-h-[20rem]"
/>
</slot>
</div>
<RiveAnimation
:desktop-src="heroAnimation"
:mobile-src="heroAnimation"
:desktop-width="640"
:desktop-height="630"
:mobile-width="640"
:mobile-height="630"
canvas-class="w-full"
/>
</div>
<a
href="https://www.youtube.com/watch?v=Bp86buftbX8"
target="_blank"
class="p-5 flex gap-5 items-center relative group"
>
<div class="relative h-16 aspect-244/144 shrink-0 overflow-hidden">
<img
src="./void-thumb.jpg"
alt="Video thumbnail"
class="h-16 aspect-244/144 group-hover:opacity-75 group-hover:scale-105 transition-[scale,opacity]"
/>
<div class="pointer-events-none absolute inset-0 flex items-center justify-center">
<div
class="flex h-10 w-10 items-center justify-center rounded-full bg-black/55 shadow-[0_6px_24px_rgba(0,0,0,0.35)] transition-transform duration-200 group-hover:scale-110"
>
<Icon icon="simple-icons:youtube" class="h-5 w-5 text-[#ff0033]" />
</div>
</div>
</div>
<div>
<h5 class="text-white">What is Void?</h5>
<p class="text-base">Evan You announces Void</p>
</div>
<span
class="absolute top-5 right-5 text-electric bg-slate rounded px-3 py-1 text-xs font-mono"
>15:33</span
>
</a>
</div>
</div>
</template>
110 changes: 66 additions & 44 deletions docs/.vitepress/theme/Home.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,62 @@
<script setup>
import FeatureGrid from '@components/oss/FeatureGrid.vue';
import Footer from '@components/oss/Footer.vue';
import Spacer from '@components/shared/Spacer.vue';
import { useData } from 'vitepress';
import bg from './hero-bg.jpg';
import Hero from './Hero.vue';
import HomeCli from './HomeCli.vue';
import HomeFeatures from './HomeFeatures.vue';
import HomePlatform from './HomePlatform.vue';

const { frontmatter } = useData();
</script>

<template>
<Hero :background="bg">
<template #hero-image>
<div class="hero-file-tree">
<VoidAppFileTree />
</div>
</template>
</Hero>
<Hero />

<Spacer />

<FeatureGrid />
<HomeCli />

<Spacer />
<Spacer class="bg-primary" />

<div class="platform-surface bg-white text-primary">
<section
class="wrapper border-t border-stroke px-5 sm:px-10 h-70 sm:h-80 flex flex-col justify-center items-center gap-5 text-center"
aria-labelledby="full-stack-heading"
>
<a
href="/guide/self-hosted-platform"
class="section-label-link"
aria-label="Self-host Void Platform guide"
>
<img src="/void-platform-dark.svg" alt="" class="section-label" />
</a>
<h2 id="full-stack-heading" class="text-primary text-2xl md:text-[2.5rem]">
Deploy with your Security Built-In
</h2>
<p class="max-w-md text-pretty text-primary/70">
Self-host your team's Void Platform & customize it to fit your security needs.
</p>
</section>

<HomePlatform />
<Spacer />
</div>

<section
class="wrapper border-t border-nickel px-5 sm:px-10 h-70 sm:h-[22rem] flex flex-col justify-center gap-6 text-center items-center"
aria-labelledby="features-heading"
>
<a href="/guide/" class="section-label-link" aria-label="Void SDK guide">
<img src="/void-sdk.svg" alt="" class="section-label section-label--sdk" />
</a>
<h2 id="features-heading" class="text-white">Turn Vite Apps Full-Stack</h2>
<p class="max-w-md text-white/70 text-balance sm:text-pretty">
Use your favorite Vite framework, add the backend features you need, and infer your resources.
</p>
</section>

<HomeFeatures />

<Footer
:heading="frontmatter.footer_heading"
Expand All @@ -33,50 +67,38 @@ const { frontmatter } = useData();
</template>

<style scoped>
.hero-file-tree {
margin-top: 2rem;
max-width: calc(100vw - 80px);
}

@media (min-width: 768px) {
.hero-file-tree {
margin-top: 0;
max-width: none;
}
.section-label {
height: 0.9rem;
width: auto;
}

@media (min-width: 1024px) {
.hero-file-tree :deep(.file-tree) {
max-height: 362px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.42) rgba(255, 255, 255, 0.08);
}
.section-label--sdk {
width: 6rem;
height: auto;
}

.hero-file-tree :deep(.file-tree),
.hero-file-tree :deep(.adapter-tabs) {
background-color: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(10px);
border-color: rgba(255, 255, 255, 0.1);
.section-label-link {
display: inline-flex;
align-items: center;
justify-content: center;
height: 0.9rem;
line-height: 0;
}

.hero-file-tree :deep(.file-tree::-webkit-scrollbar) {
width: 10px;
.section-label-link:focus-visible {
outline: 2px solid var(--color-electric);
outline-offset: 4px;
}

.hero-file-tree :deep(.file-tree::-webkit-scrollbar-track) {
background: rgba(255, 255, 255, 0.08);
border-radius: 999px;
.platform-surface :deep(.wrapper) {
border-color: var(--color-stroke);
}

.hero-file-tree :deep(.file-tree::-webkit-scrollbar-thumb) {
background: rgba(255, 255, 255, 0.42);
border: 2px solid rgba(0, 0, 0, 0.35);
border-radius: 999px;
.platform-surface :deep(.wrapper--ticks::before) {
border-left-color: var(--color-stroke);
}

.hero-file-tree :deep(.file-tree::-webkit-scrollbar-thumb:hover) {
background: rgba(255, 255, 255, 0.58);
.platform-surface :deep(.wrapper--ticks::after) {
border-right-color: var(--color-stroke);
}
</style>
Loading
Loading