Skip to content

Commit 50d6c4a

Browse files
Navbar LeftSidebar RightSidebar
1 parent 588a5fc commit 50d6c4a

22 files changed

+1969
-39
lines changed

app/(root)/(home)/page.tsx

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,5 @@
11
"use client";
22

3-
import { UserButton } from "@clerk/nextjs";
4-
5-
const DotIcon = () => {
6-
return (
7-
<svg
8-
xmlns="http://www.w3.org/2000/svg"
9-
viewBox="0 0 512 512"
10-
fill="currentColor"
11-
>
12-
<path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512z" />
13-
</svg>
14-
);
15-
};
16-
173
export default function Home() {
18-
return (
19-
<header>
20-
<UserButton>
21-
<UserButton.MenuItems>
22-
<UserButton.Action
23-
label="Open chat"
24-
labelIcon={<DotIcon />}
25-
onClick={() => alert("init chat")}
26-
/>
27-
</UserButton.MenuItems>
28-
</UserButton>
29-
</header>
30-
);
4+
return <header></header>;
315
}

app/(root)/layout.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import LeftSidebar from "@/components/shared/LeftSidebar";
2+
import Navbar from "@/components/shared/navbar/Navbar";
3+
import RightSidebar from "@/components/shared/RightSidebar";
4+
import React from "react";
5+
6+
const Layout = ({ children }: { children: React.ReactNode }) => {
7+
return (
8+
<main className="background-light850_dark100 relative">
9+
<Navbar />
10+
<div className="flex">
11+
<LeftSidebar />
12+
<section className="flex min-h-screen flex-1 flex-col px-6 pb-6 pt-36 max-md:pb-14 sm:px-14">
13+
<div className="mx-auto w-full max-w-5xl">{children}</div>
14+
</section>
15+
<RightSidebar />
16+
</div>
17+
Toaster
18+
</main>
19+
);
20+
};
21+
22+
export default Layout;

components.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "default",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "app/globals.css",
9+
"baseColor": "slate",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
}
20+
}

components/shared/LeftSidebar.tsx

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"use client";
2+
3+
import { sidebarLinks } from "@/constants";
4+
import Image from "next/image";
5+
import Link from "next/link";
6+
import { usePathname } from "next/navigation";
7+
import React from "react";
8+
import { Button } from "../ui/button";
9+
10+
const LeftSidebar = () => {
11+
const pathName = usePathname();
12+
return (
13+
<section className="background-light900_dark200 light-border custom-scrollbar sticky left-0 top-0 flex h-screen flex-col justify-between overflow-y-auto border-r p-6 pt-36 shadow-light-300 dark:shadow-none max-sm:hidden lg:w-[266px]">
14+
<div className="flex flex-1 flex-col gap-6">
15+
{sidebarLinks.map((item) => {
16+
const isActive =
17+
(pathName.includes(item.route) && item.route.length > 1) ||
18+
pathName === item.route;
19+
return (
20+
<Link
21+
key={item.route}
22+
href={item.route}
23+
className={`${isActive ? "primary-gradient rounded-lg text-light-900" : "text-dark300_light900"} flex items-center justify-start gap-4 bg-transparent p-4`}
24+
>
25+
<Image
26+
src={item.imgURL}
27+
alt={item.label}
28+
width={20}
29+
height={20}
30+
className={`${isActive ? "" : "invert-colors"}`}
31+
/>
32+
<p
33+
className={`${isActive ? "base-bold" : "base-medium"} max-lg:hidden`}
34+
>
35+
{item.label}
36+
</p>
37+
</Link>
38+
);
39+
})}
40+
</div>
41+
42+
<div className="flex flex-col gap-3">
43+
<Link href="/sign-in" className="flex">
44+
<Button className="small-medium btn-secondary min-h-[41px] w-full rounded-lg px-4 py-3 shadow-none">
45+
<Image
46+
src="assets/icons/account.svg"
47+
alt="login"
48+
width={20}
49+
height={20}
50+
className="invert-colors lg:hidden"
51+
/>
52+
<span className="primary-text-gradient max-lg:hidden">Log In</span>
53+
</Button>
54+
</Link>
55+
56+
<Link href="/sign-up" className="flex">
57+
<Button className="small-medium light-border-2 btn-tertiary min-h-[41px] w-full rounded-lg px-4 py-3 shadow-none text-dark400_light900">
58+
<Image
59+
src="assets/icons/sign-up.svg"
60+
alt="sign up"
61+
width={20}
62+
height={20}
63+
className="invert-colors lg:hidden"
64+
/>
65+
<span className="max-lg:hidden">Sign up</span>
66+
</Button>
67+
</Link>
68+
</div>
69+
</section>
70+
);
71+
};
72+
73+
export default LeftSidebar;

