Follow
EngagementAdd follow/unfollow functionality to user profiles.
Demo
564 followers
Install via CLI
npx feature101@latest add followFiles
components/FollowButton.ts
"use client";
import { memo } from "react";
import { useFollow } from "../follow.hooks";
import type { FollowButtonProps } from "../follow.types";
const FollowButton = memo(
({
currentUserId,
targetUserId,
initialIsFollowing,
initialFollowerCount,
showCount = true,
className = "",
onFollowChange,
}: FollowButtonProps) => {
const { isFollowing, followerCount, isLoading, error, toggleFollow } =
useFollow({
currentUserId,
targetUserId,
initialIsFollowing,
initialFollowerCount,
});
const handleClick = async () => {
await toggleFollow();
onFollowChange?.(!isFollowing);
};
// Don't show button if trying to follow yourself
if (currentUserId === targetUserId) {
return null;
}
return (
<div className={`inline-flex items-center gap-2 ${className}`}>
<button
onClick={handleClick}
disabled={isLoading}
className={`
px-4 py-2 rounded-lg font-medium transition-all
min-w-25 h-10 flex items-center justify-center
${
isFollowing
? "bg-gray-200 text-gray-800 hover:bg-gray-300"
: "bg-blue-500 text-white hover:bg-blue-600"
}
disabled:opacity-50
`}
aria-label={isFollowing ? "Unfollow" : "Follow"}
>
{isLoading ? (
<svg
className="animate-spin h-5 w-5 mx-auto"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
) : isFollowing ? (
"Following"
) : (
"Follow"
)}
</button>
{showCount && (
<span className="text-sm text-gray-600">
{followerCount} {followerCount === 1 ? "follower" : "followers"}
</span>
)}
{error && <span className="text-xs text-red-500">{error}</span>}
</div>
);
},
);
FollowButton.displayName = "FollowButton";
export default FollowButton;