-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathTabNavigation.tsx
More file actions
79 lines (71 loc) · 2.26 KB
/
TabNavigation.tsx
File metadata and controls
79 lines (71 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import React, { useEffect, useRef, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
interface Tab {
id: string;
label: string;
}
interface TabNavigationProps {
tabs: Tab[];
className?: string;
}
/**
* A reusable tab navigation component that handles routing based on tab selection
* with a smooth sliding animation effect
*/
export function TabNavigation({ tabs, className = "" }: TabNavigationProps) {
const navigate = useNavigate();
const location = useLocation();
const tabsRef = useRef<(HTMLButtonElement | null)[]>([]);
const [underlineStyle, setUnderlineStyle] = useState({ left: 0, width: 0 });
// Helper function to check if a tab is active
function isTabActive(tabId: string) {
const pathParts = location.pathname.split("/");
return pathParts.includes(tabId);
}
// Update the underline position when location changes
useEffect(() => {
const activeIndex = tabs.findIndex((tab) => {
const pathParts = location.pathname.split("/");
return pathParts.includes(tab.id);
});
if (activeIndex !== -1) {
const currentTab = tabsRef.current[activeIndex];
if (currentTab) {
setUnderlineStyle({
left: currentTab.offsetLeft,
width: currentTab.offsetWidth,
});
}
}
}, [location.pathname, tabs]);
return (
<div className={`mx-6 flex border-b border-fp-dec-00 text-fp-p text-14 relative ${className}`}>
<nav className="flex relative" aria-label="Tabs">
{/* Animated underline */}
<div
className="absolute bottom-0 h-0.5 bg-fp-a-03 transition-all duration-300"
style={{
left: `${underlineStyle.left}px`,
width: `${underlineStyle.width}px`,
}}
/>
{tabs.map((tab, index) => (
<button
key={tab.id}
ref={(el) => {
tabsRef.current[index] = el;
}}
type="button"
onClick={() => navigate(tab.id)}
className={`
px-4 py-2 select-none hover:text-fp-a-03 transition-colors duration-200
${isTabActive(tab.id) ? "text-fp-a-03" : ""}
`}
>
{tab.label}
</button>
))}
</nav>
</div>
);
}