Skip to content

Commit 5a1bfab

Browse files
committed
updated dropdown menu
1 parent 5942207 commit 5a1bfab

File tree

4 files changed

+297
-53
lines changed

4 files changed

+297
-53
lines changed

frontend/components.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": false,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "tailwind.config.ts",
8+
"css": "src/styles/globals.css",
9+
"baseColor": "neutral",
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+
"iconLibrary": "lucide"
21+
}

frontend/src/components/Hamburger.tsx

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,80 @@
11
import React from 'react';
2-
import { AnimatePresence, motion, useCycle } from 'framer-motion';
32
import Link from 'next/link';
3+
import {
4+
DropdownMenu,
5+
DropdownMenuContent,
6+
DropdownMenuItem,
7+
DropdownMenuLabel,
8+
DropdownMenuSeparator,
9+
DropdownMenuTrigger,
10+
} from "@/components/ui/dropdown-menu";
411

512
export default function Hamburger() {
6-
const [isOpen, toggleOpen] = useCycle(false, true);
713

814
return (
9-
<button
10-
onClick={() => {
11-
toggleOpen();
12-
}}
13-
>
14-
<svg
15-
className="w-10 h-10"
16-
fill="none"
17-
stroke="currentColor"
18-
viewBox="0 0 24 24"
19-
xmlns="http://www.w3.org/2000/svg"
15+
<DropdownMenu modal={false}>
16+
<DropdownMenuTrigger>
17+
<button className="p-2 rounded-lg transition-all">
18+
<svg
19+
className="w-10 h-10 hover:scale-110 hover:rotate-2 transition-all"
20+
fill="none"
21+
stroke="white"
22+
viewBox="0 0 24 24"
23+
xmlns="http://www.w3.org/2000/svg"
24+
>
25+
<path strokeLinecap="round"
26+
strokeLinejoin="round"
27+
d="M4 6h16M4 12h16m-7 6h7"
28+
/>
29+
</svg>
30+
</button>
31+
</DropdownMenuTrigger>
32+
33+
<DropdownMenuContent
34+
align="end"
35+
className="w-44 bg-[#3977F9] border-none shadow-lg rounded-2xl text-white"
2036
>
21-
<path
22-
strokeLinecap="round"
23-
strokeLinejoin="round"
24-
strokeWidth={2}
25-
d="M4 6h16M4 12h16m-7 6h7"
26-
/>
27-
</svg>
28-
<AnimatePresence>
29-
{isOpen && (
30-
<motion.div
31-
initial={{ opacity: 0, y: -10 }}
32-
animate={{ opacity: 1, y: 0 }}
33-
exit={{ opacity: 0, y: -10 }}
34-
transition={{ duration: 0.2 }}
35-
className="absolute top-16 right-0 bg-[#3977F9] p-4 shadow-lg w-40 rounded-2xl"
37+
38+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
39+
<Link href="/about" className="w-full block">
40+
About Us
41+
</Link>
42+
</DropdownMenuItem>
43+
44+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
45+
<Link href="/events" className="w-full block">
46+
Events
47+
</Link>
48+
</DropdownMenuItem>
49+
50+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
51+
<Link href="/resources" className="w-full block">
52+
Resources
53+
</Link>
54+
</DropdownMenuItem>
55+
56+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
57+
<Link href="/sponsors" className="w-full block">
58+
Sponsors
59+
</Link>
60+
</DropdownMenuItem>
61+
62+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
63+
<Link href="/contact-us" className="w-full block">
64+
Contact Us
65+
</Link>
66+
</DropdownMenuItem>
67+
68+
<DropdownMenuItem className="text-white text-lg py-2 px-4 rounded-2xl focus:bg-white/10 hover:bg-white/10 cursor-pointer">
69+
<a
70+
target="_blank"
71+
href="https://csesoc-merch.square.site/"
72+
className="w-full block"
3673
>
37-
<ul>
38-
<li className="py-2 text-lg">
39-
<Link href={'/about'}>About Us</Link>
40-
</li>
41-
<li className="py-2 text-lg">
42-
<Link href={'/events'}>Events</Link>
43-
</li>
44-
<li className="py-2 text-lg">
45-
<Link href={'/resources'}>Resources</Link>
46-
</li>
47-
<li className="py-2 text-lg">
48-
<Link href={'/sponsors'}>Sponsors</Link>
49-
</li>
50-
<li className="py-2 text-lg">
51-
<Link href={'/contact-us'}>Contact Us</Link>
52-
</li>
53-
<li className="py-2 text-lg">
54-
<a target="_blank" href="https://csesoc-merch.square.site/">Merch Store</a>
55-
</li>
56-
</ul>
57-
</motion.div>
58-
)}
59-
</AnimatePresence>
60-
</button>
74+
Merch
75+
</a>
76+
</DropdownMenuItem>
77+
</DropdownMenuContent>
78+
</DropdownMenu>
6179
);
62-
}
80+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
import * as React from "react"
2+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
3+
import { Check, ChevronRight, Circle } from "lucide-react"
4+
5+
import { cn } from "@/lib/utils"
6+
7+
const DropdownMenu = DropdownMenuPrimitive.Root
8+
9+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
10+
11+
const DropdownMenuGroup = DropdownMenuPrimitive.Group
12+
13+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
14+
15+
const DropdownMenuSub = DropdownMenuPrimitive.Sub
16+
17+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
18+
19+
const DropdownMenuSubTrigger = React.forwardRef<
20+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
21+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
22+
inset?: boolean
23+
}
24+
>(({ className, inset, children, ...props }, ref) => (
25+
<DropdownMenuPrimitive.SubTrigger
26+
ref={ref}
27+
className={cn(
28+
"flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
29+
inset && "pl-8",
30+
className
31+
)}
32+
{...props}
33+
>
34+
{children}
35+
<ChevronRight className="ml-auto" />
36+
</DropdownMenuPrimitive.SubTrigger>
37+
))
38+
DropdownMenuSubTrigger.displayName =
39+
DropdownMenuPrimitive.SubTrigger.displayName
40+
41+
const DropdownMenuSubContent = React.forwardRef<
42+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
43+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
44+
>(({ className, ...props }, ref) => (
45+
<DropdownMenuPrimitive.SubContent
46+
ref={ref}
47+
className={cn(
48+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
49+
className
50+
)}
51+
{...props}
52+
/>
53+
))
54+
DropdownMenuSubContent.displayName =
55+
DropdownMenuPrimitive.SubContent.displayName
56+
57+
const DropdownMenuContent = React.forwardRef<
58+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
59+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
60+
>(({ className, sideOffset = 4, ...props }, ref) => (
61+
<DropdownMenuPrimitive.Portal>
62+
<DropdownMenuPrimitive.Content
63+
ref={ref}
64+
sideOffset={sideOffset}
65+
className={cn(
66+
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
67+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
68+
className
69+
)}
70+
{...props}
71+
/>
72+
</DropdownMenuPrimitive.Portal>
73+
))
74+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
75+
76+
const DropdownMenuItem = React.forwardRef<
77+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
78+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
79+
inset?: boolean
80+
}
81+
>(({ className, inset, ...props }, ref) => (
82+
<DropdownMenuPrimitive.Item
83+
ref={ref}
84+
className={cn(
85+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
86+
inset && "pl-8",
87+
className
88+
)}
89+
{...props}
90+
/>
91+
))
92+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
93+
94+
const DropdownMenuCheckboxItem = React.forwardRef<
95+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
96+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
97+
>(({ className, children, checked, ...props }, ref) => (
98+
<DropdownMenuPrimitive.CheckboxItem
99+
ref={ref}
100+
className={cn(
101+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
102+
className
103+
)}
104+
checked={checked}
105+
{...props}
106+
>
107+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
108+
<DropdownMenuPrimitive.ItemIndicator>
109+
<Check className="h-4 w-4" />
110+
</DropdownMenuPrimitive.ItemIndicator>
111+
</span>
112+
{children}
113+
</DropdownMenuPrimitive.CheckboxItem>
114+
))
115+
DropdownMenuCheckboxItem.displayName =
116+
DropdownMenuPrimitive.CheckboxItem.displayName
117+
118+
const DropdownMenuRadioItem = React.forwardRef<
119+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
120+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
121+
>(({ className, children, ...props }, ref) => (
122+
<DropdownMenuPrimitive.RadioItem
123+
ref={ref}
124+
className={cn(
125+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
126+
className
127+
)}
128+
{...props}
129+
>
130+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
131+
<DropdownMenuPrimitive.ItemIndicator>
132+
<Circle className="h-2 w-2 fill-current" />
133+
</DropdownMenuPrimitive.ItemIndicator>
134+
</span>
135+
{children}
136+
</DropdownMenuPrimitive.RadioItem>
137+
))
138+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
139+
140+
const DropdownMenuLabel = React.forwardRef<
141+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
142+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
143+
inset?: boolean
144+
}
145+
>(({ className, inset, ...props }, ref) => (
146+
<DropdownMenuPrimitive.Label
147+
ref={ref}
148+
className={cn(
149+
"px-2 py-1.5 text-sm font-semibold",
150+
inset && "pl-8",
151+
className
152+
)}
153+
{...props}
154+
/>
155+
))
156+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
157+
158+
const DropdownMenuSeparator = React.forwardRef<
159+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
160+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
161+
>(({ className, ...props }, ref) => (
162+
<DropdownMenuPrimitive.Separator
163+
ref={ref}
164+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
165+
{...props}
166+
/>
167+
))
168+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
169+
170+
const DropdownMenuShortcut = ({
171+
className,
172+
...props
173+
}: React.HTMLAttributes<HTMLSpanElement>) => {
174+
return (
175+
<span
176+
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
177+
{...props}
178+
/>
179+
)
180+
}
181+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
182+
183+
export {
184+
DropdownMenu,
185+
DropdownMenuTrigger,
186+
DropdownMenuContent,
187+
DropdownMenuItem,
188+
DropdownMenuCheckboxItem,
189+
DropdownMenuRadioItem,
190+
DropdownMenuLabel,
191+
DropdownMenuSeparator,
192+
DropdownMenuShortcut,
193+
DropdownMenuGroup,
194+
DropdownMenuPortal,
195+
DropdownMenuSub,
196+
DropdownMenuSubContent,
197+
DropdownMenuSubTrigger,
198+
DropdownMenuRadioGroup,
199+
}

frontend/src/lib/utils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { clsx, type ClassValue } from "clsx"
2+
import { twMerge } from "tailwind-merge"
3+
4+
export function cn(...inputs: ClassValue[]) {
5+
return twMerge(clsx(inputs))
6+
}

0 commit comments

Comments
 (0)