Skip to content

Commit 7cf205a

Browse files
committed
feat: close left sidebar on category click
1 parent d93bb36 commit 7cf205a

File tree

3 files changed

+186
-182
lines changed

3 files changed

+186
-182
lines changed

components/left-sidebar-sheet.tsx

Lines changed: 162 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -12,172 +12,171 @@ import { usePosts } from "@/contexts/posts-context";
1212
import { buildFolderStructure } from "@/lib/utils";
1313

1414
export default function LeftSidebarSheet() {
15-
const { posts } = usePosts();
16-
const [open, setOpen] = useState(false);
17-
const pathname = usePathname();
15+
const { posts } = usePosts();
16+
const [open, setOpen] = useState(false);
17+
const pathname = usePathname();
1818

19-
const folderStructure = buildFolderStructure(posts);
19+
const folderStructure = buildFolderStructure(posts);
2020

21-
return (
22-
<Sheet open={open} onOpenChange={setOpen}>
23-
<DialogTitle hidden={true}></DialogTitle>
24-
<DialogDescription hidden={true}></DialogDescription>
25-
<SheetTrigger asChild className="hidden">
26-
<Button id="sidebar-trigger" variant="outline" size="icon">
27-
<Menu className="h-4 w-4" />
28-
</Button>
29-
</SheetTrigger>
30-
<SheetContent
31-
side="left"
32-
className="w-[280px] sm:w-[320px] md:w-[360px] p-0 pt-10 sm:pt-12"
33-
onCloseAutoFocus={(e) => e.preventDefault()}
34-
>
35-
<div className="relative h-full">
36-
<div className="h-full p-3 sm:p-4 flex flex-col">
37-
<ScrollArea className="flex-grow">
38-
{/* 네비게이션 링크 추가 */}
39-
<div className="mb-6 px-1 sm:px-2">
40-
<h2 className="text-lg font-semibold mb-3">메뉴</h2>
41-
<div className="flex flex-col space-y-2">
42-
<Link
43-
href="/"
44-
className={`flex items-center px-3 py-2 rounded-md transition-colors ${
45-
pathname === "/"
46-
? "bg-primary/10 text-primary font-medium"
47-
: "hover:bg-accent"
48-
}`}
49-
onClick={() => setOpen(false)}
50-
>
51-
<svg
52-
xmlns="http://www.w3.org/2000/svg"
53-
className="w-5 h-5 mr-2"
54-
viewBox="0 0 24 24"
55-
fill="none"
56-
stroke="currentColor"
57-
strokeWidth="2"
58-
strokeLinecap="round"
59-
strokeLinejoin="round"
60-
>
61-
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
62-
<polyline points="9 22 9 12 15 12 15 22"></polyline>
63-
</svg>
64-
65-
</Link>
66-
<Link
67-
href="/projects"
68-
className={`flex items-center px-3 py-2 rounded-md transition-colors ${
69-
pathname === "/projects"
70-
? "bg-primary/10 text-primary font-medium"
71-
: "hover:bg-accent"
72-
}`}
73-
onClick={() => setOpen(false)}
74-
>
75-
<svg
76-
xmlns="http://www.w3.org/2000/svg"
77-
className="w-5 h-5 mr-2"
78-
viewBox="0 0 24 24"
79-
fill="none"
80-
stroke="currentColor"
81-
strokeWidth="2"
82-
strokeLinecap="round"
83-
strokeLinejoin="round"
84-
>
85-
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
86-
<polyline points="7.5 4.21 12 6.81 16.5 4.21"></polyline>
87-
<polyline points="7.5 19.79 7.5 14.6 3 12"></polyline>
88-
<polyline points="21 12 16.5 14.6 16.5 19.79"></polyline>
89-
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
90-
<line x1="12" y1="22.08" x2="12" y2="12"></line>
91-
</svg>
92-
포트폴리오
93-
</Link>
94-
</div>
95-
</div>
21+
return (
22+
<Sheet open={open} onOpenChange={setOpen}>
23+
<DialogTitle hidden={true}></DialogTitle>
24+
<DialogDescription hidden={true}></DialogDescription>
25+
<SheetTrigger asChild className="hidden">
26+
<Button id="sidebar-trigger" variant="outline" size="icon">
27+
<Menu className="h-4 w-4" />
28+
</Button>
29+
</SheetTrigger>
30+
<SheetContent
31+
side="left"
32+
className="w-[280px] sm:w-[320px] md:w-[360px] p-0 pt-10 sm:pt-12"
33+
onCloseAutoFocus={(e) => e.preventDefault()}
34+
>
35+
<div className="relative h-full">
36+
<div className="h-full p-3 sm:p-4 flex flex-col">
37+
<ScrollArea className="flex-grow">
38+
{/* 네비게이션 링크 추가 */}
39+
<div className="mb-6 px-1 sm:px-2">
40+
<h2 className="text-lg font-semibold mb-3">메뉴</h2>
41+
<div className="flex flex-col space-y-2">
42+
<Link
43+
href="/"
44+
className={`flex items-center px-3 py-2 rounded-md transition-colors ${pathname === "/"
45+
? "bg-primary/10 text-primary font-medium"
46+
: "hover:bg-accent"
47+
}`}
48+
onClick={() => setOpen(false)}
49+
>
50+
<svg
51+
xmlns="http://www.w3.org/2000/svg"
52+
className="w-5 h-5 mr-2"
53+
viewBox="0 0 24 24"
54+
fill="none"
55+
stroke="currentColor"
56+
strokeWidth="2"
57+
strokeLinecap="round"
58+
strokeLinejoin="round"
59+
>
60+
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
61+
<polyline points="9 22 9 12 15 12 15 22"></polyline>
62+
</svg>
63+
64+
</Link>
65+
<Link
66+
href="/projects"
67+
className={`flex items-center px-3 py-2 rounded-md transition-colors ${pathname === "/projects"
68+
? "bg-primary/10 text-primary font-medium"
69+
: "hover:bg-accent"
70+
}`}
71+
onClick={() => setOpen(false)}
72+
>
73+
<svg
74+
xmlns="http://www.w3.org/2000/svg"
75+
className="w-5 h-5 mr-2"
76+
viewBox="0 0 24 24"
77+
fill="none"
78+
stroke="currentColor"
79+
strokeWidth="2"
80+
strokeLinecap="round"
81+
strokeLinejoin="round"
82+
>
83+
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
84+
<polyline points="7.5 4.21 12 6.81 16.5 4.21"></polyline>
85+
<polyline points="7.5 19.79 7.5 14.6 3 12"></polyline>
86+
<polyline points="21 12 16.5 14.6 16.5 19.79"></polyline>
87+
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
88+
<line x1="12" y1="22.08" x2="12" y2="12"></line>
89+
</svg>
90+
포트폴리오
91+
</Link>
92+
</div>
93+
</div>
9694

97-
<h2 className="text-lg font-semibold mb-3 sm:mb-4 px-1 sm:px-2">
98-
카테고리
99-
</h2>
100-
<TreeView
101-
key={`mobile-tree-${pathname}`}
102-
data={folderStructure}
103-
/>
104-
</ScrollArea>
95+
<h2 className="text-lg font-semibold mb-3 sm:mb-4 px-1 sm:px-2">
96+
카테고리
97+
</h2>
98+
<TreeView
99+
key={`mobile-tree-${pathname}`}
100+
data={folderStructure}
101+
onNodeClick={() => setOpen(false)}
102+
/>
103+
</ScrollArea>
105104

106-
{/* 푸터 정보 */}
107-
<div className="py-6 border-t border-border/60">
108-
{/* 소셜 링크 */}
109-
<div className="flex items-center justify-center gap-4 mb-4">
110-
<Link
111-
href="https://github.com/lazy-dinosaur"
112-
target="_blank"
113-
onClick={() => setOpen(false)}
114-
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
115-
>
116-
<svg
117-
xmlns="http://www.w3.org/2000/svg"
118-
viewBox="0 0 24 24"
119-
fill="none"
120-
stroke="currentColor"
121-
strokeWidth="2"
122-
strokeLinecap="round"
123-
strokeLinejoin="round"
124-
className="w-4 h-4"
125-
>
126-
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
127-
</svg>
128-
</Link>
129-
<Link
130-
href="mailto:[email protected]"
131-
target="_blank"
132-
onClick={() => setOpen(false)}
133-
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
134-
>
135-
<svg
136-
xmlns="http://www.w3.org/2000/svg"
137-
viewBox="0 0 24 24"
138-
fill="none"
139-
stroke="currentColor"
140-
strokeWidth="2"
141-
strokeLinecap="round"
142-
strokeLinejoin="round"
143-
className="w-4 h-4"
144-
>
145-
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
146-
<polyline points="22,6 12,13 2,6"></polyline>
147-
</svg>
148-
</Link>
149-
<Link
150-
href="https://open.kakao.com/o/sdG4BPjh"
151-
target="_blank"
152-
onClick={() => setOpen(false)}
153-
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
154-
>
155-
<svg
156-
xmlns="http://www.w3.org/2000/svg"
157-
viewBox="0 0 24 24"
158-
fill="currentColor"
159-
className="w-4 h-4"
160-
>
161-
<path
162-
fillRule="evenodd"
163-
d="M12 2C6.486 2 2 5.677 2 10.2c0 2.933 1.904 5.41 4.666 6.82-.193.86-.707 3.088-.73 3.266-.036.268.127.517.364.593.085.028.174.041.262.041.147 0 .291-.054.404-.155.16-.143 2.398-1.647 3.484-2.384.503.07 1.026.118 1.55.118 5.514 0 10-3.675 10-8.2C22 5.677 17.514 2 12 2z"
164-
clipRule="evenodd"
165-
/>
166-
</svg>
167-
</Link>
168-
</div>
105+
{/* 푸터 정보 */}
106+
<div className="py-6 border-t border-border/60">
107+
{/* 소셜 링크 */}
108+
<div className="flex items-center justify-center gap-4 mb-4">
109+
<Link
110+
href="https://github.com/lazy-dinosaur"
111+
target="_blank"
112+
onClick={() => setOpen(false)}
113+
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
114+
>
115+
<svg
116+
xmlns="http://www.w3.org/2000/svg"
117+
viewBox="0 0 24 24"
118+
fill="none"
119+
stroke="currentColor"
120+
strokeWidth="2"
121+
strokeLinecap="round"
122+
strokeLinejoin="round"
123+
className="w-4 h-4"
124+
>
125+
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
126+
</svg>
127+
</Link>
128+
<Link
129+
href="mailto:[email protected]"
130+
target="_blank"
131+
onClick={() => setOpen(false)}
132+
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
133+
>
134+
<svg
135+
xmlns="http://www.w3.org/2000/svg"
136+
viewBox="0 0 24 24"
137+
fill="none"
138+
stroke="currentColor"
139+
strokeWidth="2"
140+
strokeLinecap="round"
141+
strokeLinejoin="round"
142+
className="w-4 h-4"
143+
>
144+
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
145+
<polyline points="22,6 12,13 2,6"></polyline>
146+
</svg>
147+
</Link>
148+
<Link
149+
href="https://open.kakao.com/o/sdG4BPjh"
150+
target="_blank"
151+
onClick={() => setOpen(false)}
152+
className="flex items-center justify-center w-8 h-8 rounded-full bg-primary/10 text-primary hover:bg-primary/20 transition-colors"
153+
>
154+
<svg
155+
xmlns="http://www.w3.org/2000/svg"
156+
viewBox="0 0 24 24"
157+
fill="currentColor"
158+
className="w-4 h-4"
159+
>
160+
<path
161+
fillRule="evenodd"
162+
d="M12 2C6.486 2 2 5.677 2 10.2c0 2.933 1.904 5.41 4.666 6.82-.193.86-.707 3.088-.73 3.266-.036.268.127.517.364.593.085.028.174.041.262.041.147 0 .291-.054.404-.155.16-.143 2.398-1.647 3.484-2.384.503.07 1.026.118 1.55.118 5.514 0 10-3.675 10-8.2C22 5.677 17.514 2 12 2z"
163+
clipRule="evenodd"
164+
/>
165+
</svg>
166+
</Link>
167+
</div>
169168

170-
{/* 저작권 정보 */}
171-
<div className="text-xs text-muted-foreground text-center">
172-
Copyright © {new Date().getFullYear()} by Hyeongseok Woo
173-
</div>
174-
<div className="text-xs text-muted-foreground text-center mt-1">
175-
Built with Next.js, TypeScript, and Tailwind CSS
176-
</div>
177-
</div>
178-
</div>
179-
</div>
180-
</SheetContent>
181-
</Sheet>
182-
);
169+
{/* 저작권 정보 */}
170+
<div className="text-xs text-muted-foreground text-center">
171+
Copyright © {new Date().getFullYear()} by Hyeongseok Woo
172+
</div>
173+
<div className="text-xs text-muted-foreground text-center mt-1">
174+
Built with Next.js, TypeScript, and Tailwind CSS
175+
</div>
176+
</div>
177+
</div>
178+
</div>
179+
</SheetContent>
180+
</Sheet>
181+
);
183182
}

