Enhance the visual design with new colors and Islamic-inspired elements

Adds Islamic patterns and color themes to the hero section and feature cards using new UI components and CSS classes.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: acaf01d7-65a7-4fc5-901d-853488e196e8
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/af8dabca-e746-4e53-9c29-d8d4d9cf30f5/0c99a732-a747-4909-ac7a-aedc0fba1b90.jpg
This commit is contained in:
JeffEmmett 2025-05-07 03:37:44 +00:00
parent 6c21fef897
commit fbc3f108b0
5 changed files with 379 additions and 15 deletions

View File

@ -13,26 +13,50 @@ export function FeatureCard({ title, description, icon, color }: FeatureCardProp
bg: "bg-teal-light",
iconBg: "bg-teal",
text: "text-teal",
pattern: "islamic-pattern-teal",
},
purple: {
bg: "bg-purple-light",
iconBg: "bg-purple",
text: "text-purple",
pattern: "islamic-pattern",
},
rose: {
bg: "bg-rose-light",
iconBg: "bg-rose",
text: "text-rose",
pattern: "islamic-pattern-rose",
},
};
return (
<div className={`${colorClasses[color].bg} rounded-lg p-6 text-center`}>
<div className={`w-16 h-16 ${colorClasses[color].iconBg} rounded-full flex items-center justify-center mx-auto mb-4`}>
<i className={`fas ${icon} text-white text-2xl`}></i>
<div className="group relative rounded-lg p-6 text-center transition-all duration-300 hover:shadow-lg overflow-hidden">
<div className={`absolute inset-0 ${colorClasses[color].bg} opacity-40`}></div>
<div className={`absolute inset-0 ${colorClasses[color].pattern} opacity-5 group-hover:opacity-10 transition-opacity duration-300`}></div>
{/* Icon container with geometric border */}
<div className="relative">
<div className={`w-20 h-20 ${colorClasses[color].iconBg} rounded-full flex items-center justify-center mx-auto mb-5 transform transition-transform group-hover:scale-110 duration-300`}>
<i className={`fas ${icon} text-white text-2xl`}></i>
</div>
{/* Decorative elements */}
<div className="absolute top-9 left-1/2 transform -translate-x-1/2 -z-10">
<svg width="120" height="120" viewBox="0 0 120 120" className="absolute top-0 left-0 -mt-10 -ml-10">
<polygon
points="60,0 77.8,42.2 120,42.2 85.1,68.2 97.1,110.3 60,86.3 22.9,110.3 34.9,68.2 0,42.2 42.2,42.2"
fill="none"
stroke={color === "teal" ? "#0c8991" : color === "purple" ? "#9D5E9B" : "#B55076"}
strokeWidth="1"
strokeOpacity="0.2"
className="transform scale-75 origin-center"
/>
</svg>
</div>
</div>
<h3 className="text-xl font-playfair font-bold mb-2">{title}</h3>
<p className="text-gray-600">{description}</p>
<h3 className={`text-xl font-playfair font-bold mb-3 ${colorClasses[color].text}`}>{title}</h3>
<p className="text-gray-600 relative z-10">{description}</p>
</div>
);
}

View File

