Profile Settings Card
A profile settings with links card often used as popover on avatar.
Installations
Install lucide-react, clsx, and tailwind-merge to use avatar component.
npm install lucide-react clsx tailwind-merge
Add the following function in lib/utils
import clsx, { type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cx(...args: ClassValue[]) {
return twMerge(clsx(...args));
}
Copy paste the component
import {
LinkIcon,
LogOutIcon,
MoonIcon,
SettingsIcon,
UserIcon,
} from "lucide-react";
import { cx } from "@/lib/utils";
import Link from "next/link";
const profileLinks = [
{ icon: <UserIcon width={18} />, value: "Profile", link: "#" },
{ icon: <SettingsIcon width={18} />, value: "Account Settings", link: "#" },
{ icon: <LinkIcon width={18} />, value: "Integration", link: "#" },
{ icon: <MoonIcon width={18} />, value: "Dark Mode", link: "#" },
];
export default function ProfilePopoverContent({
className,
}: {
className?: string;
}) {
return (
<div
className={cx(
"border border-gray-200 dark:border-gray-800 py-2 w-3xs bg-white dark:bg-[#090E1A] rounded-lg text-sm",
className
)}
>
{profileLinks.map((link) => {
if (link.value == "Dark Mode") {
return (
<div
key="dark-mode-toggle"
className="flex items-center justify-between pr-3 hover:bg-gray-100 dark:hover:bg-gray-600"
>
<NavLink
key={link.value}
link={{
icon: link.icon,
value: link.value,
link: link.link,
}}
className="hover:bg-gray-100 dark:hover:bg-gray-600 p-1 dark:text-gray-100"
/>
<SwitchRoot>
<SwitchThumb />
</SwitchRoot>
</div>
);
}
return (
<NavLink
key={link.value}
link={{
icon: link.icon,
value: link.value,
link: link.link,
}}
className="hover:bg-gray-100 dark:hover:bg-gray-600 p-1 dark:text-gray-100"
/>
);
})}
<hr className="text-gray-200 dark:text-gray-800 my-3" />
<NavLink
key="signout"
link={{
icon: <LogOutIcon width={18} />,
value: "Sign Out",
link: "#",
}}
className="hover:bg-gray-100 dark:hover:bg-gray-600 p-1 dark:text-gray-100"
/>
</div>
);
}
function NavLink({
link,
className,
}: {
link: { icon: ReactElement; link: string; active?: boolean; value: string };
className?: string;
}) {
return (
<Link
href={link.link}
className={cx(
// base
"flex gap-2 items-center",
// active
link.active
? "text-gray-950 dark:text-gray-50"
: "text-gray-500 dark:text-gray-400",
// class props
className
)}
>
<span
className={`p-1 rounded-lg ${
link.active ? "text-white bg-blue-600" : ""
}`}
>
{link.icon}
</span>{" "}
{link.value}
</Link>
);
}
Usage
import ProfilePopoverContent from "@/library/blocks/profileCard";
export default function ProfileSettingsCard() {
return (
<CardRoot className="not-prose">
<ProfilePopoverContent />
</CardRoot>
);
}
Next: Top Products Card
Found a bug? Report here.