Skip to content

Commit 7eff5ac

Browse files
authored
docs: update home page for responsive menu, forces light mode, and change buttons to direct to docs (#513)
1 parent a21216e commit 7eff5ac

5 files changed

Lines changed: 289 additions & 33 deletions

File tree

docs/.vitepress/config.mts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -749,18 +749,7 @@ export default extendConfig(
749749
],
750750
];
751751

752-
// return [...ogInfo, canonicalUrlEntry];
753-
const headExtras: HeadConfig[] = [...ogInfo, canonicalUrlEntry];
754-
755-
if (pageData.frontmatter?.layout === 'home') {
756-
headExtras.unshift([
757-
'script',
758-
{},
759-
"document.documentElement.setAttribute('data-theme', 'light')",
760-
]);
761-
}
762-
763-
return headExtras;
752+
return [...ogInfo, canonicalUrlEntry];
764753
},
765754
}),
766755
);

docs/.vitepress/theme/Layout.vue

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { onMounted, watch } from 'vue';
23
import { useData } from 'vitepress';
34
import BaseTheme from '@voidzero-dev/vitepress-theme/src/viteplus';
45
import Header from './components/Header.vue';
@@ -8,6 +9,25 @@ import Home from './layouts/Home.vue';
89
910
const { frontmatter } = useData();
1011
const { Layout: BaseLayout } = BaseTheme;
12+
13+
const ensureHomeLight = () => {
14+
if (frontmatter.value?.layout !== 'home' || typeof document === 'undefined') {
15+
return;
16+
}
17+
18+
document.documentElement.classList.remove('dark');
19+
};
20+
21+
onMounted(() => {
22+
ensureHomeLight();
23+
});
24+
25+
watch(
26+
() => frontmatter.value?.layout,
27+
() => {
28+
ensureHomeLight();
29+
},
30+
);
1131
</script>
1232

1333
<template>

docs/.vitepress/theme/components/Footer.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88
Take your team's productivity to the next level with Vite+
99
</h2>
1010
<div class="flex items-center gap-5">
11-
<a
12-
href="https://tally.so/r/nGWebL"
11+
<a href="/vite/guide" target="_self" class="button button--white">Get started</a>
12+
<!-- <a
13+
href="https://voidzero.dev/posts/announcing-vite-plus?utm_source=viteplusdev&utm_content=bottom_learn_more"
1314
target="_blank"
1415
rel="noopener noreferrer"
1516
class="button button--white"
16-
>Register your interest</a
1717
>
18-
<a href="./vite/guide" rel="noopener noreferrer" class="button button--white">
1918
Learn more
20-
</a>
19+
</a> -->
2120
</div>
2221
</div>
2322
<div

docs/.vitepress/theme/components/Header.vue

Lines changed: 257 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,68 @@
11
<script setup lang="ts">
2-
import { useData, useRoute } from 'vitepress';
2+
import { ref, onMounted, onUnmounted } from 'vue';
33
44
const nav = [{ text: 'Docs', link: '/vite/guide' }];
5+
6+
// Mobile menu state
7+
const mobileMenuOpen = ref(false);
8+
const expandedMobileItem = ref<string | null>(null);
9+
10+
// Body scroll lock for mobile menu
11+
const lockBodyScroll = () => {
12+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
13+
document.body.style.overflow = 'hidden';
14+
document.body.style.position = 'fixed';
15+
document.body.style.width = '100%';
16+
document.body.style.top = '0';
17+
if (scrollbarWidth > 0) {
18+
document.body.style.paddingRight = `${scrollbarWidth}px`;
19+
}
20+
};
21+
22+
const unlockBodyScroll = () => {
23+
document.body.style.overflow = '';
24+
document.body.style.position = '';
25+
document.body.style.width = '';
26+
document.body.style.top = '';
27+
document.body.style.paddingRight = '';
28+
};
29+
30+
// Close mobile menu
31+
const closeMobileMenu = () => {
32+
mobileMenuOpen.value = false;
33+
expandedMobileItem.value = null;
34+
unlockBodyScroll();
35+
};
36+
37+
// Handle keyboard navigation
38+
const handleKeydown = (e: KeyboardEvent) => {
39+
if (e.key === 'Escape') {
40+
if (mobileMenuOpen.value) {
41+
closeMobileMenu();
42+
}
43+
}
44+
};
45+
46+
// Toggle mobile menu
47+
const toggleMobileMenu = () => {
48+
mobileMenuOpen.value = !mobileMenuOpen.value;
49+
if (mobileMenuOpen.value) {
50+
lockBodyScroll();
51+
expandedMobileItem.value = null;
52+
} else {
53+
unlockBodyScroll();
54+
expandedMobileItem.value = null;
55+
}
56+
};
57+
58+
onMounted(() => {
59+
document.addEventListener('keydown', handleKeydown);
60+
});
61+
62+
onUnmounted(() => {
63+
document.removeEventListener('keydown', handleKeydown);
64+
unlockBodyScroll();
65+
});
566
</script>
667

768
<template>
@@ -53,16 +114,203 @@ const nav = [{ text: 'Docs', link: '/vite/guide' }];
53114
<img class="h-3" src="@assets/logos/voidzero-dark.svg" alt="VoidZero" />
54115
</a>
55116
</span>
56-
<a
57-
href="https://tally.so/r/nGWebL"
58-
target="_blank"
59-
rel="noopener noreferrer"
60-
class="button hidden sm:block"
117+
<a href="/vite/guide" target="_self" class="button hidden md:block"> Get started </a>
118+
119+
<!-- Mobile hamburger/close button - Right aligned -->
120+
<button
121+
@click="toggleMobileMenu"
122+
:aria-expanded="mobileMenuOpen"
123+
aria-controls="mobile-menu"
124+
aria-label="Toggle navigation menu"
125+
class="md:hidden p-2 -mr-2 text-primary dark:text-white hover:opacity-70 transition-opacity cursor-pointer"
126+
type="button"
61127
>
62-
Join early access
63-
</a>
128+
<svg
129+
v-if="!mobileMenuOpen"
130+
class="size-6 block dark:hidden"
131+
viewBox="0 0 18 8"
132+
xmlns="http://www.w3.org/2000/svg"
133+
>
134+
<path d="M0 0.75H18" stroke="#08060D" stroke-width="1.5" />
135+
<path d="M0 6.75H18" stroke="#08060D" stroke-width="1.5" />
136+
</svg>
137+
<svg
138+
v-if="!mobileMenuOpen"
139+
class="size-6 hidden dark:block"
140+
viewBox="0 0 18 8"
141+
xmlns="http://www.w3.org/2000/svg"
142+
>
143+
<path d="M0 0.75H18" stroke="#FFFFFF" stroke-width="1.5" />
144+
<path d="M0 6.75H18" stroke="#FFFFFF" stroke-width="1.5" />
145+
</svg>
146+
</button>
64147
</div>
65148
</header>
149+
150+
<!-- Mobile Menu Overlay - Full Screen -->
151+
<div
152+
v-if="mobileMenuOpen"
153+
id="mobile-menu"
154+
role="dialog"
155+
aria-modal="true"
156+
aria-label="Mobile navigation menu"
157+
data-theme="dark"
158+
class="md:hidden fixed inset-0 z-[1001] bg-primary"
159+
>
160+
<section class="wrapper animate-fade-in">
161+
<!-- Internal Header with Logo and Close Button -->
162+
<div class="w-full pl-5 pr-7 py-5 lg:py-7 flex items-center justify-between">
163+
<a href="/">
164+
<img class="h-4" src="@assets/logos/viteplus-light.svg" alt="Vite+" />
165+
</a>
166+
<button
167+
@click="closeMobileMenu"
168+
aria-label="Close navigation menu"
169+
class="p-2 -mr-2 text-white hover:opacity-70 transition-opacity"
170+
type="button"
171+
>
172+
<svg
173+
class="size-6 cursor-pointer"
174+
xmlns="http://www.w3.org/2000/svg"
175+
fill="none"
176+
viewBox="0 0 24 24"
177+
stroke="currentColor"
178+
aria-hidden="true"
179+
>
180+
<path
181+
stroke-linecap="round"
182+
stroke-linejoin="round"
183+
stroke-width="2"
184+
d="M6 18L18 6M6 6l12 12"
185+
/>
186+
</svg>
187+
</button>
188+
</div>
189+
190+
<!-- Scrollable content container -->
191+
<div
192+
class="overflow-y-auto flex flex-col [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden"
193+
style="height: calc(100vh - 88px)"
194+
>
195+
<!-- Navigation Items - Top Section -->
196+
<nav class="flex-1 w-full pt-6 pb-8">
197+
<ul class="space-y-1">
198+
<li v-for="navItem in nav" :key="navItem.link">
199+
<!-- :class="{ 'bg-white/10': route.path === navItem.link }" -->
200+
<a
201+
:href="navItem.link"
202+
@click="closeMobileMenu"
203+
:target="navItem.link?.startsWith('http') ? '_blank' : '_self'"
204+
:rel="navItem.link?.startsWith('http') ? 'noopener noreferrer' : undefined"
205+
class="flex py-3 px-4 text-lg font-sans text-white items-center justify-between"
206+
>
207+
{{ navItem.text }}
208+
<svg
209+
v-if="navItem.link?.startsWith('http')"
210+
class="inline-block ml-1 size-4"
211+
xmlns="http://www.w3.org/2000/svg"
212+
viewBox="0 0 12 12"
213+
fill="none"
214+
aria-hidden="true"
215+
>
216+
<path
217+
d="M2.81802 2.81803L9.18198 2.81803L9.18198 9.18199"
218+
class="stroke-primary dark:stroke-white"
219+
stroke-width="1.5"
220+
/>
221+
<path
222+
d="M9.18213 2.81802L2.81817 9.18198"
223+
class="stroke-primary dark:stroke-white"
224+
stroke-width="1.5"
225+
/>
226+
</svg>
227+
</a>
228+
</li>
229+
</ul>
230+
</nav>
231+
232+
<!-- Bottom Section - CTA and Social -->
233+
<div class="w-full py-12 border-t border-nickel relative tick-left tick-right mt-auto">
234+
<div class="space-y-12">
235+
<!-- CTA Button -->
236+
<div class="px-6">
237+
<a
238+
href="/vite/guide"
239+
target="_self"
240+
class="button button--primary button--white block text-center bg-white text-primary hover:bg-white/90"
241+
@click="closeMobileMenu"
242+
>
243+
<span>Get started</span>
244+
</a>
245+
</div>
246+
247+
<!-- Divider -->
248+
<div class="border-t border-nickel tick-left tick-right relative"></div>
249+
250+
<!-- Social Icons -->
251+
<div class="flex items-center justify-center gap-4 pb-12">
252+
<a
253+
href="https://github.com/voidzero-dev"
254+
target="_blank"
255+
rel="noopener noreferrer"
256+
class="hover:opacity-70 transition-opacity"
257+
@click="closeMobileMenu"
258+
>
259+
<img src="@assets/social/github-light.svg" alt="GitHub" class="size-6" />
260+
</a>
261+
<a
262+
href="https://bsky.app/profile/voidzero.dev"
263+
target="_blank"
264+
rel="noopener noreferrer"
265+
class="hover:opacity-70 transition-opacity"
266+
@click="closeMobileMenu"
267+
>
268+
<img src="@assets/social/bluesky-light.svg" alt="Bluesky" class="size-6" />
269+
</a>
270+
<a
271+
href="https://x.com/voidzerodev"
272+
target="_blank"
273+
rel="noopener noreferrer"
274+
class="hover:opacity-70 transition-opacity"
275+
@click="closeMobileMenu"
276+
>
277+
<img src="@assets/social/twitter-light.svg" alt="X" class="size-6" />
278+
</a>
279+
</div>
280+
</div>
281+
</div>
282+
</div>
283+
</section>
284+
</div>
66285
</template>
67286