components/shared/RenderTag.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Link from "next/link";
2+
import React from "react";
3+
import { Badge } from "@/components/ui/badge";
4+
5+
interface Props {
6+
_id: number;
7+
name: string;
8+
totalQuestions?: number;
9+
showCount?: boolean;
10+
}
11+
12+
const RenderTag = ({ _id, name, totalQuestions, showCount }: Props) => {
13+
return (
14+
<Link href={`/tags/${_id}`} className="flex justify-between gap-2">
15+
<Badge className="subtle-medium background-light800_dark300 text-light400_light500 rounded-md border-none px-4 py-2 uppercase">
16+
{name}
17+
</Badge>
18+
{showCount && (
19+
<p className="small-medium text-dark500_light700">{totalQuestions}</p>
20+
)}
21+
</Link>
22+
);
23+
};
24+
25+
export default RenderTag;

components/shared/RightSidebar.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Image from "next/image";
2+
import Link from "next/link";
3+
import { title } from "process";
4+
import React from "react";
5+
import RenderTag from "./RenderTag";
6+
7+
const RightSidebar = () => {
8+
const hotQuestions = [
9+
{ _id: 1, title: "How do I use express as a custom server in NextJS?" },
10+
{ _id: 2, title: "Cascading Deletes in SQLAlchemy?" },
11+
{ _id: 3, title: "How to perfectly Center a Div with Tailwind CSS?" },
12+
{
13+
_id: 4,
14+
title:
15+
"Best practices for data fetching in a Next.js application with Server-Side Rendering (SSR)?",
16+
},
17+
{ _id: 5, title: "Redux Toolkit Not Updating State as Expected" },
18+
];
19+
20+
const popularTags = [
21+
{
22+
_id: 1,
23+
name: "javascript",
24+
totalQuestions: 5,
25+
},
26+
{
27+
_id: 2,
28+
name: "react",
29+
totalQuestions: 4,
30+
},
31+
{
32+
_id: 3,
33+
name: "next",
34+
totalQuestions: 6,
35+
},
36+
{
37+
_id: 4,
38+
name: "vue",
39+
totalQuestions: 2,
40+
},
41+
{
42+
_id: 5,
43+
name: "redux",
44+
totalQuestions: 10,
45+
},
46+
];
47+
48+
return (
49+
<section
50+
className="background-light900_dark200 light-border custom-scrollbar sticky right-0 top-0 flex h-screen
51+
w-[350px] flex-col overflow-y-auto border-r p-6 pt-36 shadow-light-300 dark:shadow-none max-xl:hidden"
52+
>
53+
<div>
54+
<h3 className="h3-bold text-dark200_light900">Top Questions</h3>
55+
<div className="mt-7 flex w-full flex-col gap-[30px]">
56+
{hotQuestions.map((questions) => (
57+
<Link
58+
href={`/questions/${questions._id}`}
59+
key={questions._id}
60+
className="flex cursor-pointer items-center justify-between gap-7"
61+
>
62+
<p className="body-medium text-dark500_light700">
63+
{questions.title}
64+
</p>
65+
<Image
66+
src={`/assets/icons/chevron-right.svg`}
67+
alt="chevron right"
68+
width={20}
69+
height={20}
70+
className="invert-colors"
71+
/>
72+
</Link>
73+
))}
74+
</div>
75+
</div>
76+
<div className="mt-16">
77+
<h3 className="h3-bold text-dark200_light900">Popular Tags</h3>
78+
<div className="mt-7 flex flex-col gap-4">
79+
{popularTags.map((tag) => (
80+
<RenderTag
81+
key={tag._id}
82+
_id={tag._id}
83+
name={tag.name}
84+
totalQuestions={tag.totalQuestions}
85+
showCount
86+
/>
87+
))}
88+
</div>
89+
</div>
90+
</section>
91+
);
92+
};
93+
94+
export default RightSidebar;
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
"use client";
2+
3+
import {
4+
Sheet,
5+
SheetClose,
6+
SheetContent,
7+
SheetDescription,
8+
SheetHeader,
9+
SheetTitle,
10+
SheetTrigger,
11+
} from "@/components/ui/sheet";
12+
import Image from "next/image";
13+
import Link from "next/link";
14+
import { SignedOut } from "@clerk/nextjs";
15+
import { Button } from "@/components/ui/button";
16+
import { sidebarLinks } from "@/constants";
17+
import { usePathname } from "next/navigation";
18+
19+
const NavContent = () => {
20+
const pathName = usePathname();
21+
return (
22+
<section className="flex h-full flex-col gap-6 pt-16">
23+
{sidebarLinks.map((item) => {
24+
const isActive =
25+
(pathName.includes(item.route) && item.route.length > 1) ||
26+
pathName === item.route;
27+
return (
28+
<SheetClose asChild key={item.route}>
29+
<Link
30+
href={item.route}
31+
className={`${isActive ? "primary-gradient rounded-lg text-light-900" : "text-dark300_light900"} flex items-center justify-start gap-4 bg-transparent p-4`}
32+
>
33+
<Image
34+
src={item.imgURL}
35+
alt={item.label}
36+
width={20}
37+
height={20}
38+
className={`${isActive ? "" : "invert-colors"}`}
39+
/>
40+
<p className={`${isActive ? "base-bold" : "base-medium"}`}>
41+
{item.label}
42+
</p>
43+
</Link>
44+
</SheetClose>
45+
);
46+
})}
47+
</section>
48+
);
49+
};
50+
51+
const MobileNav = () => {
52+
return (
53+
<Sheet>
54+
<SheetTrigger asChild>
55+
<Image
56+
src="/assets/icons/hamburger.svg"
57+
width={36}
58+
height={36}
59+
alt="Menu"
60+
className="invert-colors sm:hidden"
61+
/>
62+
</SheetTrigger>
63+
<SheetContent
64+
side={"left"}
65+
className="background-light900_dark200 border-none"
66+
>
67+
<Link href="/" className="flex">
68+
<Image
69+
src="/assets/images/site-logo.svg"
70+
width={23}
71+
height={23}
72+
alt="DevFlow"
73+
/>
74+
<p className="h2-bold text-dark100_light900 font-spaceGrotesk">
75+
Dev<span className="text-primary-500">Overflow</span>
76+
</p>
77+
</Link>
78+
<div>
79+
<SheetClose asChild>
80+
<NavContent />
81+
</SheetClose>
82+
83+
<SignedOut>
84+
<div className="flex flex-col gap-3">
85+
<SheetClose asChild>
86+
<Link href="/sign-in" className="flex">
87+
<Button className="small-medium btn-secondary min-h-[41px] w-full rounded-lg px-4 py-3 shadow-none">
88+
<span className="primary-text-gradient">Log In</span>
89+
</Button>
90+
</Link>
91+
</SheetClose>
92+
93+
<SheetClose asChild>
94+
<Link href="/sign-up" className="flex">
95+
<Button className="small-medium light-border-2 btn-tertiary min-h-[41px] w-full rounded-lg px-4 py-3 shadow-none text-dark400_light900">
96+
Sign Up
97+
</Button>
98+
</Link>
99+
</SheetClose>
100+
</div>
101+
</SignedOut>
102+
</div>
103+
</SheetContent>
104+
</Sheet>
105+
);
106+
};
107+
108+
export default MobileNav;

0 commit comments

Comments
 (0)