Skip to content

Commit 205195b

Browse files
committed
fix: correct Product submenu structure and z-index
- Fix submenu hierarchy: - Main categories (Principles, Guidelines, Resources) are unindented - Sub-pages (UX Patterns, Visual Patterns, Workflow & Rituals) are indented under Guidelines - Remove icons from sub-pages in submenu - Implement nested submenu structure: - Guidelines has its own submenu with indented items - Proper hover states for both desktop and mobile - Smooth animations for nested dropdowns - Fix z-index layering: - Main submenu: z-[60] (above page content) - Guidelines submenu: z-[70] (above main submenu) - Ensures submenu appears above fixed page elements - Clean up unused imports: - Remove MousePointer, Eye, Workflow icons from Header imports - Keep only necessary ChevronDown icon for dropdowns - Enhanced mobile navigation: - Nested accordion structure for mobile - Proper indentation and visual hierarchy - Consistent state management across all menu levels
1 parent 1648c61 commit 205195b

File tree

1 file changed

+142
-34
lines changed

1 file changed

+142
-34
lines changed

src/components/layout/Header.tsx

Lines changed: 142 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState } from 'react';
44
import { motion, AnimatePresence } from 'framer-motion';
5-
import { Menu, X, BookOpen, Award, Code, ChevronDown, MousePointer, Eye, Workflow } from 'lucide-react';
5+
import { Menu, X, BookOpen, Award, Code, ChevronDown } from 'lucide-react';
66
import { useLanguage } from '@/contexts/LanguageContext';
77
import { useRouter } from 'next/navigation';
88
import LanguageSwitcher from './LanguageSwitcher';
@@ -11,6 +11,7 @@ import Logo from './Logo';
1111
const Header = () => {
1212
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
1313
const [isProductSubmenuOpen, setIsProductSubmenuOpen] = useState(false);
14+
const [isGuidelinesSubmenuOpen, setIsGuidelinesSubmenuOpen] = useState(false);
1415
const { t } = useLanguage();
1516
const router = useRouter();
1617

@@ -24,11 +25,17 @@ const Header = () => {
2425
hasSubmenu: true,
2526
submenuItems: [
2627
{ name: t('product.sections.principles'), href: '/product#principles' },
27-
{ name: t('product.sections.guidelines'), href: '/product#guidelines' },
28+
{
29+
name: t('product.sections.guidelines'),
30+
href: '/product#guidelines',
31+
hasSubmenu: true,
32+
submenuItems: [
33+
{ name: 'UX Patterns', href: '/product/UX-patterns' },
34+
{ name: 'Visual Patterns', href: '/product/visual-patterns' },
35+
{ name: 'Workflow & Rituals', href: '/product/workflow-rituals' },
36+
]
37+
},
2838
{ name: t('product.sections.resources'), href: '/product#resources' },
29-
{ name: 'UX Patterns', href: '/product/UX-patterns', icon: MousePointer },
30-
{ name: 'Visual Patterns', href: '/product/visual-patterns', icon: Eye },
31-
{ name: 'Workflow & Rituals', href: '/product/workflow-rituals', icon: Workflow },
3239
]
3340
},
3441
];
@@ -79,24 +86,78 @@ const Header = () => {
7986
animate={{ opacity: 1, y: 0 }}
8087
exit={{ opacity: 0, y: 10 }}
8188
transition={{ duration: 0.2 }}
82-
className="absolute top-full left-0 mt-2 w-64 bg-background/98 backdrop-blur-sm border border-border rounded-lg shadow-xl z-50"
89+
className="absolute top-full left-0 mt-2 w-64 bg-background/98 backdrop-blur-sm border border-border rounded-lg shadow-xl z-[60]"
8390
>
8491
<div className="py-2">
8592
{item.submenuItems?.map((subItem, subIndex) => (
86-
<motion.button
87-
key={subItem.name}
88-
whileHover={{ x: 4 }}
89-
onClick={() => {
90-
router.push(subItem.href);
91-
setIsProductSubmenuOpen(false);
92-
}}
93-
className="w-full flex items-center space-x-3 px-4 py-3 text-left hover:bg-accent transition-colors"
94-
>
95-
{subItem.icon && <subItem.icon className="w-4 h-4 text-muted-foreground" />}
96-
<span className={`font-medium ${subItem.icon ? 'text-muted-foreground' : 'text-foreground pl-7'}`}>
97-
{subItem.name}
98-
</span>
99-
</motion.button>
93+
<div key={subItem.name} className="relative">
94+
{subItem.hasSubmenu ? (
95+
<div
96+
onMouseEnter={() => setIsGuidelinesSubmenuOpen(true)}
97+
onMouseLeave={() => setIsGuidelinesSubmenuOpen(false)}
98+
className="relative"
99+
>
100+
<motion.button
101+
whileHover={{ x: 4 }}
102+
onClick={() => {
103+
router.push(subItem.href);
104+
setIsProductSubmenuOpen(false);
105+
}}
106+
className="w-full flex items-center justify-between px-4 py-3 text-left hover:bg-accent transition-colors"
107+
>
108+
<span className="font-medium text-foreground">
109+
{subItem.name}
110+
</span>
111+
<ChevronDown className={`w-4 h-4 transition-transform duration-200 ${isGuidelinesSubmenuOpen ? 'rotate-180' : ''}`} />
112+
</motion.button>
113+
114+
{/* Guidelines Submenu */}
115+
<AnimatePresence>
116+
{isGuidelinesSubmenuOpen && (
117+
<motion.div
118+
initial={{ opacity: 0, x: 10 }}
119+
animate={{ opacity: 1, x: 0 }}
120+
exit={{ opacity: 0, x: 10 }}
121+
transition={{ duration: 0.2 }}
122+
className="absolute top-0 left-full ml-2 w-56 bg-background/98 backdrop-blur-sm border border-border rounded-lg shadow-xl z-[70]"
123+
>
124+
<div className="py-2">
125+
{subItem.submenuItems?.map((guidelineItem, guidelineIndex) => (
126+
<motion.button
127+
key={guidelineItem.name}
128+
whileHover={{ x: 4 }}
129+
onClick={() => {
130+
router.push(guidelineItem.href);
131+
setIsProductSubmenuOpen(false);
132+
setIsGuidelinesSubmenuOpen(false);
133+
}}
134+
className="w-full flex items-center px-4 py-3 text-left hover:bg-accent transition-colors"
135+
>
136+
<span className="font-medium text-muted-foreground pl-4">
137+
{guidelineItem.name}
138+
</span>
139+
</motion.button>
140+
))}
141+
</div>
142+
</motion.div>
143+
)}
144+
</AnimatePresence>
145+
</div>
146+
) : (
147+
<motion.button
148+
whileHover={{ x: 4 }}
149+
onClick={() => {
150+
router.push(subItem.href);
151+
setIsProductSubmenuOpen(false);
152+
}}
153+
className="w-full flex items-center px-4 py-3 text-left hover:bg-accent transition-colors"
154+
>
155+
<span className="font-medium text-foreground">
156+
{subItem.name}
157+
</span>
158+
</motion.button>
159+
)}
160+
</div>
100161
))}
101162
</div>
102163
</motion.div>
@@ -174,20 +235,67 @@ const Header = () => {
174235
>
175236
<div className="ml-6 space-y-1">
176237
{item.submenuItems?.map((subItem, subIndex) => (
177-
<motion.button
178-
key={subItem.name}
179-
onClick={() => {
180-
setIsMobileMenuOpen(false);
181-
setIsProductSubmenuOpen(false);
182-
router.push(subItem.href);
183-
}}
184-
className="flex items-center space-x-3 px-4 py-2 rounded-lg hover:bg-accent transition-colors cursor-pointer w-full text-left"
185-
>
186-
{subItem.icon && <subItem.icon className="w-4 h-4 text-muted-foreground" />}
187-
<span className={`font-medium text-sm ${subItem.icon ? 'text-muted-foreground' : 'text-foreground'}`}>
188-
{subItem.name}
189-
</span>
190-
</motion.button>
238+
<div key={subItem.name}>
239+
{subItem.hasSubmenu ? (
240+
<div>
241+
<motion.button
242+
onClick={() => {
243+
setIsGuidelinesSubmenuOpen(!isGuidelinesSubmenuOpen);
244+
}}
245+
className="flex items-center justify-between w-full px-4 py-2 rounded-lg hover:bg-accent transition-colors cursor-pointer text-left"
246+
>
247+
<span className="font-medium text-sm text-foreground">
248+
{subItem.name}
249+
</span>
250+
<ChevronDown className={`w-4 h-4 transition-transform duration-200 ${isGuidelinesSubmenuOpen ? 'rotate-180' : ''}`} />
251+
</motion.button>
252+
253+
<AnimatePresence>
254+
{isGuidelinesSubmenuOpen && (
255+
<motion.div
256+
initial={{ opacity: 0, height: 0 }}
257+
animate={{ opacity: 1, height: 'auto' }}
258+
exit={{ opacity: 0, height: 0 }}
259+
transition={{ duration: 0.2 }}
260+
className="overflow-hidden"
261+
>
262+
<div className="ml-6 space-y-1">
263+
{subItem.submenuItems?.map((guidelineItem, guidelineIndex) => (
264+
<motion.button
265+
key={guidelineItem.name}
266+
onClick={() => {
267+
setIsMobileMenuOpen(false);
268+
setIsProductSubmenuOpen(false);
269+
setIsGuidelinesSubmenuOpen(false);
270+
router.push(guidelineItem.href);
271+
}}
272+
className="flex items-center px-4 py-2 rounded-lg hover:bg-accent transition-colors cursor-pointer w-full text-left"
273+
>
274+
<span className="font-medium text-sm text-muted-foreground">
275+
{guidelineItem.name}
276+
</span>
277+
</motion.button>
278+
))}
279+
</div>
280+
</motion.div>
281+
)}
282+
</AnimatePresence>
283+
</div>
284+
) : (
285+
<motion.button
286+
onClick={() => {
287+
setIsMobileMenuOpen(false);
288+
setIsProductSubmenuOpen(false);
289+
router.push(subItem.href);
290+
}}
291+
className="flex items-center px-4 py-2 rounded-lg hover:bg-accent transition-colors cursor-pointer w-full text-left"
292+
>
293+
<span className="font-medium text-sm text-foreground">
294+
{subItem.name}
295+
</span>
296+
</motion.button>
297+
)}
298+
</div>
191299
))}
192300
</div>
193301
</motion.div>

0 commit comments

Comments
 (0)