Skip to content

Commit 17285b4

Browse files
committed
refactor: reorganize components for improved structure and responsiveness
1 parent c053f9a commit 17285b4

File tree

6 files changed

+240
-91
lines changed

6 files changed

+240
-91
lines changed

.astro/content-modules.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11

22
export default new Map([
33
["src/content/blog/welcome.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fblog%2Fwelcome.mdx&astroContentModuleFlag=true")],
4-
["src/content/docs/framework/blog.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fblog.mdx&astroContentModuleFlag=true")],
54
["src/content/docs/framework/configuration.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fconfiguration.mdx&astroContentModuleFlag=true")],
65
["src/content/docs/framework/docs.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fdocs.mdx&astroContentModuleFlag=true")],
7-
["src/content/docs/framework/installation.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Finstallation.mdx&astroContentModuleFlag=true")],
6+
["src/content/docs/framework/blog.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fblog.mdx&astroContentModuleFlag=true")],
87
["src/content/docs/framework/getting-started.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fgetting-started.mdx&astroContentModuleFlag=true")],
98
["src/content/docs/framework/project-structure.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Fproject-structure.mdx&astroContentModuleFlag=true")],
109
["src/content/docs/syntax/alert.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Falert.mdx&astroContentModuleFlag=true")],
10+
["src/content/docs/framework/installation.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframework%2Finstallation.mdx&astroContentModuleFlag=true")],
1111
["src/content/docs/syntax/code-block.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Fcode-block.mdx&astroContentModuleFlag=true")],
12-
["src/content/docs/syntax/markdown.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Fmarkdown.mdx&astroContentModuleFlag=true")],
13-
["src/content/docs/syntax/text.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Ftext.mdx&astroContentModuleFlag=true")]]);
12+
["src/content/docs/syntax/text.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Ftext.mdx&astroContentModuleFlag=true")],
13+
["src/content/docs/syntax/markdown.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fsyntax%2Fmarkdown.mdx&astroContentModuleFlag=true")]]);
1414

Lines changed: 113 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,125 @@
1-
import * as React from "react"
2-
import { cn } from "@/utils"
3-
import { Menu, X } from "lucide-react"
4-
import { Button } from "../ui/button"
1+
import {
2+
Sheet,
3+
SheetContent,
4+
SheetDescription,
5+
SheetHeader,
6+
SheetTrigger
7+
} from "@/components/ui/sheet"
8+
import { Icon } from '@iconify/react'
9+
import clsx from 'clsx'
10+
import { Fragment, useState } from 'react'
11+
import config from '../../../../explainer.config'
512

