fix : added animation and responsiveness in portfolio segment
This commit is contained in:
parent
ae41722019
commit
f20e8591cb
|
|
@ -6,109 +6,213 @@ import {
|
||||||
Grid,
|
Grid,
|
||||||
Typography,
|
Typography,
|
||||||
Button,
|
Button,
|
||||||
|
Container,
|
||||||
|
useMediaQuery,
|
||||||
|
useTheme,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
import portfolioImg from "../ourwork/Rectangle 6.png";
|
import portfolioImg from "../ourwork/Rectangle 6.png";
|
||||||
|
|
||||||
const works = [
|
const works = [
|
||||||
{
|
{
|
||||||
title: "Project Name",
|
title: "Project Aurora",
|
||||||
image: portfolioImg,
|
image: portfolioImg,
|
||||||
|
description: "Modern web design with seamless user experience",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Project Name",
|
title: "Project Nexus",
|
||||||
image: portfolioImg,
|
image: portfolioImg,
|
||||||
|
description: "Mobile application development for enterprise",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Project Name",
|
title: "Project Horizon",
|
||||||
image: portfolioImg,
|
image: portfolioImg,
|
||||||
|
description: "Brand identity and marketing campaign",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const OurWorks = () => {
|
const OurWorks = () => {
|
||||||
return (
|
const theme = useTheme();
|
||||||
<Box sx={{ backgroundColor: "#1d2733", color: "#fff", py: 8, px: 2 }}>
|
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
||||||
<Typography variant="h4" align="center" fontWeight="bold" gutterBottom>
|
|
||||||
Our Works
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="subtitle1" align="center" mb={6}>
|
|
||||||
We’ve helped brands grow through bold strategy and creative execution.
|
|
||||||
Explore our recent success stories.
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<Grid container spacing={4} justifyContent="center">
|
return (
|
||||||
{works.map((work, index) => (
|
<Box
|
||||||
<Grid item xs={12} sm={6} md={4} key={index}>
|
sx={{
|
||||||
<Card
|
backgroundColor: "#1d2733",
|
||||||
sx={{
|
color: "#fff",
|
||||||
borderRadius: 3,
|
py: 8,
|
||||||
overflow: "hidden",
|
px: { xs: 2, sm: 4 },
|
||||||
bgcolor: "#fff",
|
}}
|
||||||
maxWidth: 320,
|
>
|
||||||
margin: "0 auto",
|
<Container maxWidth="md">
|
||||||
}}
|
<motion.div
|
||||||
elevation={3}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
>
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
<CardContent>
|
transition={{ duration: 0.6 }}
|
||||||
<Typography
|
viewport={{ once: true }}
|
||||||
variant="subtitle1"
|
>
|
||||||
fontWeight="bold"
|
<Typography
|
||||||
color="Black"
|
variant="h4"
|
||||||
gutterBottom
|
align="center"
|
||||||
>
|
fontWeight={700}
|
||||||
{work.title}
|
gutterBottom
|
||||||
</Typography>
|
sx={{
|
||||||
</CardContent>
|
mb: 2,
|
||||||
<CardMedia
|
fontFamily: "'Montserrat', sans-serif",
|
||||||
component="img"
|
letterSpacing: 0.5,
|
||||||
image={work.image}
|
}}
|
||||||
alt={work.title}
|
>
|
||||||
sx={{
|
Our Portfolio
|
||||||
objectFit: "contain",
|
</Typography>
|
||||||
height: 250,
|
<Typography
|
||||||
px: 2,
|
variant="subtitle1"
|
||||||
}}
|
align="center"
|
||||||
/>
|
mb={6}
|
||||||
<CardContent>
|
sx={{
|
||||||
<Button
|
maxWidth: 600,
|
||||||
variant="contained"
|
mx: "auto",
|
||||||
fullWidth
|
color: "rgba(255,255,255,0.8)",
|
||||||
|
fontFamily: "'Open Sans', sans-serif",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
We craft digital experiences that drive results
|
||||||
|
</Typography>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<Grid container spacing={isMobile ? 3 : 4} justifyContent="center">
|
||||||
|
{works.map((work, index) => (
|
||||||
|
<Grid item xs={12} sm={6} md={4} key={index}>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
whileHover={{ y: -5 }}
|
||||||
|
>
|
||||||
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
backgroundColor: "#000",
|
borderRadius: 2,
|
||||||
color: "#00FFD1",
|
overflow: "hidden",
|
||||||
fontWeight: "bold",
|
bgcolor: "#fff",
|
||||||
|
maxWidth: 320,
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
|
||||||
|
transition: "all 0.3s ease",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
backgroundColor: "#333",
|
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
|
||||||
},
|
},
|
||||||
borderRadius: "30px",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
VIEW DEMO
|
<Box
|
||||||
</Button>
|
sx={{
|
||||||
</CardContent>
|
height: 180,
|
||||||
</Card>
|
display: "flex",
|
||||||
</Grid>
|
alignItems: "center",
|
||||||
))}
|
justifyContent: "center",
|
||||||
</Grid>
|
bgcolor: "#f8f9fa",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
image={work.image}
|
||||||
|
alt={work.title}
|
||||||
|
sx={{
|
||||||
|
width: "90%",
|
||||||
|
height: "90%",
|
||||||
|
objectFit: "contain",
|
||||||
|
transition: "transform 0.3s ease",
|
||||||
|
"&:hover": {
|
||||||
|
transform: "scale(1.05)",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<CardContent sx={{ flexGrow: 1, px: 3, py: 2 }}>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
fontWeight={600}
|
||||||
|
color="#000"
|
||||||
|
gutterBottom
|
||||||
|
sx={{
|
||||||
|
fontFamily: "'Montserrat', sans-serif",
|
||||||
|
fontSize: "1.1rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{work.title}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color="#000"
|
||||||
|
sx={{
|
||||||
|
mb: 2,
|
||||||
|
fontFamily: "'Open Sans', sans-serif",
|
||||||
|
fontSize: "0.875rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{work.description}
|
||||||
|
</Typography>
|
||||||
|
</CardContent>
|
||||||
|
<CardContent sx={{ px: 3, py: 0, pb: 3 }}>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
sx={{
|
||||||
|
borderRadius: "20px",
|
||||||
|
border: "1px solid #000",
|
||||||
|
color: "#000",
|
||||||
|
fontWeight: 600,
|
||||||
|
py: 1,
|
||||||
|
fontSize: "0.8rem",
|
||||||
|
textTransform: "none",
|
||||||
|
letterSpacing: 0.5,
|
||||||
|
fontFamily: "'Montserrat', sans-serif",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#000",
|
||||||
|
color: "#fff",
|
||||||
|
border: "1px solid #000",
|
||||||
|
},
|
||||||
|
transition: "all 0.3s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
View Case Study
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</motion.div>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Box mt={6} display="flex" justifyContent="center">
|
<Box mt={6} display="flex" justifyContent="center">
|
||||||
<Button
|
<motion.div whileHover={{ scale: 1.03 }} whileTap={{ scale: 0.98 }}>
|
||||||
variant="outlined"
|
<Button
|
||||||
sx={{
|
variant="outlined"
|
||||||
borderRadius: "30px",
|
sx={{
|
||||||
borderColor: "#00FFD1",
|
borderRadius: "20px",
|
||||||
color: "#00FFD1",
|
border: "1px solid #00FFD1",
|
||||||
px: 4,
|
color: "#00FFD1",
|
||||||
py: 1.5,
|
px: 4,
|
||||||
fontWeight: "bold",
|
py: 1,
|
||||||
"&:hover": {
|
fontWeight: 600,
|
||||||
backgroundColor: "#00FFD1",
|
fontSize: "0.9rem",
|
||||||
color: "#000",
|
textTransform: "none",
|
||||||
},
|
letterSpacing: 0.5,
|
||||||
}}
|
fontFamily: "'Montserrat', sans-serif",
|
||||||
>
|
"&:hover": {
|
||||||
VIEW FULL PORTFOLIO →
|
backgroundColor: "rgba(0, 255, 209, 0.1)",
|
||||||
</Button>
|
border: "1px solid #00FFD1",
|
||||||
</Box>
|
},
|
||||||
|
transition: "all 0.3s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Explore Full Portfolio
|
||||||
|
</Button>
|
||||||
|
</motion.div>
|
||||||
|
</Box>
|
||||||
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Container,
|
Container,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
Grid,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { motion, AnimatePresence, PanInfo } from "framer-motion";
|
import { motion, AnimatePresence, PanInfo } from "framer-motion";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
@ -35,18 +36,17 @@ const services = [
|
||||||
|
|
||||||
const Services = () => {
|
const Services = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
const isMobile = useMediaQuery(theme.breakpoints.down("md"));
|
||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
const [hoveredCard, setHoveredCard] = useState<number | null>(null);
|
||||||
|
|
||||||
const handleDragEnd = (
|
const handleDragEnd = (
|
||||||
event: MouseEvent | TouchEvent | PointerEvent,
|
event: MouseEvent | TouchEvent | PointerEvent,
|
||||||
info: PanInfo
|
info: PanInfo
|
||||||
) => {
|
) => {
|
||||||
if (info.offset.x > 50) {
|
if (info.offset.x > 50) {
|
||||||
// Swiped right
|
|
||||||
setCurrentIndex((prev) => (prev === 0 ? services.length - 1 : prev - 1));
|
setCurrentIndex((prev) => (prev === 0 ? services.length - 1 : prev - 1));
|
||||||
} else if (info.offset.x < -50) {
|
} else if (info.offset.x < -50) {
|
||||||
// Swiped left
|
|
||||||
setCurrentIndex((prev) => (prev === services.length - 1 ? 0 : prev + 1));
|
setCurrentIndex((prev) => (prev === services.length - 1 ? 0 : prev + 1));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -58,23 +58,29 @@ const Services = () => {
|
||||||
initial={{ opacity: 0, y: -20 }}
|
initial={{ opacity: 0, y: -20 }}
|
||||||
whileInView={{ opacity: 1, y: 0 }}
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.6 }}
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true, margin: "-100px" }}
|
||||||
>
|
>
|
||||||
<Typography
|
<Typography
|
||||||
variant="h4"
|
variant="h4"
|
||||||
align="center"
|
align="center"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
gutterBottom
|
gutterBottom
|
||||||
|
sx={{ mb: 2 }}
|
||||||
>
|
>
|
||||||
Services
|
Our Services
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="subtitle1" align="center" mb={6}>
|
<Typography
|
||||||
We offer design, development & marketing services
|
variant="subtitle1"
|
||||||
|
align="center"
|
||||||
|
mb={6}
|
||||||
|
sx={{ maxWidth: 600, mx: "auto" }}
|
||||||
|
>
|
||||||
|
Professional solutions tailored to your needs
|
||||||
</Typography>
|
</Typography>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
<Box sx={{ position: "relative", height: 400, overflow: "hidden" }}>
|
<Box sx={{ position: "relative", height: 380 }}>
|
||||||
<AnimatePresence initial={false}>
|
<AnimatePresence initial={false}>
|
||||||
<motion.div
|
<motion.div
|
||||||
key={currentIndex}
|
key={currentIndex}
|
||||||
|
|
@ -91,144 +97,216 @@ const Services = () => {
|
||||||
padding: "0 16px",
|
padding: "0 16px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Card
|
<motion.div
|
||||||
sx={{
|
whileHover={{ scale: 1.02 }}
|
||||||
borderRadius: 5,
|
whileTap={{ scale: 0.98 }}
|
||||||
overflow: "hidden",
|
|
||||||
height: "100%",
|
|
||||||
bgcolor: "#fff",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
maxWidth: 345,
|
|
||||||
mx: "auto",
|
|
||||||
}}
|
|
||||||
elevation={3}
|
|
||||||
>
|
>
|
||||||
<Box
|
<Card
|
||||||
sx={{
|
sx={{
|
||||||
height: 200,
|
borderRadius: 2,
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
|
height: "100%",
|
||||||
|
bgcolor: "#fff",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
maxWidth: 300,
|
||||||
|
mx: "auto",
|
||||||
|
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.1)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CardMedia
|
<Box
|
||||||
component="img"
|
|
||||||
image={services[currentIndex].image}
|
|
||||||
alt={services[currentIndex].title}
|
|
||||||
sx={{
|
sx={{
|
||||||
objectFit: "contain",
|
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: 150,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
bgcolor: "#f8f9fa",
|
||||||
|
overflow: "hidden",
|
||||||
}}
|
}}
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<CardContent sx={{ flexGrow: 1 }}>
|
|
||||||
<Typography
|
|
||||||
variant="h6"
|
|
||||||
fontWeight="bold"
|
|
||||||
gutterBottom
|
|
||||||
color="black"
|
|
||||||
>
|
>
|
||||||
{services[currentIndex].title}
|
<motion.div
|
||||||
</Typography>
|
animate={{
|
||||||
<Typography variant="body2" color="black">
|
scale: hoveredCard === currentIndex ? 1.05 : 1,
|
||||||
{services[currentIndex].description}
|
y: hoveredCard === currentIndex ? -5 : 0,
|
||||||
</Typography>
|
}}
|
||||||
</CardContent>
|
transition={{ duration: 0.3 }}
|
||||||
</Card>
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
image={services[currentIndex].image}
|
||||||
|
alt={services[currentIndex].title}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "auto",
|
||||||
|
objectFit: "cover",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</Box>
|
||||||
|
<CardContent sx={{ flexGrow: 1 }}>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
fontWeight="bold"
|
||||||
|
gutterBottom
|
||||||
|
color="#000"
|
||||||
|
>
|
||||||
|
{services[currentIndex].title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="#000" sx={{ mb: 2 }}>
|
||||||
|
{services[currentIndex].description}
|
||||||
|
</Typography>
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ x: 5 }}
|
||||||
|
transition={{ type: "spring", stiffness: 300 }}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
color="primary"
|
||||||
|
fontWeight="bold"
|
||||||
|
sx={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
Learn more →
|
||||||
|
</Typography>
|
||||||
|
</motion.div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
{/* Dots indicator */}
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
mt: 2,
|
mt: 3,
|
||||||
gap: 1,
|
gap: 1.5,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{services.map((_, index) => (
|
{services.map((_, index) => (
|
||||||
<Box
|
<motion.div
|
||||||
key={index}
|
key={index}
|
||||||
onClick={() => setCurrentIndex(index)}
|
onClick={() => setCurrentIndex(index)}
|
||||||
sx={{
|
whileHover={{ scale: 1.2 }}
|
||||||
width: 10,
|
whileTap={{ scale: 0.9 }}
|
||||||
height: 10,
|
>
|
||||||
borderRadius: "50%",
|
<Box
|
||||||
bgcolor: index === currentIndex ? "#00E0FF" : "#ffffff80",
|
sx={{
|
||||||
cursor: "pointer",
|
width: 10,
|
||||||
}}
|
height: 10,
|
||||||
/>
|
borderRadius: "50%",
|
||||||
|
bgcolor: index === currentIndex ? "#00E0FF" : "#ffffff80",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Box
|
<Grid container spacing={3} justifyContent="center">
|
||||||
sx={{
|
|
||||||
display: "grid",
|
|
||||||
gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
|
|
||||||
gap: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{services.map((service, index) => (
|
{services.map((service, index) => (
|
||||||
<motion.div
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
sm={6}
|
||||||
|
md={4}
|
||||||
key={index}
|
key={index}
|
||||||
whileHover={{ y: -5 }}
|
sx={{ display: "flex", justifyContent: "center" }}
|
||||||
transition={{ duration: 0.3 }}
|
|
||||||
>
|
>
|
||||||
<Card
|
<motion.div
|
||||||
sx={{
|
initial={{ opacity: 0, y: 50 }}
|
||||||
borderRadius: 5,
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
overflow: "hidden",
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
height: "100%",
|
viewport={{ once: true, margin: "-100px" }}
|
||||||
bgcolor: "#fff",
|
onHoverStart={() => setHoveredCard(index)}
|
||||||
display: "flex",
|
onHoverEnd={() => setHoveredCard(null)}
|
||||||
flexDirection: "column",
|
style={{ width: "100%", maxWidth: 280 }}
|
||||||
}}
|
|
||||||
elevation={3}
|
|
||||||
>
|
>
|
||||||
<Box
|
<motion.div
|
||||||
sx={{
|
whileHover={{
|
||||||
height: 200,
|
y: -8,
|
||||||
display: "flex",
|
boxShadow: "0 15px 30px -5px rgba(0, 0, 0, 0.2)",
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
}}
|
||||||
|
transition={{ type: "spring", stiffness: 400, damping: 10 }}
|
||||||
|
style={{ height: "100%" }}
|
||||||
>
|
>
|
||||||
<motion.div whileHover={{ scale: 1.05 }}>
|
<Card
|
||||||
<CardMedia
|
sx={{
|
||||||
component="img"
|
borderRadius: 2,
|
||||||
image={service.image}
|
overflow: "hidden",
|
||||||
alt={service.title}
|
height: "100%",
|
||||||
sx={{
|
bgcolor: "#fff",
|
||||||
objectFit: "contain",
|
display: "flex",
|
||||||
width: "100%",
|
flexDirection: "column",
|
||||||
height: "100%",
|
boxShadow: "0 5px 15px rgba(0, 0, 0, 0.1)",
|
||||||
}}
|
width: "100%",
|
||||||
/>
|
}}
|
||||||
</motion.div>
|
|
||||||
</Box>
|
|
||||||
<CardContent sx={{ flexGrow: 1 }}>
|
|
||||||
<Typography
|
|
||||||
variant="h6"
|
|
||||||
fontWeight="bold"
|
|
||||||
gutterBottom
|
|
||||||
color="black"
|
|
||||||
>
|
>
|
||||||
{service.title}
|
<Box
|
||||||
</Typography>
|
sx={{
|
||||||
<Typography variant="body2" color="black">
|
width: "100%",
|
||||||
{service.description}
|
height: 160,
|
||||||
</Typography>
|
display: "flex",
|
||||||
</CardContent>
|
alignItems: "center",
|
||||||
</Card>
|
justifyContent: "center",
|
||||||
</motion.div>
|
bgcolor: "#f8f9fa",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
animate={{
|
||||||
|
scale: hoveredCard === index ? 1.1 : 1,
|
||||||
|
y: hoveredCard === index ? -5 : 0,
|
||||||
|
}}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
image={service.image}
|
||||||
|
alt={service.title}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "auto",
|
||||||
|
objectFit: "cover",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</Box>
|
||||||
|
<CardContent sx={{ flexGrow: 1 }}>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
fontWeight="bold"
|
||||||
|
gutterBottom
|
||||||
|
color="#000"
|
||||||
|
>
|
||||||
|
{service.title}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="#000" sx={{ mb: 2 }}>
|
||||||
|
{service.description}
|
||||||
|
</Typography>
|
||||||
|
<motion.div
|
||||||
|
whileHover={{ x: 5 }}
|
||||||
|
transition={{ type: "spring", stiffness: 300 }}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
variant="caption"
|
||||||
|
color="primary"
|
||||||
|
fontWeight="bold"
|
||||||
|
sx={{ cursor: "pointer" }}
|
||||||
|
>
|
||||||
|
Learn more →
|
||||||
|
</Typography>
|
||||||
|
</motion.div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue