Add InfoCard component to display customizable card layouts

Introduced a reusable InfoCard component with support for a variety of props including images, colors, text, and buttons. This component enhances flexibility and consistency in displaying card-based UI elements across the application.
This commit is contained in:
2025-03-14 11:45:34 +01:00
parent 41464f8bea
commit 991fd0356a

View File

@@ -0,0 +1,142 @@
import React from "react";
import Image from "next/image";
import Link from "next/link";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface CardButton {
text: string;
href: string;
backgroundColor?: string;
textColor?: string;
}
interface InfoCardProps {
imageSrc?: string | null;
imageAlt?: string;
imagePosition?: "left" | "right";
borderColor?: string;
backgroundColor?: string;
boxShadow?: string;
headingText: string;
headingStyle?: React.CSSProperties;
bodyText?: string;
bodyTextColor?: string;
buttonProps?: CardButtonProps;
}
interface CardButtonProps {
text: string;
href: string;
backgroundColor?: string;
textColor?: string;
}
const InfoCard: React.FC<InfoCardProps> = ({
imageSrc,
imageAlt = "Image",
imagePosition = "left",
borderColor = "#ccc",
backgroundColor = "rgba(240,233,214,0.7)",
boxShadow = "0 2px 4px rgba(0, 0, 0, 0.05)",
headingText,
headingStyle = {},
bodyText,
bodyTextColor = "#555",
buttonProps,
}) => {
const imageElement = (
<div className="mb-4 hidden md:mb-0 md:block">
<div
className="flex h-28 w-28 items-center justify-center rounded-full border-2 md:h-32 md:w-32"
style={{ borderColor }}
>
{imageSrc ? (
<div className="relative h-24 w-24 md:h-28 md:w-28">
<Image
src={imageSrc}
alt={imageAlt ?? "Image"}
fill
className="object-contain"
/>
</div>
) : (
<p className="text-center text-sm">{imageAlt ?? "Image"}</p>
)}
</div>
</div>
);
return (
<div
className={cn(
"mb-10 flex flex-col items-center md:items-start md:space-x-6",
imagePosition === "right"
? "md:flex-row-reverse md:space-x-reverse"
: "md:flex-row",
)}
>
{imageElement}
<Card
className="flex-1 relative overflow-hidden p-6"
style={{ backgroundColor, borderColor, boxShadow }}
>
{imageSrc && (
<div
className={cn(
"absolute bottom-0 h-32 w-32 opacity-20 md:hidden",
imagePosition === "right" ? "left-0" : "right-0",
)}
style={{
backgroundImage: `url(${imageSrc})`,
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition:
imagePosition === "right" ? "bottom left" : "bottom right",
}}
/>
)}
<h3
className="mb-2 text-center text-2xl font-bold md:text-left"
style={headingStyle}
>
{headingText}
</h3>
{bodyText && (
<p
className="text-center md:text-left"
style={{ color: bodyTextColor }}
>
{bodyText}
</p>
)}
{buttonProps && (
<div className="mt-4 text-center md:text-left">
<Link
href={buttonProps.href}
target="_blank"
rel="noopener noreferrer"
>
<Button
className="rounded-full"
style={{
backgroundColor: buttonProps.backgroundColor,
color: buttonProps.textColor ?? "white",
}}
>
{buttonProps.text}
</Button>
</Link>
</div>
)}
</Card>
</div>
);
};
export default InfoCard;