Merge pull request 'Navigation Dropdown' (#31) from nav-dropdown into main
Reviewed-on: Webmaster/dev-ieeeucsd-org#31 Reviewed-by: Shing Hung <shing.hung@ieeeucsd.org>
This commit is contained in:
commit
fe79dd6c9c
2 changed files with 418 additions and 155 deletions
|
@ -5,150 +5,399 @@ import pages from "../../data/pages.json";
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div
|
|
||||||
class="flex justify-between items-center bg-ieee-black my-[1%] mx-[2.5%] py-[0.5%] px-[1%] rounded-full md:border-[0.1vw]"
|
|
||||||
>
|
|
||||||
<a href="/" class="hover:opacity-60 duration-300">
|
|
||||||
<Image
|
|
||||||
class="w-[15vw] md:block hidden"
|
|
||||||
src={whiteLogoHorizontal}
|
|
||||||
alt="IEEE UCSD Logo"
|
|
||||||
/>
|
|
||||||
<Image
|
|
||||||
class="w-[40vw] md:hidden block"
|
|
||||||
src={whiteLogoHorizontal}
|
|
||||||
alt="IEEE UCSD Logo"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<!-- Desktop Navigation -->
|
|
||||||
<div class="hidden md:flex md:w-[55%] md:justify-between">
|
|
||||||
{
|
|
||||||
pages.map((page) => (
|
|
||||||
<a
|
|
||||||
href={page.path}
|
|
||||||
class={`uppercase rounded-full duration-300 px-[1.5vw] py-[0.2vw] text-[1.2vw] text-nowrap
|
|
||||||
${
|
|
||||||
page.name === "Online Store"
|
|
||||||
? "bg-ieee-yellow text-black hover:opacity-70"
|
|
||||||
: "text-white border-white hover:opacity-50 border-[0.1vw] font-light"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{page.name}
|
|
||||||
</a>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile Hamburger/Close Button -->
|
|
||||||
<button
|
|
||||||
id="menu-btn"
|
|
||||||
class="md:hidden text-white p-2 flex justify-center items-center focus:outline-none relative z-[60] scale-150"
|
|
||||||
aria-label="Toggle menu"
|
|
||||||
>
|
|
||||||
<!-- Hamburger Icon -->
|
|
||||||
<svg
|
|
||||||
class="w-6 h-6 menu-icon"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M4 6h16M4 12h16M4 18h16"></path>
|
|
||||||
</svg>
|
|
||||||
<!-- Close Icon -->
|
|
||||||
<svg
|
|
||||||
class="w-6 h-6 close-icon hidden"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M6 18L18 6M6 6l12 12"></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Mobile Menu -->
|
|
||||||
<div
|
|
||||||
id="mobile-menu"
|
|
||||||
class="fixed inset-0 z-[51] hidden xl:hidden motion-safe:transition-transform motion-safe:duration-300 translate-x-full"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex flex-col items-center min-h-screen justify-center bg-black py-20 px-4 space-y-8"
|
class="flex justify-between items-center bg-ieee-black my-[1%] mx-[2.5%] py-[0.5%] px-[1%] rounded-full md:border-[0.1vw]"
|
||||||
>
|
>
|
||||||
{
|
<a href="/" class="hover:opacity-60 duration-300">
|
||||||
pages.map((page) => (
|
<Image
|
||||||
<a
|
class="w-[15vw] md:block hidden"
|
||||||
href={page.path}
|
src={whiteLogoHorizontal}
|
||||||
class={`block py-4 px-12 text-center rounded-[3rem] motion-safe:transition-colors motion-safe:duration-200 uppercase font-bold text-2xl w-full max-w-md
|
alt="IEEE UCSD Logo"
|
||||||
${
|
/>
|
||||||
page.name === "Online Store"
|
<Image
|
||||||
? "bg-[#f3c135] text-black border-[#f3c135] hover:bg-[#dba923] hover:border-[#dba923]"
|
class="w-[40vw] md:hidden block"
|
||||||
: "text-white hover:text-gray-300 border-white border-2"
|
src={whiteLogoHorizontal}
|
||||||
}`}
|
alt="IEEE UCSD Logo"
|
||||||
>
|
/>
|
||||||
{page.name}
|
</a>
|
||||||
</a>
|
|
||||||
))
|
<!-- Desktop Navigation -->
|
||||||
}
|
<div class="hidden md:flex md:w-[55%] md:justify-between">
|
||||||
|
{
|
||||||
|
pages.map((page) =>
|
||||||
|
page.subpages ? (
|
||||||
|
<div class="relative group">
|
||||||
|
<a
|
||||||
|
href={page.path}
|
||||||
|
class="uppercase rounded-full duration-300 px-[1.5vw] py-[0.2vw] text-[1.2vw] text-nowrap text-white border-white hover:opacity-50 border-[0.1vw] font-light inline-block"
|
||||||
|
>
|
||||||
|
{page.name}
|
||||||
|
</a>
|
||||||
|
<div class="absolute left-1/2 transform -translate-x-1/2 top-full pt-2 w-64 z-50">
|
||||||
|
<div class="rounded-lg bg-ieee-black border border-white shadow-lg hidden group-hover:block animate-fade-down animate-duration-200 animate-ease-in-out">
|
||||||
|
{page.subpages.map((subpage) => (
|
||||||
|
<a
|
||||||
|
href={subpage.path}
|
||||||
|
class="block px-6 py-3 text-white hover:bg-gray-700 text-[1vw] first:rounded-t-lg last:rounded-b-lg text-center whitespace-nowrap transition-colors duration-200"
|
||||||
|
>
|
||||||
|
{subpage.name}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<a
|
||||||
|
href={page.path}
|
||||||
|
class={`uppercase rounded-full duration-300 px-[1.5vw] py-[0.2vw] text-[1.2vw] text-nowrap
|
||||||
|
${
|
||||||
|
page.name === "Online Store"
|
||||||
|
? "bg-ieee-yellow text-black hover:opacity-70"
|
||||||
|
: "text-white border-white hover:opacity-50 border-[0.1vw] font-light"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{page.name}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile Hamburger/Close Button -->
|
||||||
|
<button
|
||||||
|
id="menu-btn"
|
||||||
|
class="md:hidden text-white p-2 flex justify-center items-center focus:outline-none relative z-[60] scale-150"
|
||||||
|
aria-label="Toggle menu"
|
||||||
|
>
|
||||||
|
<!-- Hamburger Icon -->
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6 menu-icon"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M4 6h16M4 12h16M4 18h16"></path>
|
||||||
|
</svg>
|
||||||
|
<!-- Close Icon -->
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6 close-icon hidden"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M6 18L18 6M6 6l12 12"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mobile Menu -->
|
||||||
|
<div
|
||||||
|
id="mobile-menu"
|
||||||
|
class="fixed inset-0 z-[51] hidden xl:hidden motion-safe:transition-transform motion-safe:duration-300 translate-x-full bg-black"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex flex-col items-center min-h-screen w-full justify-center py-20 px-4 space-y-6 overflow-y-auto"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
pages.map((page) =>
|
||||||
|
page.subpages ? (
|
||||||
|
<div class="w-full max-w-md space-y-4 relative dropdown-container">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<a
|
||||||
|
href={page.path}
|
||||||
|
class="flex-1 block py-4 px-12 text-center rounded-[3rem] motion-safe:transition-colors motion-safe:duration-200 uppercase font-bold text-2xl text-white hover:text-gray-300 border-white border-2"
|
||||||
|
>
|
||||||
|
{page.name}
|
||||||
|
</a>
|
||||||
|
<button
|
||||||
|
class="mobile-dropdown-toggle py-4 px-6 text-center rounded-[3rem] motion-safe:transition-all motion-safe:duration-200 uppercase font-bold text-2xl text-white hover:text-gray-300 border-white border-2 flex items-center justify-center"
|
||||||
|
aria-expanded="false"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="w-6 h-6 transform transition-transform duration-200 dropdown-icon"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M19 9l-7 7-7-7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-dropdown-content mt-2 space-y-2 pl-4 absolute w-full animate-duration-200 animate-ease-in-out">
|
||||||
|
{page.subpages.map((subpage) => (
|
||||||
|
<a
|
||||||
|
href={subpage.path}
|
||||||
|
class="block py-3 px-8 text-center rounded-[2rem] motion-safe:transition-all motion-safe:duration-200 uppercase font-medium text-lg w-full text-white hover:text-gray-300 border-white border bg-[#111111] hover:bg-[#222222]"
|
||||||
|
>
|
||||||
|
{subpage.name}
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<a
|
||||||
|
href={page.path}
|
||||||
|
class={`block py-4 px-12 text-center rounded-[3rem] motion-safe:transition-colors motion-safe:duration-200 uppercase font-bold text-2xl w-full max-w-md
|
||||||
|
${
|
||||||
|
page.name === "Online Store"
|
||||||
|
? "bg-[#f3c135] text-black border-[#f3c135] hover:bg-[#dba923] hover:border-[#dba923]"
|
||||||
|
: "text-white hover:text-gray-300 border-white border-2"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{page.name}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#mobile-menu.show {
|
#mobile-menu.show {
|
||||||
@apply translate-x-0;
|
@apply translate-x-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-dropdown-content {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 30;
|
||||||
|
width: calc(100% - 1rem) !important;
|
||||||
|
animation: fadeOut 0.2s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-dropdown-content.show {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
backdrop-filter: none;
|
||||||
|
animation: fadeIn 0.2s ease-in-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeOut {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-dropdown-content a {
|
||||||
|
margin-inline: auto;
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: calc(100% - 1rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-icon.rotated {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add styles for focus effect */
|
||||||
|
.dropdown-container {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container.active {
|
||||||
|
transform: scale(1.02);
|
||||||
|
z-index: 25;
|
||||||
|
backdrop-filter: none;
|
||||||
|
filter: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container.active .mobile-dropdown-toggle,
|
||||||
|
.dropdown-container.active > div > a {
|
||||||
|
position: relative;
|
||||||
|
z-index: 25;
|
||||||
|
pointer-events: all;
|
||||||
|
backdrop-filter: none;
|
||||||
|
filter: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-container.active::after {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
z-index: 15;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-menu.has-active-dropdown > div > *:not(.dropdown-container.active) {
|
||||||
|
opacity: 0.2;
|
||||||
|
transform: scale(0.98);
|
||||||
|
filter: blur(2px);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-menu.has-active-dropdown .dropdown-container.active {
|
||||||
|
pointer-events: all;
|
||||||
|
filter: none;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mobile-menu.has-active-dropdown
|
||||||
|
.dropdown-container.active
|
||||||
|
.mobile-dropdown-content.show {
|
||||||
|
filter: none;
|
||||||
|
backdrop-filter: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const menuBtn = document.getElementById("menu-btn");
|
const menuBtn = document.getElementById("menu-btn");
|
||||||
const mobileMenu = document.getElementById("mobile-menu");
|
const mobileMenu = document.getElementById("mobile-menu");
|
||||||
const menuIcon = document.querySelector(".menu-icon");
|
const menuIcon = document.querySelector(".menu-icon");
|
||||||
const closeIcon = document.querySelector(".close-icon");
|
const closeIcon = document.querySelector(".close-icon");
|
||||||
|
const dropdownToggles = document.querySelectorAll(
|
||||||
|
".mobile-dropdown-toggle"
|
||||||
|
);
|
||||||
|
|
||||||
function toggleMenu(show: boolean) {
|
function toggleMenu(show: boolean) {
|
||||||
if (show) {
|
if (show) {
|
||||||
mobileMenu?.classList.remove("hidden");
|
mobileMenu?.classList.remove("hidden");
|
||||||
menuIcon?.classList.add("hidden");
|
menuIcon?.classList.add("hidden");
|
||||||
closeIcon?.classList.remove("hidden");
|
closeIcon?.classList.remove("hidden");
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
mobileMenu?.classList.add("show");
|
mobileMenu?.classList.add("show");
|
||||||
}, 10);
|
}, 10);
|
||||||
} else {
|
} else {
|
||||||
mobileMenu?.classList.remove("show");
|
mobileMenu?.classList.remove("show");
|
||||||
menuIcon?.classList.remove("hidden");
|
menuIcon?.classList.remove("hidden");
|
||||||
closeIcon?.classList.add("hidden");
|
closeIcon?.classList.add("hidden");
|
||||||
document.body.style.overflow = "";
|
document.body.style.overflow = "";
|
||||||
|
|
||||||
setTimeout(() => {
|
// First wait for the navbar to slide out
|
||||||
mobileMenu?.classList.add("hidden");
|
setTimeout(() => {
|
||||||
}, 100);
|
mobileMenu?.classList.add("hidden");
|
||||||
|
|
||||||
|
// Then reset all dropdowns and focus states
|
||||||
|
document
|
||||||
|
.querySelectorAll(".dropdown-container")
|
||||||
|
.forEach((el) => {
|
||||||
|
const dropdownContent = el.querySelector(
|
||||||
|
".mobile-dropdown-content"
|
||||||
|
);
|
||||||
|
const dropdownToggle = el.querySelector(
|
||||||
|
".mobile-dropdown-toggle"
|
||||||
|
);
|
||||||
|
const dropdownIcon =
|
||||||
|
dropdownToggle?.querySelector(".dropdown-icon");
|
||||||
|
|
||||||
|
el.classList.remove("active");
|
||||||
|
dropdownContent?.classList.remove("show");
|
||||||
|
dropdownIcon?.classList.remove("rotated");
|
||||||
|
dropdownToggle?.setAttribute("aria-expanded", "false");
|
||||||
|
});
|
||||||
|
mobileMenu?.classList.remove("has-active-dropdown");
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
menuBtn?.addEventListener("click", () => {
|
menuBtn?.addEventListener("click", () => {
|
||||||
const isMenuHidden = mobileMenu?.classList.contains("hidden") ?? true;
|
const isMenuHidden = mobileMenu?.classList.contains("hidden") ?? true;
|
||||||
toggleMenu(isMenuHidden);
|
toggleMenu(isMenuHidden);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close menu when clicking outside
|
// Handle dropdown toggles
|
||||||
document.addEventListener("click", (e) => {
|
dropdownToggles.forEach((toggle) => {
|
||||||
if (
|
toggle.addEventListener("click", (e) => {
|
||||||
!mobileMenu?.contains(e.target as Node) &&
|
e.stopPropagation();
|
||||||
!menuBtn?.contains(e.target as Node) &&
|
const container = toggle.closest(".dropdown-container");
|
||||||
!mobileMenu?.classList.contains("hidden")
|
const content = toggle.parentElement
|
||||||
) {
|
?.nextElementSibling as HTMLElement;
|
||||||
toggleMenu(false);
|
const icon = toggle.querySelector(".dropdown-icon");
|
||||||
}
|
const isExpanded = toggle.getAttribute("aria-expanded") === "true";
|
||||||
});
|
|
||||||
|
// If clicking an already active dropdown, close it and restore interactions
|
||||||
|
if (isExpanded) {
|
||||||
|
// First close the dropdown
|
||||||
|
content?.classList.remove("show");
|
||||||
|
icon?.classList.remove("rotated");
|
||||||
|
|
||||||
|
// Then wait for animation to complete plus a delay before removing focus
|
||||||
|
setTimeout(() => {
|
||||||
|
container?.classList.remove("active");
|
||||||
|
mobileMenu?.classList.remove("has-active-dropdown");
|
||||||
|
toggle.setAttribute("aria-expanded", "false");
|
||||||
|
}, 300); // 200ms for animation + 100ms delay
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove active state from all dropdowns first
|
||||||
|
document.querySelectorAll(".dropdown-container").forEach((el) => {
|
||||||
|
const dropdownContent = el.querySelector(
|
||||||
|
".mobile-dropdown-content"
|
||||||
|
);
|
||||||
|
const dropdownToggle = el.querySelector(
|
||||||
|
".mobile-dropdown-toggle"
|
||||||
|
);
|
||||||
|
const dropdownIcon =
|
||||||
|
dropdownToggle?.querySelector(".dropdown-icon");
|
||||||
|
|
||||||
|
dropdownContent?.classList.remove("show");
|
||||||
|
dropdownIcon?.classList.remove("rotated");
|
||||||
|
dropdownToggle?.setAttribute("aria-expanded", "false");
|
||||||
|
});
|
||||||
|
|
||||||
|
// First focus the new dropdown
|
||||||
|
container?.classList.add("active");
|
||||||
|
mobileMenu?.classList.add("has-active-dropdown");
|
||||||
|
toggle.setAttribute("aria-expanded", "true");
|
||||||
|
icon?.classList.add("rotated");
|
||||||
|
|
||||||
|
// Then show the content with animation after a short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
content?.classList.add("show");
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close menu when clicking outside ~ Doesnt really work at the moment
|
||||||
|
document.addEventListener("click", (e) => {
|
||||||
|
if (
|
||||||
|
!mobileMenu?.contains(e.target as Node) &&
|
||||||
|
!menuBtn?.contains(e.target as Node) &&
|
||||||
|
!mobileMenu?.classList.contains("hidden")
|
||||||
|
) {
|
||||||
|
toggleMenu(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,26 +1,40 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "Join",
|
"name": "Join",
|
||||||
"path": "/join"
|
"path": "/join"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Events",
|
"name": "Events",
|
||||||
"path": "/events"
|
"path": "/events"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Projects",
|
"name": "Projects",
|
||||||
"path": "/projects"
|
"path": "/projects",
|
||||||
},
|
"subpages": [
|
||||||
{
|
{
|
||||||
"name": "Board",
|
"name": "Robocup",
|
||||||
"path": "/board"
|
"path": "/projects/robocup"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Find Us",
|
"name": "Signal Processing",
|
||||||
"path": "/find"
|
"path": "/projects/signal-processing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Online Store",
|
"name": "Supercomputing",
|
||||||
"path": "/online-store"
|
"path": "/projects/supercomputing"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Board",
|
||||||
|
"path": "/board"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Find Us",
|
||||||
|
"path": "/find"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Online Store",
|
||||||
|
"path": "/online-store"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue