👤 Profile Card

A stylish profile showcase card featuring an avatar image, name, short bio, rating, earnings, hourly rate, and interactive contact/bookmark buttons.
Perfect for freelancers, creators, and professionals to display a quick snapshot of their profile.

img

Natasha Romanoff

I'm a Brand Desinger who focuses on clarity & emotional connection

4.8

Rating

$45k+

Earned

$50/hr

Rate

Install Dependencies

npm i clsx tailwind-merge

Add utility file

lib/utils.ts

import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Code

ProfileCard.tsx

"use client"
import Image from "next/image"
import { IconBookmark,IconMail,IconCarambola,IconRosetteDiscountCheck  } from '@tabler/icons-react';
import { cn } from "@/lib/utils";
interface CardProps {
    name?: string;
    desc?: string;
    rating?: string | number;
    money?: string | number;
    charges?: string | number;
    ctaText?: string;
    imgSrc?:string;
    onContactClick?: () => void;
    onBookmarkClick?: () => void;
    className?:string;
}
export default function ProfileCard({ 
    name = "Natasha Romanoff",
     desc = "I'm a Brand Desinger who focuses on clarity & emotional connection", 
     rating = "4.8",
      money = "45k+", 
      charges = "50/hr", 
      ctaText = "Get In Touch",
      imgSrc = "/cardImg4.png",
      onContactClick,onBookmarkClick,className
     }: CardProps) {
    return (
      
            <div className= {cn("max-w-xs w-2xs max-h-[440px] h-110 rounded-3xl relative overflow-hidden",className)}>
                <Image src={imgSrc} alt="img" height={1000} width={1000} className="absolute inset-0 w-full h-full rounded-3xl object-cover opacity-60 [mask-image:linear-gradient(to_bottom,rgba(255,255,255,1),rgba(255,255,255,0))]"></Image>


                {/* Info */}

                <div className="flex flex-col items-start space-y-1 text-white absolute 
                bottom-0 left-0 p-2 z-80">
                   
                  

                    {/* name & desc */}
                    <div className="z-70" >
                       <h2 className="flex items-center gap-1 text-xl text-[#e7e5e4] mb-1">{name}<IconRosetteDiscountCheck stroke={2} className="h-5 w-5" fill="#4f46e5" /></h2>
                        <p className="text-[#d4d4d4] text-xs tracking-wide mb-2">{desc}</p>
                    </div>

                    {/* workex & cta */}
                     <div className="flex flex-col items-start justify-start w-2xs z-70">
                    {/* WorkEx */}
                    <div className="flex flex-row gap-12">
                        <div className="flex flex-col items-center justify-center ">
                            <h2 className="flex flex-row items-center justify-evenly gap-1 text-sm mt-0 pt-0 mb-0 pb-0"><IconCarambola stroke={2} className="h-4 w-4 " fill="#ea580c" />{rating}</h2>
                            <p className="text-zinc-400 text-xs mt-1 pt-1 mb-1 pb-1">Rating</p>
                        </div>

                        <div className="flex flex-col items-center justify-center ">
                            <h2 className="flex flex-row items-center justify-evenly gap-1 text-sm mt-0 pt-0 mb-0 pb-0">&#x24;{money}</h2>
                            <p className="text-zinc-400 text-xs mt-1 pt-1 mb-1 pb-1">Earned</p>
                        </div>

                        <div className="flex flex-col items-center justify-center ">
                            <h2 className="flex flex-row items-center justify-evenly gap-1 text-sm mt-0 pt-0 mb-0 pb-0">&#x24;{charges}</h2>
                            <p className="text-zinc-400 text-xs mt-1 pt-1 mb-1 pb-1">Rate</p>
                        </div>
                    </div>

                    {/* CTA */}
                    <div className="flex flex-row items-start justify-evenly gap-6 ">
                       
                       <button onClick={onContactClick} className="bg-zinc-300 text-black text-sm px-8 py-2 rounded-3xl flex flex-row items-center justify-evenly gap-1"><IconMail stroke={2} className="h-4 w-4" />{ctaText}</button>


                       <button onClick={onBookmarkClick} className="bg-white/20 backdrop-blur-md text-white text-sm px-3 py-1 rounded-4xl "><IconBookmark stroke={2} /></button>
                    </div>
                    </div>
                    </div>
                    
                </div>
    );
}


Props

PropTypeDefaultDescription
namestring"Natasha Romanoff"The person's name displayed on the card
descstring"I'm a Brand Designer who focuses on clarity & emotional connection"Short bio/description text
ratingstring | number"4.8"Rating score (displayed with star icon)
moneystring | number"45k+"Total earnings amount
chargesstring | number"50/hr"Hourly rate
ctaTextstring"Get In Touch"Text for the contact button
imgSrcstring"/cardImg4.png"Profile image source URL
onContactClick() => voidundefinedCallback function when contact button is clicked
onBookmarkClick() => voidundefinedCallback function when bookmark button is clicked
classNamestringundefinedAdditional CSS classes for customization
Profile Card16