mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
website: fix astro not compiling because it can't detect server-side component
This commit is contained in:
parent
a2894db652
commit
dbba55606b
43
website/src/components/drawer/Drawer.astro
Normal file
43
website/src/components/drawer/Drawer.astro
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
import { LuMenu } from "react-icons/lu";
|
||||
---
|
||||
|
||||
<button
|
||||
id="button-toggle"
|
||||
class="btn btn-icon"
|
||||
class:list={[Astro.props.class]}
|
||||
>
|
||||
{(<LuMenu />)}
|
||||
</button>
|
||||
|
||||
<div
|
||||
id="drawer"
|
||||
class="fixed bg-white dark:bg-surface-800 shadow-lg transition-all duration-300 left-0 top-0 h-screen w-64 -translate-x-[100vw] z-[100]"
|
||||
>
|
||||
<button
|
||||
id="button-close"
|
||||
class="absolute top-2 right-2 text-gray-500 hover:text-gray-700"
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<div class="p-4">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const buttonToggle = document.getElementById("button-toggle");
|
||||
const drawer = document.getElementById("drawer");
|
||||
const buttonClose = document.getElementById("button-close");
|
||||
|
||||
buttonToggle?.addEventListener("click", () => {
|
||||
drawer?.classList.toggle("-translate-x-[100vw]");
|
||||
});
|
||||
|
||||
buttonClose?.addEventListener("click", () => {
|
||||
drawer?.classList.add("-translate-x-[100vw]");
|
||||
});
|
||||
});
|
||||
</script>
|
@ -1,45 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { LuMenu } from "react-icons/lu";
|
||||
|
||||
|
||||
|
||||
interface DrawerProps {
|
||||
buttonLabel?: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
|
||||
export const Drawer: React.FC<DrawerProps> = ({
|
||||
buttonLabel = <LuMenu />,
|
||||
children,
|
||||
className = "",
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button className={`btn btn-icon ${className}`} onClick={() => setOpen(true)}>
|
||||
{buttonLabel}
|
||||
</button>
|
||||
|
||||
|
||||
{/* Drawer */}
|
||||
<div
|
||||
className={`
|
||||
fixed bg-white dark:bg-surface-800 shadow-lg transition-all duration-300 left-0 top-0 h-screen w-64
|
||||
${open ? "-translate-x-5" : "-translate-x-[100vw]"}
|
||||
`}
|
||||
>
|
||||
<button
|
||||
className="absolute top-2 right-2 text-gray-500 hover:text-gray-700"
|
||||
onClick={() => setOpen(false)}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<div className="p-4">{children}</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,63 +1,13 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
interface NavigationItem extends HTMLAttributes<"a"> {
|
||||
title: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
interface NavigationGroup {
|
||||
title: string;
|
||||
items: NavigationItem[];
|
||||
}
|
||||
import { getNavigationCollection } from "~/utils/get-collection";
|
||||
|
||||
interface Props {
|
||||
topGroups?: NavigationGroup[];
|
||||
classList?: string;
|
||||
bottomGroups?: NavigationGroup[];
|
||||
classList?: string[];
|
||||
}
|
||||
|
||||
const { classList } = Astro.props;
|
||||
|
||||
const sortByOrder = (a: CollectionEntry<"docs">, b: CollectionEntry<"docs">) =>
|
||||
a.data.order - b.data.order;
|
||||
|
||||
async function queryCollection(startsWith: string) {
|
||||
return (
|
||||
await getCollection("docs", (entry) => {
|
||||
if (!entry.id.startsWith(startsWith)) return false;
|
||||
if (entry.id.split("/").length > 2) return false;
|
||||
if (entry.id.endsWith("meta")) return false;
|
||||
return true;
|
||||
})
|
||||
).toSorted(sortByOrder);
|
||||
}
|
||||
const toNavItems = (entries: CollectionEntry<"docs">[]) =>
|
||||
entries.map((page) => ({
|
||||
title: page.data.title,
|
||||
href: `/docs/${page.id}`,
|
||||
}));
|
||||
|
||||
// Define navigation sections
|
||||
const sections: [
|
||||
string,
|
||||
string,
|
||||
(prefix: string) => Promise<CollectionEntry<"docs">[]>,
|
||||
][] = [
|
||||
["Get Started", "get-started/", queryCollection],
|
||||
["Developing Plugins", "developing-plugins/", queryCollection],
|
||||
["Plugin APIs", "plugin-apis/", queryCollection],
|
||||
["Reference", "reference/", queryCollection],
|
||||
];
|
||||
|
||||
// Build navigation dynamically
|
||||
const navigation: NavigationGroup[] = await Promise.all(
|
||||
sections.map(async ([title, prefix, queryFn]) => ({
|
||||
title,
|
||||
items: toNavItems(await queryFn(prefix)),
|
||||
}))
|
||||
);
|
||||
const navigation = await getNavigationCollection();
|
||||
|
||||
const pathname = Astro.url.pathname.endsWith("/")
|
||||
? Astro.url.pathname.slice(0, -1)
|
||||
|
@ -3,8 +3,6 @@ import { routes } from "~/collections/app";
|
||||
import { FaGithub } from "react-icons/fa6";
|
||||
import SidebarButton from "./sidebar-button";
|
||||
import Search from "astro-pagefind/components/Search";
|
||||
import { Drawer } from "../drawer/drawer";
|
||||
import DocSideBar from "./DocSideBar.astro";
|
||||
|
||||
const pathname = Astro.url.pathname;
|
||||
---
|
||||
@ -16,9 +14,7 @@ const pathname = Astro.url.pathname;
|
||||
<div class="flex items-center gap-2">
|
||||
{
|
||||
pathname.startsWith("/docs") ? (
|
||||
<Drawer client:only className="md:hidden">
|
||||
<DocSideBar />
|
||||
</Drawer>
|
||||
<div class="h-10 w-10" />
|
||||
) : (
|
||||
<SidebarButton client:only />
|
||||
)
|
||||
|
@ -3,6 +3,8 @@ import RootLayout from "layouts/RootLayout.astro";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
import { render } from "astro:content";
|
||||
import { getCollection, getEntry } from "astro:content";
|
||||
import DocSideBar from "~/components/navigation/DocSideBar.astro";
|
||||
import Drawer from "~/components/drawer/Drawer.astro";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const pages = await getCollection("docs");
|
||||
@ -29,5 +31,8 @@ if (page.id.startsWith("components/") || page.id.startsWith("integrations/")) {
|
||||
---
|
||||
|
||||
<RootLayout>
|
||||
<Drawer class="fixed top-3 left-2 z-50 md:hidden">
|
||||
<DocSideBar />
|
||||
</Drawer>
|
||||
<Content />
|
||||
</RootLayout>
|
||||
|
57
website/src/utils/get-collection.ts
Normal file
57
website/src/utils/get-collection.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { getCollection, type CollectionEntry } from "astro:content";
|
||||
|
||||
interface NavigationItem extends HTMLAttributes<"a"> {
|
||||
title: string;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
export interface NavigationGroup {
|
||||
title: string;
|
||||
items: NavigationItem[];
|
||||
}
|
||||
|
||||
function sortByOrder(a: CollectionEntry<"docs">, b: CollectionEntry<"docs">) {
|
||||
return a.data.order - b.data.order;
|
||||
}
|
||||
|
||||
async function queryCollection(startsWith: string) {
|
||||
return (
|
||||
await getCollection("docs", (entry) => {
|
||||
if (!entry.id.startsWith(startsWith)) return false;
|
||||
if (entry.id.split("/").length > 2) return false;
|
||||
if (entry.id.endsWith("meta")) return false;
|
||||
return true;
|
||||
})
|
||||
).toSorted(sortByOrder);
|
||||
}
|
||||
function toNavItems(entries: CollectionEntry<"docs">[]) {
|
||||
return entries.map((page) => ({
|
||||
title: page.data.title,
|
||||
href: `/docs/${page.id}`,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getNavigationCollection() {
|
||||
// Define navigation sections
|
||||
const sections: [
|
||||
string,
|
||||
string,
|
||||
(prefix: string) => Promise<CollectionEntry<"docs">[]>
|
||||
][] = [
|
||||
["Get Started", "get-started/", queryCollection],
|
||||
["Developing Plugins", "developing-plugins/", queryCollection],
|
||||
["Plugin APIs", "plugin-apis/", queryCollection],
|
||||
["Reference", "reference/", queryCollection],
|
||||
];
|
||||
|
||||
// Build navigation dynamically
|
||||
const navigation: NavigationGroup[] = await Promise.all(
|
||||
sections.map(async ([title, prefix, queryFn]) => ({
|
||||
title,
|
||||
items: toNavItems(await queryFn(prefix)),
|
||||
}))
|
||||
);
|
||||
|
||||
return navigation;
|
||||
}
|
Loading…
Reference in New Issue
Block a user