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 { getNavigationCollection } from "~/utils/get-collection";
|
||||||
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[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
topGroups?: NavigationGroup[];
|
classList?: string[];
|
||||||
classList?: string;
|
|
||||||
bottomGroups?: NavigationGroup[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { classList } = Astro.props;
|
const { classList } = Astro.props;
|
||||||
|
|
||||||
const sortByOrder = (a: CollectionEntry<"docs">, b: CollectionEntry<"docs">) =>
|
const navigation = await getNavigationCollection();
|
||||||
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 pathname = Astro.url.pathname.endsWith("/")
|
const pathname = Astro.url.pathname.endsWith("/")
|
||||||
? Astro.url.pathname.slice(0, -1)
|
? Astro.url.pathname.slice(0, -1)
|
||||||
|
@ -3,8 +3,6 @@ import { routes } from "~/collections/app";
|
|||||||
import { FaGithub } from "react-icons/fa6";
|
import { FaGithub } from "react-icons/fa6";
|
||||||
import SidebarButton from "./sidebar-button";
|
import SidebarButton from "./sidebar-button";
|
||||||
import Search from "astro-pagefind/components/Search";
|
import Search from "astro-pagefind/components/Search";
|
||||||
import { Drawer } from "../drawer/drawer";
|
|
||||||
import DocSideBar from "./DocSideBar.astro";
|
|
||||||
|
|
||||||
const pathname = Astro.url.pathname;
|
const pathname = Astro.url.pathname;
|
||||||
---
|
---
|
||||||
@ -16,9 +14,7 @@ const pathname = Astro.url.pathname;
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{
|
{
|
||||||
pathname.startsWith("/docs") ? (
|
pathname.startsWith("/docs") ? (
|
||||||
<Drawer client:only className="md:hidden">
|
<div class="h-10 w-10" />
|
||||||
<DocSideBar />
|
|
||||||
</Drawer>
|
|
||||||
) : (
|
) : (
|
||||||
<SidebarButton client:only />
|
<SidebarButton client:only />
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,8 @@ import RootLayout from "layouts/RootLayout.astro";
|
|||||||
import type { GetStaticPaths } from "astro";
|
import type { GetStaticPaths } from "astro";
|
||||||
import { render } from "astro:content";
|
import { render } from "astro:content";
|
||||||
import { getCollection, getEntry } 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 () => {
|
export const getStaticPaths = (async () => {
|
||||||
const pages = await getCollection("docs");
|
const pages = await getCollection("docs");
|
||||||
@ -29,5 +31,8 @@ if (page.id.startsWith("components/") || page.id.startsWith("integrations/")) {
|
|||||||
---
|
---
|
||||||
|
|
||||||
<RootLayout>
|
<RootLayout>
|
||||||
|
<Drawer class="fixed top-3 left-2 z-50 md:hidden">
|
||||||
|
<DocSideBar />
|
||||||
|
</Drawer>
|
||||||
<Content />
|
<Content />
|
||||||
</RootLayout>
|
</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