6-
interface SidebarItem {
7-
title: string
8-
href: string
9-
icon?: React.ReactNode
10-
items?: SidebarItem[]
13+
type Props = {
1114
}
1215

13-
interface DocsSidebarProps {
14-
items: SidebarItem[]
15-
className?: string
16-
}
16+
export function DocsSidebar(props: Props) {
17+
const [isOpen, setIsOpen] = useState(false)
1718

18-
const SidebarLink = ({ item }: { item: SidebarItem }) => {
1919
return (
20-
<li>
21-
<a
22-
href={item.href}
23-
className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground rounded-md hover:bg-accent hover:text-accent-foreground"
24-
>
25-
{item.icon}
26-
{item.title}
27-
</a>
28-
{item.items && (
29-
<ul className="ml-4 mt-2 space-y-1">
30-
{item.items.map((subItem) => (
31-
<SidebarLink key={subItem.href} item={subItem} />
32-
))}
33-
</ul>
34-
)}
35-
</li>
20+
<div>
21+
<div>
22+
<SidebarRenderer />
23+
</div>
24+
<Sheet open={isOpen} onOpenChange={setIsOpen}>
25+
<SheetTrigger>
26+
<Icon
27+
icon={isOpen ? 'lucide:chevron-up' : 'lucide:chevron-down'}
28+
className="size-5"
29+
/>
30+
</SheetTrigger>
31+
<SheetContent side="left">
32+
<SheetHeader>
33+
<SheetDescription />
34+
<SidebarRenderer />
35+
</SheetHeader>
36+
</SheetContent>
37+
</Sheet>
38+
</div>
3639
)
3740
}
3841

39-
export function DocsSidebar({ items, className }: DocsSidebarProps) {
40-
const [isOpen, setIsOpen] = React.useState(false)
41-
42+
function SidebarRenderer() {
4243
return (
43-
<>
44-
{/* Mobile toggle */}
45-
<Button
46-
variant="ghost"
47-
size="icon"
48-
className="fixed top-4 left-4 z-40 lg:hidden"
49-
onClick={() => setIsOpen(!isOpen)}
50-
>
51-
{isOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
52-
</Button>
44+
<Fragment>
45+
<nav>
46+
<div className="space-y-3 mb-3 lg:mb-6 -mx-1 lg:mx-0">
47+
{
48+
Object.entries(config.docs).map(([key, element]) => (
49+
<a
50+
className="flex items-center gap-2 group text-primary font-medium"
51+
href={element.href}
52+
>
53+
<div
54+
className={clsx(
55+
"rounded-sm p-1 inline-flex ring-inset ring-1",
56+
window.location.pathname.startsWith(element.baseUrl)
57+
? "bg-primary ring-primary text-white"
58+
: "bg-gray-50 dark:bg-gray-800 ring-gray-200 dark:ring-gray-700 text-muted-foreground",
59+
)}
60+
>
61+
<Icon
62+
icon={element.icon}
63+
className="size-4"
64+
/>
65+
</div>
66+
<span
67+
className={clsx(
68+
"text-sm relative",
69+
window.location.pathname.startsWith(element.baseUrl)
70+
? "text-primary"
71+
: "text-muted-foreground",
72+
)}
73+
>
74+
{element.label}
75+
</span>
76+
</a>
77+
))
78+
}
79+
</div>
80+
</nav>
5381

54-
{/* Backdrop */}
55-
{isOpen && (
56-
<div
57-
className="fixed inset-0 z-30 bg-background/80 backdrop-blur-sm lg:hidden"
58-
onClick={() => setIsOpen(false)}
59-
/>
60-
)}
82+
<hr
83+
className="my-5 border-dashed border-gray-200 dark:border-gray-700"
84+
/>
6185

62-
{/* Sidebar */}
63-
<aside
64-
className={cn(
65-
"fixed top-0 left-0 z-30 h-screen w-72 border-r bg-background transition-transform lg:translate-x-0 lg:relative",
66-
isOpen ? "translate-x-0" : "-translate-x-full",
67-
className
68-
)}
69-
>
70-
<div className="sticky top-0 overflow-y-auto h-full p-6 pt-16 lg:pt-6">
71-
<nav>
72-
<ul className="space-y-2">
73-
{items.map((item) => (
74-
<SidebarLink key={item.href} item={item} />
75-
))}
76-
</ul>
77-
</nav>
78-
</div>
79-
</aside>
80-
</>
86+
<div className="space-y-1">
87+
{
88+
currentCollectionItems.map((item) => (
89+
<a
90+
href={item.href}
91+
className="group block py-1.5 px-1.5 text-sm rounded-md transition-colors hover:text-primary"
92+
>
93+
<div className="flex items-center gap-2">
94+
{item.icon ? (
95+
<Icon
96+
client:only
97+
icon={item.icon}
98+
className={clsx(
99+
"text-gray-500 dark:text-gray-400 group-hover:text-primary size-5",
100+
Astro.url.pathname.startsWith(item.href)
101+
? "text-primary"
102+
: "text-muted-foreground",
103+
)}
104+
/>
105+
) : (
106+
<div className="size-5" />
107+
)}
108+
<span
109+
className={clsx(
110+
"text-sm group-hover:text-primary",
111+
Astro.url.pathname.startsWith(item.href)
112+
? "text-primary"
113+
: "text-muted-foreground",
114+
)}
115+
>
116+
{item.label}
117+
</span>
118+
</div>
119+
</a>
120+
))
121+
}
122+
</div>
123+
</Fragment >
81124
)
82-
}
125+
}

src/lib/components/elements/navbar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export default function Navbar() {
114114
</div>
115115
</div>
116116

117-
<div className="flex items-center gap-2sm:hidden">
117+
<div className="flex items-center gap-2 sm:hidden">
118118
<ThemeToggle />
119119
<Sheet>
120120
<SheetTrigger asChild>

src/lib/layouts/DocsLayout.astro

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { Icon } from "@iconify/react";
44
import type { CollectionKey, z } from "astro:content";
55
import { getCollection } from "astro:content";
66
import clsx from "clsx";
7-
import type { icons } from "lucide-react";
87
import type { docSchema } from "src/content.config";
98
import config from "../../../explainer.config";
109
import "../../assets/css/global.css";
@@ -35,9 +34,9 @@ const currentCollectionItems = collection
3534
<BaseLayout>
3635
<main class="relative flex-1">
3736
<Separator />
38-
<div class="mx-auto px-4 sm:px-0 max-w-screen-xl">
37+
<div class="mx-auto px-2 sm:px-0 max-w-screen-xl">
3938
<div class="flex flex-col lg:grid lg:grid-cols-10 lg:gap-8">
40-
<aside class="lg:col-span-2 pr-2">
39+
<aside class="hidden sm:block lg:col-span-2 pr-2">
4140
<div
4241
class="sticky top-14 px-4 sm:px-0 py-8 overflow-y-auto h-[calc(100vh-4rem)]"
4342
>
@@ -94,7 +93,7 @@ const currentCollectionItems = collection
9493
{item.icon ? (
9594
<Icon
9695
client:only
97-
icon={item.icon as keyof typeof icons}
96+
icon={item.icon}
9897
className={clsx(
9998
"text-gray-500 dark:text-gray-400 group-hover:text-primary size-5",
10099
Astro.url.pathname.startsWith(item.href)
@@ -122,8 +121,115 @@ const currentCollectionItems = collection
122121
</div>
123122
</div>
124123
</aside>
124+
<div
125+
class="flex justify-between border-b border-dashed border-border py-2.5 px-4 sm:hidden"
126+
>
127+
<details class="group w-full">
128+
<summary
129+
class="text-sm font-semibold w-full flex items-center justify-between cursor-pointer"
130+
>
131+
<span>In the documentation</span>
132+
<div class="flex">
133+
<svg
134+
class="h-4 w-4 transition-transform group-open:rotate-180"
135+
xmlns="http://www.w3.org/2000/svg"
136+
fill="none"
137+
viewBox="0 0 24 24"
138+
stroke="currentColor"
139+
>
140+
<path
141+
stroke-linecap="round"
142+
stroke-linejoin="round"
143+
stroke-width="2"
144+
d="M19 9l-7 7-7-7"></path>
145+
</svg>
146+
</div>
147+
</summary>
148+
<div class="mt-2">
149+
<div class="px-4 sm:px-0 py-5 overflow-y-auto">
150+
<nav>
151+
<div class="space-y-3 mb-3 lg:mb-6 -mx-1 lg:mx-0">
152+
{
153+
Object.entries(config.docs).map(([key, element]) => (
154+
<a
155+
class="flex items-center gap-2 group text-primary font-medium"
156+
href={element.href}
157+
>
158+
<div
159+
class={clsx(
160+
"rounded-sm p-1 inline-flex ring-inset ring-1",
161+
Astro.url.pathname.startsWith(element.baseUrl)
162+
? "bg-primary ring-primary text-white"
163+
: "bg-gray-50 dark:bg-gray-800 ring-gray-200 dark:ring-gray-700 text-muted-foreground",
164+
)}
165+
>
166+
<Icon
167+
client:only
168+
icon={element.icon}
169+
className="size-4"
170+
/>
171+
</div>
172+
<span
173+
class={clsx(
174+
"text-sm relative",
175+
Astro.url.pathname.startsWith(element.baseUrl)
176+
? "text-primary"
177+
: "text-muted-foreground",
178+
)}
179+
>
180+
{element.label}
181+
</span>
182+
</a>
183+
))
184+
}
185+
</div>
186+
</nav>
187+
188+
<hr
189+
class="my-5 border-dashed border-gray-200 dark:border-gray-700"
190+
/>
125191

126-
{/* Main content */}
192+
<div class="space-y-1">
193+
{
194+
currentCollectionItems.map((item) => (
195+
<a
196+
href={item.href}
197+
class="group block py-1.5 px-1.5 text-sm rounded-md transition-colors hover:text-primary"
198+
>
199+
<div class="flex items-center gap-2">
200+
{item.icon ? (
201+
<Icon
202+
client:only
203+
icon={item.icon}
204+
className={clsx(
205+
"text-gray-500 dark:text-gray-400 group-hover:text-primary size-5",
206+
Astro.url.pathname.startsWith(item.href)
207+
? "text-primary"
208+
: "text-muted-foreground",
209+
)}
210+
/>
211+
) : (
212+
<div class="size-5" />
213+
)}
214+
<span
215+
class={clsx(
216+
"text-sm group-hover:text-primary",
217+
Astro.url.pathname.startsWith(item.href)
218+
? "text-primary"
219+
: "text-muted-foreground",
220+
)}
221+
>
222+
{item.label}
223+
</span>
224+
</div>
225+
</a>
226+
))
227+
}
228+
</div>
229+
</div>
230+
</div>
231+
</details>
232+
</div>
127233
<slot />
128234
</div>
129235
</div>

src/lib/utils.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import type { CollectionKey } from 'astro:content'
2-
import { clsx, type ClassValue } from "clsx"
3-
import { twMerge } from "tailwind-merge"
1+
import type { CollectionKey } from 'astro:content';
2+
import { clsx, type ClassValue } from "clsx";
3+
import { twMerge } from "tailwind-merge";
44

55
export function cn(...inputs: ClassValue[]) {
66
return twMerge(clsx(inputs))
77
}
88

9+
export type HeadingNode = {
10+
depth: number;
11+
slug: string;
12+
text: string;
13+
children: HeadingNode[];
14+
};
15+
916
type NavbarCollection = {
1017
label: string
1118
items?: NavbarItem[]

0 commit comments

Comments
 (0)