68-
<style scoped></style>
287+
<style scoped>
288+
@keyframes shadowFadeIn {
289+
from {
290+
box-shadow:
291+
rgba(50, 50, 93, 0.1) 0px 25px 50px -20px,
292+
rgba(0, 0, 0, 0.15) 0px 15px 30px -30px;
293+
}
294+
295+
to {
296+
box-shadow:
297+
rgba(50, 50, 93, 0.25) 0px 50px 100px -20px,
298+
rgba(0, 0, 0, 0.3) 0px 30px 60px -30px;
299+
}
300+
}
301+
302+
@keyframes fadeIn {
303+
from {
304+
opacity: 0;
305+
}
306+
307+
to {
308+
opacity: 1;
309+
}
310+
}
311+
312+
.animate-fade-in {
313+
animation: fadeIn 300ms ease-out 100ms forwards;
314+
opacity: 0;
315+
}
316+
</style>

docs/.vitepress/theme/components/home/Hero.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
</p>
1414
</div>
1515
<div class="flex items-center gap-5">
16-
<a
17-
href="https://tally.so/r/nGWebL"
16+
<a href="/vite/guide" target="_self" class="button button--primary"> Get started </a>
17+
<!--<a href="#intro" @click="smoothScrollTo($event, 'intro')" class="button">-->
18+
<!-- <a
19+
href="https://voidzero.dev/posts/announcing-vite-plus?utm_source=viteplusdev&utm_content=top_learn_more"
1820
target="_blank"
1921
rel="noopener noreferrer"
20-
class="button button--primary"
22+
class="button"
2123
>
22-
Join early access
23-
</a>
24-
<!--<a href="#intro" @click="smoothScrollTo($event, 'intro')" class="button">-->
25-
<a href="./vite/guide" rel="noopener noreferrer" class="button"> Learn more </a>
24+
Learn more
25+
</a> -->
2626
</div>
2727
</div>
2828
</div>

0 commit comments

Comments
 (0)