components/tree-view.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ interface TreeViewProps {
1111
data: FolderStructure[];
1212
level?: number;
1313
parentPath?: string;
14+
onNodeClick: () => void;
1415
}
1516

16-
export function TreeView({ data, level = 0, parentPath = "" }: TreeViewProps) {
17+
export function TreeView({ data, level = 0, parentPath = "", onNodeClick }: TreeViewProps) {
1718
return (
1819
<div className="space-y-1.5">
1920
{data.map((item) => (
@@ -22,6 +23,7 @@ export function TreeView({ data, level = 0, parentPath = "" }: TreeViewProps) {
2223
node={item}
2324
level={level}
2425
parentPath={parentPath}
26+
onNodeClick={onNodeClick}
2527
/>
2628
))}
2729
</div>
@@ -32,10 +34,12 @@ function TreeNode({
3234
node,
3335
level,
3436
parentPath,
37+
onNodeClick,
3538
}: {
3639
node: FolderStructure;
3740
level: number;
3841
parentPath: string;
42+
onNodeClick: () => void;
3943
}) {
4044
const [isExpanded, setIsExpanded] = useState(false);
4145
const pathname = usePathname();
@@ -86,7 +90,7 @@ function TreeNode({
8690
)}
8791
<div className="flex-1 min-w-0 max-w-full">
8892
{node.type === "file" ? (
89-
<Link href={normalizedCurrentPath} className={linkClassName}>
93+
<Link href={normalizedCurrentPath} className={linkClassName} onClick={() => onNodeClick()}>
9094
{isFileActive && (
9195
<span className="absolute left-0 top-0 bottom-0 w-0.5 bg-primary" />
9296
)}
@@ -128,6 +132,7 @@ function TreeNode({
128132
data={node.children}
129133
level={level + 1}
130134
parentPath={currentPath}
135+
onNodeClick={onNodeClick}
131136
/>
132137
</motion.div>
133138
)}

0 commit comments

Comments
 (0)