waveform/components/friends/FriendsHeader.tsx

117 lines
4 KiB
TypeScript

/**
* @file components/friends/FriendsHeader.tsx
* @description Renders a responsive sub-header with tabs for navigating between all friends, pending requests, and adding a friend.
*/
"use client";
import { Users, Clock } from "lucide-react";
import { ActionButton } from "../ui/ActionButton";
/**
* Available tab types for the friends navigation view.
*
* @type {TabType}
*/
export type TabType = "all" | "pending" | "add";
/**
* Properties for the FriendsHeader component.
*
* @interface FriendsHeaderProps
* @property {TabType} activeTab - The currently active friends tab identifier.
* @property {(tab: TabType) => void} setActiveTab - Callback function to update the active friends tab.
* @property {number} [allCount=0] - The total number of friends.
* @property {number} [pendingCount=0] - The number of pending friend requests.
*/
interface FriendsHeaderProps {
activeTab: TabType;
setActiveTab: (tab: TabType) => void;
allCount?: number;
pendingCount?: number;
}
/**
* Renders a responsive sub-header with tabs for navigating between all friends, pending requests, and adding a friend.
*
* @param {FriendsHeaderProps} props - The component props.
* @param {TabType} props.activeTab - The currently active tab.
* @param {(tab: TabType) => void} props.setActiveTab - Function to change the active tab.
* @param {number} [props.allCount=0] - Total count of all friends.
* @param {number} [props.pendingCount=0] - Count of pending friend requests.
* @returns {JSX.Element} The rendered friends navigation header component.
*/
export function FriendsHeader({
activeTab,
setActiveTab,
allCount = 0,
pendingCount = 0,
}: FriendsHeaderProps) {
return (
<nav
aria-label="Friends navigation"
className="flex items-center gap-2 h-12"
>
{/* Title / Icon Indicator */}
<div className="flex items-center gap-2.5 pr-3 border-r border-muted/20 text-foreground font-bold tracking-wide">
<Users className="w-5 h-5 text-accent" />
<span className="hidden sm:inline text-sm">Friends</span>
</div>
{/* Tabs Container */}
<div className="flex items-center gap-1.5 text-sm font-medium">
{/* All Friends Tab */}
<button
type="button"
onClick={() => setActiveTab("all")}
className={`px-3 py-1.5 rounded-lg transition-all duration-150 cursor-pointer flex items-center gap-2 active:scale-95 ${
activeTab === "all"
? "bg-surface text-foreground shadow-sm font-semibold"
: "text-muted hover:bg-surface/50 hover:text-foreground"
}`}
>
<span>All</span>
<span
className={`text-xs px-1.5 py-0.5 rounded-md ${
activeTab === "all"
? "bg-muted/20 text-foreground"
: "bg-surface text-muted"
}`}
>
{allCount}
</span>
</button>
{/* Pending Requests Tab */}
<button
type="button"
onClick={() => setActiveTab("pending")}
className={`px-3 py-1.5 rounded-lg transition-all duration-150 flex items-center gap-2 cursor-pointer active:scale-95 ${
activeTab === "pending"
? "bg-surface text-foreground shadow-sm font-semibold"
: "text-muted hover:bg-surface/50 hover:text-foreground"
}`}
>
<Clock className="w-4 h-4 hidden sm:block opacity-70" />
<span>Pending</span>
{pendingCount > 0 && (
<span className="bg-destructive text-foreground text-xs font-bold px-1.5 py-0.5 rounded-full animate-pulse">
{pendingCount}
</span>
)}
</button>
{/* Add Friend Tab */}
<ActionButton
type="button"
variant="primary"
onClick={() => setActiveTab("add")}
size="sm"
>
<span className="inline md:hidden">Add Friend</span>
<span className="hidden md:inline">Add</span>
</ActionButton>
</div>
</nav>
);
}