@ -1,18 +1,30 @@
import { Link } from "wouter";
import { IslamicPattern, ArabesquePattern, SectionDividerBottom } from "@/components/ui/section-divider";
export function HeroSection() {
return (
<section id="home" className="relative overflow-hidden">
<div className="geometric-pattern absolute inset-0 opacity-30"></div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 md:py-24 flex flex-col md:flex-row items-center">
<section id="home" className="relative overflow-hidden teal-light-bg py-16 md:py-24">
<ArabesquePattern color="teal" opacity={15} />
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col md:flex-row items-center">
<div className="md:w-1/2 mb-10 md:mb-0 md:pr-10">
<div className="relative">
<span className="absolute -left-4 -top-4 text-4xl text-teal opacity-20 font-aref">بسم الله</span>
</div>
<h1 className="text-4xl md:text-5xl font-playfair font-bold text-gray-800 leading-tight">
Find Balance, Strength & Inner Peace
</h1>
<div className="w-20 h-1 bg-teal my-6"></div>
<div className="flex items-center my-6">
<div className="h-px w-8 bg-teal opacity-30"></div>
<div className="w-16 h-1 mx-2 bg-teal"></div>
<div className="h-px flex-grow bg-teal opacity-30"></div>
</div>
<p className="text-lg text-gray-600 font-raleway mb-8">
Transform your body and mind through the art of Pilates. Join our serene studio for personalized sessions that promote harmony, flexibility, and strength.
</p>
<div className="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
<Link
href="/classes"
@ -28,14 +40,23 @@ export function HeroSection() {
</Link>
</div>
</div>
<div className="md:w-1/2">
<img
src="https://images.unsplash.com/photo-1518611012118-696072aa579a?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&h=600"
alt="Woman practicing pilates in a bright, airy studio"
className="rounded-lg shadow-xl w-full h-auto"
/>
<div className="md:w-1/2 relative">
<div className="absolute -bottom-4 -right-4 w-full h-full border-4 border-teal border-opacity-10 rounded-lg"></div>
<div className="relative overflow-hidden rounded-lg shadow-xl">
<img
src="https://images.unsplash.com/photo-1518611012118-696072aa579a?ixlib=rb-4.0.3&auto=format&fit=crop&w=800&h=600"
alt="Woman practicing pilates in a bright, airy studio"
className="w-full h-auto"
/>
<div className="absolute inset-0 border-[12px] border-white border-opacity-20 rounded-lg"></div>
</div>
</div>
</div>
<div className="mt-12">
<SectionDividerBottom color="teal" />
</div>
</section>
);
}

View File

@ -0,0 +1,104 @@
import React from "react";
interface PatternProps {
className?: string;
fillColor?: string;
}
export function GeometricPattern({ className = "", fillColor = "#0c8991" }: PatternProps) {
return (
<div className={`absolute inset-0 opacity-10 overflow-hidden ${className}`}>
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<pattern id="islamic-geometric" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<path
d="M10,0 L20,10 L10,20 L0,10 Z"
fill="none"
stroke={fillColor}
strokeWidth="0.5"
/>
<circle cx="10" cy="10" r="2" fill={fillColor} fillOpacity="0.3" />
<path
d="M0,0 L20,0 M0,10 L20,10 M0,20 L20,20 M0,0 L0,20 M10,0 L10,20 M20,0 L20,20"
stroke={fillColor}
strokeWidth="0.2"
strokeDasharray="1,1"
/>
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#islamic-geometric)" />
</svg>
</div>
);
}
export function ArabicArch({ className = "", fillColor = "#0c8991" }: PatternProps) {
return (
<div className={`w-full overflow-hidden ${className}`}>
<svg viewBox="0 0 100 30" preserveAspectRatio="none">
<path
d="M0,30 L100,30 L100,10 C75,30 25,30 0,10 Z"
fill={fillColor}
fillOpacity="0.1"
/>
<path
d="M0,10 C25,30 75,30 100,10"
fill="none"
stroke={fillColor}
strokeWidth="0.5"
strokeDasharray="1,1"
/>
</svg>
</div>
);
}
export function CrescentMoon({ className = "", fillColor = "#0c8991" }: PatternProps) {
return (
<div className={`${className}`}>
<svg viewBox="0 0 24 24" width="24" height="24">
<path
d="M12,2 A10,10 0 0 1 12,22 A10,10 0 0 1 12,2 A8,8 0 0 0 12,18 A8,8 0 0 0 12,2"
fill={fillColor}
/>
</svg>
</div>
);
}
export function DividerPattern({ className = "", fillColor = "#0c8991" }: PatternProps) {
return (
<div className={`w-full flex items-center justify-center py-8 ${className}`}>
<div className="w-1/3 h-px bg-gray-300"></div>
<div className="mx-4">
<svg width="40" height="40" viewBox="0 0 100 100">
<polygon
points="50,10 61,35 90,35 65,55 75,80 50,65 25,80 35,55 10,35 39,35"
fill={fillColor}
fillOpacity="0.7"
/>
<circle cx="50" cy="50" r="10" fill={fillColor} />
</svg>
</div>
<div className="w-1/3 h-px bg-gray-300"></div>
</div>
);
}
export function ArabicPattern({ className = "", fillColor = "#0c8991" }: PatternProps) {
return (
<div className={`absolute inset-0 opacity-10 overflow-hidden ${className}`}>
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
<pattern id="arabesqueTile" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<path
d="M0,0 C5,5 15,5 20,0 C15,-5 5,-5 0,0 Z
M0,20 C5,15 15,15 20,20 C15,25 5,25 0,20 Z
M10,10 C15,5 15,15 10,10 Z"
fill="none"
stroke={fillColor}
strokeWidth="0.5"
/>
</pattern>
<rect x="0" y="0" width="100%" height="100%" fill="url(#arabesqueTile)" />
</svg>
</div>
);
}

View File

@ -0,0 +1,166 @@
import React from "react";
interface SectionDividerProps {
color?: "teal" | "purple" | "rose";
className?: string;
withPattern?: boolean;
}
export function SectionDivider({
color = "teal",
className = "",
withPattern = false
}: SectionDividerProps) {
const colors = {
teal: "#0c8991",
purple: "#9D5E9B",
rose: "#B55076"
};
const fillColor = colors[color];
const patternClass = withPattern ? `islamic-pattern-${color}` : "";
return (
<div className={`relative ${className}`}>
<div className="islamic-arch-top">
<svg viewBox="0 0 100 20" preserveAspectRatio="none">
<path d="M0,20 L100,20 L100,15 C75,0 25,0 0,15 Z" fill={fillColor} fillOpacity="0.15" />
<path d="M0,15 C25,0 75,0 100,15" fill="none" stroke={fillColor} strokeWidth="0.3" />
</svg>
</div>
{withPattern && <div className={`absolute inset-0 ${patternClass}`}></div>}
</div>
);
}
export function SectionDividerBottom({
color = "teal",
className = "",
withPattern = false
}: SectionDividerProps) {
const colors = {
teal: "#0c8991",
purple: "#9D5E9B",
rose: "#B55076"
};
const fillColor = colors[color];
const patternClass = withPattern ? `islamic-pattern-${color}` : "";
return (
<div className={`relative ${className}`}>
<div className="islamic-arch-bottom">
<svg viewBox="0 0 100 20" preserveAspectRatio="none">
<path d="M0,20 L100,20 L100,15 C75,0 25,0 0,15 Z" fill={fillColor} fillOpacity="0.15" />
<path d="M0,15 C25,0 75,0 100,15" fill="none" stroke={fillColor} strokeWidth="0.3" />
</svg>
</div>
{withPattern && <div className={`absolute inset-0 ${patternClass}`}></div>}
</div>
);
}
export function IslamicPattern({
color = "teal",
className = "",
opacity = 10
}: {
color?: "teal" | "purple" | "rose";
className?: string;
opacity?: number;
}) {
const patternClass = color === "teal"
? "islamic-pattern-teal"
: color === "purple"
? "islamic-pattern"
: "islamic-pattern-rose";
return <div className={`absolute inset-0 ${patternClass} opacity-${opacity} ${className}`}></div>;
}
export function ArabesquePattern({
color = "teal",
className = "",
opacity = 10
}: {
color?: "teal" | "purple" | "rose";
className?: string;
opacity?: number;
}) {
const patternClass = color === "teal"
? "arabesque-pattern"
: color === "purple"
? "arabesque-pattern-purple"
: "arabesque-pattern-rose";
return <div className={`absolute inset-0 ${patternClass} opacity-${opacity} ${className}`}></div>;
}
export function CrescentDivider({
color = "teal",
className = ""
}: {
color?: "teal" | "purple" | "rose";
className?: string;
}) {
const colors = {
teal: "#0c8991",
purple: "#9D5E9B",
rose: "#B55076"
};
const fillColor = colors[color];
return (
<div className={`flex items-center justify-center py-8 ${className}`}>
<div className="w-1/3 h-px bg-gray-300"></div>
<div className="mx-4">
<svg width="40" height="40" viewBox="0 0 100 100">
<path
d="M50,10 A40,40 0 0 1 50,90 A40,40 0 0 1 50,10 A30,30 0 0 0 50,70 A30,30 0 0 0 50,10"
fill={fillColor}
fillOpacity="0.8"
/>
<circle cx="60" cy="40" r="5" fill="#fff" />
</svg>
</div>
<div className="w-1/3 h-px bg-gray-300"></div>
</div>
);
}
export function StarDivider({
color = "teal",
className = ""
}: {
color?: "teal" | "purple" | "rose";
className?: string;
}) {
const colors = {
teal: "#0c8991",
purple: "#9D5E9B",
rose: "#B55076"
};
const fillColor = colors[color];
return (
<div className={`flex items-center justify-center py-8 ${className}`}>
<div className="w-1/3 h-px bg-gray-300"></div>
<div className="mx-4">
<svg width="40" height="40" viewBox="0 0 100 100">
<polygon
points="50,10 61,35 90,35 65,55 75,80 50,65 25,80 35,55 10,35 39,35"
fill={fillColor}
fillOpacity="0.8"
/>
</svg>
</div>
<div className="w-1/3 h-px bg-gray-300"></div>
</div>
);
}

View File

@ -72,6 +72,55 @@
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%239d5e9b' fill-opacity='0.05' fill-rule='evenodd'/%3E%3C/svg%3E");
}
.islamic-pattern-teal {
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%230c8991' fill-opacity='0.05' fill-rule='evenodd'/%3E%3C/svg%3E");
}
.islamic-pattern-rose {
background-image: url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='%23b55076' fill-opacity='0.05' fill-rule='evenodd'/%3E%3C/svg%3E");
}
.arabesque-pattern {
background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%230c8991' fill-opacity='0.05'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6h-2c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.arabesque-pattern-purple {
background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%239d5e9b' fill-opacity='0.05'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6h-2c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.arabesque-pattern-rose {
background-image: url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23b55076' fill-opacity='0.05'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6h-2c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.islamic-arch-divider {
position: relative;
height: 60px;
margin: -30px 0;
overflow: hidden;
z-index: 10;
}
.islamic-arch-top {
position: relative;
overflow: hidden;
}
.islamic-arch-top svg {
display: block;
width: 100%;
}
.islamic-arch-bottom {
position: relative;
overflow: hidden;
}
.islamic-arch-bottom svg {
display: block;
width: 100%;
transform: rotate(180deg);
}
.teal-bg {
background-color: #0c8991;
}