);
}
export const defaultTestimonials: Testimonial[] = [
{
name: "Paweł Michalski",
title: "",
company: "VC Leaders",
country: "Poland",
image: "/stories/pawel.jpeg",
content:
"Invoice reconciliation used to take a full day each month and was always stressful. With Midday, that work is mostly gone and we finally have a clear financial overview.",
fullContent:
"Company\nVC Leaders is an educational platform helping venture capitalists build better VC firms.\n\nChallenge\nMonthly invoice reconciliation was slow and painful. Missing invoices, manual checks, and no time left to properly categorize or analyze spending. The process regularly took more than a full day.\n\nImpact\nMidday reduced invoice reconciliation time by 1–2 man-days per month and made financial visibility much clearer through dashboards.\n\nFavorite features\nClear financial overview, accounts payable tracking, invoice reconciliation, and a clean, intuitive interface.",
},
{
name: "Facu Montanaro",
title: "",
company: "Kundo Studio",
country: "Argentina",
image: "/stories/facu.jpeg",
content:
"Managing invoicing, projects, and finances across tools slowed my daily work. Midday brought everything into one place and made my workflow much simpler.",
fullContent:
"Company\nKundo Studio helps startups and founders with fundraising, product launches, and growth through design and meaningful experiences.\n\nChallenge\nManaging invoicing, projects, and finances across multiple tools made daily work slower and more complex. Existing tools felt fragmented and hard to use.\n\nImpact\nMidday centralized invoicing, time tracking, and project information into one place, significantly simplifying day-to-day operations.\n\nFavorite features\nInvoicing and time tracking. Both became core parts of Facu's daily workflow and replaced multiple separate tools.",
},
{
name: "Richard Poelderl",
title: "",
company: "Conduct",
country: "Germany",
image: "/stories/richard.jpeg",
content:
"My previous accounting setup was fragmented and didn't support my bank. Midday made invoicing easier and sharing clean data with my tax advisor straightforward.",
fullContent:
"Company\nRichard works with companies that want to focus product development on building great products while outsourcing growth and marketing execution.\n\nChallenge\nHis accounting tool didn't support his bank, required manual formatting of exports, and forced him to juggle multiple financial tools.\n\nImpact\nMidday replaced bank invoicing and made it easier to work with his tax advisor by exporting clean CSV files that integrate with accounting software. This significantly reduced friction while keeping control in one system.\n\nFavorite features\nInvoicing, CSV exports for tax advisors, and bank sync to track subscriptions and expenses.",
},
{
name: "Guy Solan",
title: "",
company: "Thetis Medical",
country: "United Kingdom",
image: "/stories/guy.jpeg",
content:
"Without Midday, I had no real visibility into our cash and relied entirely on my accountant. It gave me clarity without having to learn complex accounting tools.",
fullContent:
"Company\nThetis Medical is a medical device company.\n\nChallenge\nWithout Midday, I had no real visibility into our cash and relied entirely on my accountant.\n\nImpact\nMidday gave me clarity without having to learn complex accounting tools.\n\nFavorite features\nFinancial visibility and cash flow tracking.",
video:
"https://customer-oh6t55xltlgrfayh.cloudflarestream.com/5b86803383964d52ee6834fd289f4f4e/manifest/video.m3u8",
videoPoster: "https://cdn.midday.ai/guy-cover.png",
},
];
export function TestimonialsSection({
testimonials = defaultTestimonials,
title = "Built alongside our users",
subtitle = "For founders and small teams who run their business every week, every feature earns its place in the workflow.",
showStars = true,
customHeader,
}: TestimonialsSectionProps) {
const scrollContainerRef = useRef(null);
const lastDragDistance = useRef(0);
const pointerDownRef = useRef<{ time: number; x: number } | null>(null);
const [shouldBlockClick, setShouldBlockClick] = useState(false);
// Scroll to center card on mount
useEffect(() => {
if (scrollContainerRef.current) {
const centerIndex = Math.floor(testimonials.length / 2);
const cardWidth =
scrollContainerRef.current.scrollWidth / testimonials.length;
scrollContainerRef.current.scrollLeft = centerIndex * cardWidth;
}
}, [testimonials.length]);
return (
{customHeader ? (
customHeader
) : (
{title}
{subtitle}
{showStars && (
)}
)}
{/* Desktop Testimonials Grid */}
{testimonials.map((testimonial, index) => {
const getRotation = () => {
if (index === 0) return -1;
if (index === 1) return 1;
if (index === 2) return 2;
if (index === 3) return -2;
return 0;
};
// Simple modal for video testimonials (no morphing)
if (testimonial.video) {
return (
);
}
// Morphing dialog for regular testimonials
return (
{testimonials.map((testimonial, index) => {
// Calculate rotation based on position relative to center
const centerIndex = Math.floor(testimonials.length / 2);
const offset = index - centerIndex;
let rotation = 0;
if (index === 0)
rotation = 0; // No rotation for first card
else if (offset === -1) rotation = -1;
else if (offset === 1) rotation = 1;
else if (offset === -2) rotation = -2;
else if (offset === 2) rotation = 2;
// Simple modal for video testimonials (no morphing)
if (testimonial.video) {
return (
);
}
return (
{
// Block click if there was a drag or if we're blocking clicks
if (
shouldBlockClick ||
lastDragDistance.current > 15
) {
e.preventDefault();
e.stopPropagation();
}
}}
onPointerDown={(e) => {
pointerDownRef.current = {
time: Date.now(),
x: e.clientX,
};
}}
onPointerUp={(e) => {
if (pointerDownRef.current) {
const timeDiff =
Date.now() - pointerDownRef.current.time;
const distance = Math.abs(
e.clientX - pointerDownRef.current.x,
);
// Block if it was a long press or significant movement
if (timeDiff > 200 || distance > 15) {
setShouldBlockClick(true);
setTimeout(() => {
setShouldBlockClick(false);
}, 300);
}
pointerDownRef.current = null;
}
}}
>