import React from "react";
type AboutUsProps = {
heading?: string;
subheading?: string;
description?: string;
points?: string[];
// Theming
bgColor?: string;
textColor?: string;
accentColor?: string;
cardBgColor?: string;
// Layout
maxWidth?: number; // in px
paddingY?: number; // in px
gap?: number; // in px
// Images
imageSrc?: string;
imageAlt?: string;
// Optional CTA
ctaText?: string;
onCtaClick?: () => void;
};
const AboutUs: React.FC<AboutUsProps> = ({
heading = "About Our Local Service",
subheading = "Trusted, friendly, and right around the corner.",
description = "We’re a local business committed to providing reliable, high-quality service to our community. From quick responses to transparent pricing, we’re here to make things simple and stress-free.",
points = [
"Locally owned and operated",
"Fast, reliable service",
"Transparent pricing",
"Fully licensed and insured",
],
bgColor = "#ffffff",
textColor = "#0f172a", // slate-900
accentColor = "#2563eb", // blue-600
cardBgColor = "#f8fafc", // slate-50
maxWidth = 1100,
paddingY = 48,
gap = 24,
imageSrc = "https://via.placeholder.com/640x480?text=Local+Business",
imageAlt = "Our local business team at work",
ctaText,
onCtaClick,
}) => {
// Inline styles to keep it portable and themeable
const styles: Record<string, React.CSSProperties> = {
section: {
backgroundColor: bgColor,
color: textColor,
padding: `min(8vw, ${paddingY}px) 5vw`,
display: "flex",
justifyContent: "center",
},
container: {
width: "100%",
maxWidth,
display: "grid",
gridTemplateColumns: "1fr",
gap,
},
// Responsive: switch to 2 columns on wider screens
// We’ll handle this with a min-width media query below for broader support.
mediaWrapper: {},
card: {
backgroundColor: cardBgColor,
borderRadius: 16,
padding: 24,
boxShadow:
"0 1px 2px rgba(0,0,0,0.06), 0 4px 24px rgba(0,0,0,0.07)",
},
heading: {
fontSize: "clamp(1.5rem, 2.5vw, 2.125rem)",
lineHeight: 1.2,
margin: 0,
fontWeight: 700,
letterSpacing: "-0.01em",
},
subheading: {
fontSize: "clamp(1rem, 1.3vw, 1.125rem)",
opacity: 0.9,
margin: "8px 0 16px 0",
},
description: {
fontSize: "clamp(0.95rem, 1.2vw, 1.05rem)",
lineHeight: 1.7,
margin: "0 0 16px 0",
},
list: {
margin: "12px 0 0 0",
padding: 0,
listStyle: "none",
display: "grid",
gap: 10,
},
listItem: {
display: "flex",
alignItems: "flex-start",
gap: 10,
},
bullet: {
width: 8,
height: 8,
borderRadius: "50%",
backgroundColor: accentColor,
marginTop: 7,
flex: "0 0 auto",
},
ctaRow: {
marginTop: 20,
display: "flex",
gap: 12,
flexWrap: "wrap",
},
cta: {
backgroundColor: accentColor,
color: "#ffffff",
border: 0,
borderRadius: 10,
padding: "12px 16px",
fontWeight: 600,
cursor: "pointer",
transition: "transform 120ms ease, opacity 120ms ease",
},
imageWrap: {
position: "relative",
borderRadius: 16,
overflow: "hidden",
height: "min(60vw, 420px)", // mobile height
},
img: {
width: "100%",
height: "100%",
objectFit: "cover",
display: "block",
},
badgeBar: {
position: "absolute",
left: 12,
bottom: 12,
backgroundColor: "rgba(255,255,255,0.9)",
color: textColor,
borderRadius: 12,
padding: "8px 12px",
display: "flex",
gap: 12,
alignItems: "center",
backdropFilter: "saturate(120%) blur(4px)",
},
badgeDot: {
width: 10,
height: 10,
borderRadius: "50%",
backgroundColor: accentColor,
},
};
// Create a responsive two-column layout at >= 900px
// This small helper injects a style tag once (scoped by data- attribute).
// You can also move this to your global CSS if preferred.
const styleId = "about-us-responsive-css";
if (typeof document !== "undefined" && !document.getElementById(styleId)) {
const style = document.createElement("style");
style.id = styleId;
style.innerHTML = `
[data-about-us] {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 900px) {
[data-about-us] {
grid-template-columns: 1.05fr 0.95fr;
align-items: center;
}
[data-about-us] .about-image {
height: min(34vw, 520px);
}
}
[data-about-us] .cta:hover { transform: translateY(-1px); }
[data-about-us] .cta:active { transform: translateY(0); opacity: 0.9; }
`;
document.head.appendChild(style);
}
return (
<section style={styles.section} aria-label="About us section">
<div style={styles.container} data-about-us>
<div style={styles.card}>
<h2 style={styles.heading}>{heading}</h2>
<p style={styles.subheading}>{subheading}</p>
<p style={styles.description}>{description}</p>
<ul style={styles.list} aria-label="Key points">
{points.map((p, i) => (
<li key={i} style={styles.listItem}>
<span style={styles.bullet} aria-hidden="true" />
<span>{p}</span>
</li>
))}
</ul>
{ctaText && (
<div style={styles.ctaRow}>
<button
type="button"
className="cta"
style={styles.cta}
onClick={onCtaClick}
aria-label={ctaText}
>
{ctaText}
</button>
</div>
)}
</div>
<div className="about-image" style={styles.imageWrap}>
<img
src={imageSrc}
alt={imageAlt}
style={styles.img}
loading="lazy"
/>
<div style={styles.badgeBar} aria-hidden="true">
<span style={styles.badgeDot} />
<span>Serving our neighborhood since 2015</span>
</div>
</div>
</div>
</section>
);
};
export default AboutUs;
