main page + clients page fixes

This commit is contained in:
2024-02-19 18:01:21 +05:00
parent ad0aa62f13
commit 4dc43ff56e
17 changed files with 270 additions and 123 deletions
@@ -13,7 +13,7 @@ const ClientsPageCarousel = () => {
const defaultOffset = isOddCount ? 300 : 0;
const { setModal } = useStore();
const [letters, setLetters] = useState<Image[]>(thanksgivingLetters);
const [letters] = useState<Image[]>(thanksgivingLetters);
const [currentImage, setCurrentImage] = useState(middleLetter);
const [offset, setOffset] = useState(IMAGE_WIDTH);
@@ -53,7 +53,7 @@ const ClientsPageCarousel = () => {
<div className="py-24">
<div className="flex h-[450px] w-[calc(100vw-20px)] overflow-hidden relative">
<div
className="flex transition-all duration-500 justify-center w-full "
className="flex transition-all duration-500 justify-center w-full"
style={{
transform: `translateX(${offset - defaultOffset}px)`,
}}
@@ -77,7 +77,7 @@ const ClientsPageCarousel = () => {
className="absolute left-1/4 top-1/3 bg-[#e8e8e8] w-10 h-10 rounded-full"
onClick={handleOnLeftButtonClick}
>
<ArrowCarouselIcon isLeft className="w-3 h-4 m-auto" />{" "}
<ArrowCarouselIcon isLeft className="w-[10px] h-4 m-auto" />{" "}
</button>
<button
className="absolute right-1/4 top-1/3 bg-[#e8e8e8] w-10 h-10 rounded-full"
@@ -1,4 +1,8 @@
import { Image } from "../../types";
import CrossIcon from "../../icons/CrossIcon";
import useStore from "../../store/store";
import ArrowCarouselIcon from "../../icons/ArrowCarouselIcon";
import { useState } from "react";
type ZoomInLetterModalProps = {
images: Image[];
@@ -9,15 +13,29 @@ const ZoomInLetterModal = ({
images,
currentImage,
}: ZoomInLetterModalProps) => {
const { setModal } = useStore();
const [selectedImage, setSelectedImage] = useState(currentImage);
const handleOnRightClick = () => {
setSelectedImage((prev) => prev + 1);
};
const handleOnLeftClick = () => {
setSelectedImage((prev) => prev - 1);
};
const handleOnCloseModal = () => {
setModal(null);
};
return (
<div
className="fixed w-screen h-screen bg-[#fff] z-30 flex justify-center items-center"
// onClick={handleOnCloseClick}
>
<div className="fixed w-screen h-screen bg-[#fff] z-30 flex justify-center items-center">
<div
className="flex"
className="flex w-fit duration-300 transition-all"
style={{
transform: `translateX(calc(${-1 * currentImage}*000vw))`,
transform: `translateX(calc(${
Math.round(images.length / 2) - selectedImage
}*100vw))`,
}}
>
{images.map((image) => {
@@ -33,6 +51,24 @@ const ZoomInLetterModal = ({
);
})}
</div>
<div
className="absolute top-2 right-2 z-30 cursor-pointer p-[10px]"
onClick={handleOnCloseModal}
>
<CrossIcon color="#000" />
</div>
<div
className="z-30 absolute top-1/2 right-2 p-[10px] cursor-pointer"
onClick={handleOnRightClick}
>
<ArrowCarouselIcon className="stroke-black" />
</div>
<div
className="z-30 absolute top-1/2 left-2 p-[10px] cursor-pointer"
onClick={handleOnLeftClick}
>
<ArrowCarouselIcon isLeft />
</div>
</div>
);
};
+1 -1
View File
@@ -1,8 +1,8 @@
import { useNavigate } from "react-router-dom";
import LogoIcon from "../../icons/LogoIcon";
import SocialLinks from "./SocialLinks";
import LanguageSwitcher from "./LanguageSwitcher";
import Tabs from "../Tabs";
import { useNavigate } from "react-router-dom";
const Header = (): JSX.Element => {
const navigate = useNavigate();
+2 -2
View File
@@ -14,8 +14,8 @@ const Question = ({ title, description }: QuestionProps) => {
};
return (
<li
className={`group cursor-pointer flex justify-between items-center text-2xl border-b flex-col select-none transition-[height] duration-500 overflow-hidden pb-7 ${
isOpen ? "h-40" : "h-24"
className={`group cursor-pointer flex justify-between items-center text-2xl border-b flex-col select-none transition-all duration-500 overflow-hidden ease-in-out pb-7 ${
isOpen ? "max-h-96" : "max-h-24"
}`}
onClick={handleOnQuestionClick}
>
@@ -0,0 +1,3 @@
import { createContext } from "react";
export const SliderContext = createContext(1);
@@ -1,7 +1,9 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import FirstSlide from "./slides/FirstSlide";
import SecondSlide from "./slides/SecondSlide";
import ThirdSlide from "./slides/ThirdSlide";
import { SliderContext } from "./Context";
import SwiperPaginationBullets from "../../SwiperPaginationBullets";
const slides = [
{ element: <FirstSlide />, id: 1 },
@@ -10,7 +12,13 @@ const slides = [
];
const MainPageSlider = () => {
const [offset, setOffset] = useState(-0);
const [offset, setOffset] = useState(0);
const [currentSlide, setCurrentSlide] = useState(1);
useEffect(() => {
const updatedSlide = -1 * offset + 1;
setCurrentSlide(updatedSlide);
}, [offset]);
const handleRightArrowClick = () => {
setOffset((currentOffset) => {
@@ -31,17 +39,27 @@ const MainPageSlider = () => {
return currentOffset + 1;
});
};
const handleOnSlideChange = (slide: number) => {
const updatedOffset = (slide - 1) * -1;
setCurrentSlide(slide);
setOffset(updatedOffset);
};
return (
<div className="flex flex-col">
<div className="flex flex-col select-none relative">
<div className="flex h-[calc(100vh-150px)] justify-between w-[calc(100vw-20px)] px-2 pt-20">
<div className="w-[calc(100vw-80px)] overflow-hidden">
<div className="w-screen overflow-hidden bg-gradient-radial from-[#773272] via-[#1e1530] to-[#1e1530]">
<div
className="flex transition-[1.25s]"
className="flex transition-[1.25s] "
style={{ transform: `translateX(calc(${offset}*100vw))` }}
>
{slides.map((slide) => (
<div key={slide.id}>{slide.element}</div>
))}
<SliderContext.Provider value={currentSlide}>
{slides.map((slide) => (
<div key={slide.id}>{slide.element}</div>
))}
</SliderContext.Provider>
</div>
</div>
@@ -56,6 +74,12 @@ const MainPageSlider = () => {
></button>
</div>
</div>
<SwiperPaginationBullets
className="absolute bottom-2 left-[50%]"
currentBullet={currentSlide}
bulletCount={slides.length}
handleOnBulletSwitch={handleOnSlideChange}
/>
</div>
);
};
@@ -0,0 +1,70 @@
import { useEffect, useRef, useContext } from "react";
import gsap from "gsap";
import { SliderContext } from "../Context";
const FirstSlide = () => {
const firstImageRef = useRef(null);
const secondImageRef = useRef(null);
const currentContext = useContext(SliderContext);
useEffect(() => {
if (!firstImageRef.current || !secondImageRef.current) return;
if (currentContext === 1) {
gsap.fromTo(
firstImageRef.current,
{ transform: "scale(2.0)" },
{
transform: "scale(1.6)",
duration: 1.5,
scrollTrigger: {
trigger: firstImageRef.current,
start: "10% bottom",
},
}
);
gsap.fromTo(
secondImageRef.current,
{ transform: "scale(2.0)", left: "5%", top: "25%" },
{
transform: "scale(1.5)",
left: "-0%",
top: "30%",
duration: 2.2,
scrollTrigger: {
trigger: firstImageRef.current,
start: "10% bottom",
},
}
);
}
}, [currentContext]);
return (
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw]">
<p className="font-bold text-8xl text-wrap text-white mx-auto leading-[110px]">
Технологии расширенной
<br /> реальности для вашего бизнеса
</p>
<img
ref={firstImageRef}
className="absolute top-[30%] scale-150 left-[6%]"
src="/images/slides/first-slide-2.png"
alt="image"
/>
<img
ref={secondImageRef}
className="absolute top-[30%] scale-150 left-[20%]"
src="/images/slides/first-slide-1.png"
alt="image"
/>
<p className="absolute text-white text-4xl top-[85%] left-[62%]">
Мы приглашаем вас в мир
<br /> удивительного будущего с<br /> технологиями виртуальной <br /> и
смешанной реальности
</p>
</div>
);
};
export default FirstSlide;
@@ -1,16 +1,27 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useContext } from "react";
import { gsap } from "gsap";
import { SliderContext } from "../Context";
const SecondSlide = () => {
const firstImageRef = useRef(null);
const currentSlider = useContext(SliderContext);
useEffect(() => {
if (firstImageRef.current)
gsap.to(firstImageRef.current, {
left: "151%",
top: "18%",
duration: 1.5,
});
}, []);
if (!firstImageRef.current) return;
if (currentSlider === 2)
gsap.fromTo(
firstImageRef.current,
{
left: "167%",
top: "2%",
},
{
left: "151%",
top: "18%",
duration: 2.0,
}
);
}, [currentSlider]);
return (
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw]">
@@ -1,19 +1,24 @@
import { useRef, useEffect } from "react";
import { useRef, useEffect, useContext } from "react";
import { gsap } from "gsap";
import { SliderContext } from "../Context";
const ThirdSlide = () => {
const currentSlider = useContext(SliderContext);
const firstImageRef = useRef(null);
useEffect(() => {
if (firstImageRef.current)
gsap.fromTo(
firstImageRef.current,
{
transform: "scale(1.15)",
},
{ transform: "scale(1)", duration: 1.5 }
);
}, []);
if (!firstImageRef.current) return;
gsap.fromTo(
firstImageRef.current,
{
transform: "scale(1.15)",
},
{ transform: "scale(1)", duration: 2 }
);
}, [currentSlider]);
return (
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw] relative">
<p className="font-bold text-8xl text-wrap text-white w-[1500px] mx-auto leading-[87px]">
@@ -27,7 +32,7 @@ const ThirdSlide = () => {
/>
<img
ref={firstImageRef}
className="absolute top-[-100%] left-[-18%]"
className="absolute top-[-100%] left-[-14%]"
src="/images/slides/third-slide-2.svg"
alt="image"
/>
@@ -1,73 +0,0 @@
import { useRef } from "react";
const FirstSlide = () => {
const firstImageRef = useRef(null);
const secondImageRef = useRef(null);
// useEffect(() => {
// if (firstImageRef.current) {
// console.log("imageRef.current", firstImageRef.current);
// gsap.fromTo(
// firstImageRef.current,
// { transform: "scale(2.0)" },
// {
// transform: "scale(1.6)",
// duration: 1.5,
// scrollTrigger: {
// trigger: firstImageRef.current,
// start: "10% bottom",
// },
// }
// );
// gsap.fromTo(
// secondImageRef.current,
// { transform: "scale(2.0)", left: "5%" },
// {
// transform: "scale(1.6)",
// left: "-5%",
// duration: 2.2,
// scrollTrigger: {
// trigger: firstImageRef.current,
// start: "10% bottom",
// },
// }
// );
// }
// }, []);
return (
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw]">
<p className="font-bold text-8xl text-wrap text-white mx-auto leading-[87px]">
Технологии расширенной
<br /> реальности для вашего бизнеса
</p>
{/* <motion.div
initial={{ scale: 1.2 }}
whileInView={{ scale: 1 }}
viewport={{ amount: "all" }}
transition={{ duration: 1, ease: [0.58, 0.12, 0.27, 0.98] }}
className="flex flex-col gap-1"
> */}
<img
ref={firstImageRef}
className="absolute top-[40%]"
src="/images/slides/first-slide-2.png"
alt="image"
/>
{/* </motion.div> */}
<img
ref={secondImageRef}
className="absolute top-[40%] scale-150 left-[10%]"
src="/images/slides/first-slide-1.png"
alt="image"
/>
<p className="absolute text-white text-4xl top-[85%] left-[57%]">
Мы приглашаем вас в мир
<br /> удивительного будущего с<br /> технологиями виртуальной <br /> и
смешанной реальности
</p>
</div>
);
};
export default FirstSlide;
@@ -0,0 +1,37 @@
type SwiperPaginationBulletsProps = {
className?: string;
currentBullet: number;
bulletCount: number;
handleOnBulletSwitch: (updatedBullet: number) => void;
};
const SwiperPaginationBullets = ({
className,
currentBullet,
bulletCount,
handleOnBulletSwitch,
}: SwiperPaginationBulletsProps) => {
const bullets = Array.from({ length: bulletCount }, (_, index) => {
return { id: index + 1 };
});
return (
<div className={`${className ? className : ""} flex cursor-pointer`}>
{bullets.map((bullet) => (
<div
className="p-1"
key={bullet.id}
onClick={() => handleOnBulletSwitch(bullet.id)}
>
<div
className={`w-2 h-2 rounded-full ${
currentBullet === bullet.id ? "bg-white" : "opacity-20 bg-black"
}`}
></div>
</div>
))}
</div>
);
};
export default SwiperPaginationBullets;
+14
View File
@@ -1,3 +1,4 @@
import { useEffect } from "react";
import Header from "./Header/Header";
import Footer from "./Footer/Footer";
import { Outlet } from "react-router-dom";
@@ -6,6 +7,19 @@ import useStore from "../store/store";
const Wrapper = () => {
const { modal } = useStore();
useEffect(() => {
const body = document.body;
if (!body) return;
if (!modal) {
body.style.overflow = "visible";
return;
}
body.style.overflow = "hidden";
}, [modal]);
return (
<>
{modal}
+8 -3
View File
@@ -1,12 +1,17 @@
type ArrowCarouselIconProps = {
isLeft?: boolean;
className?: string;
color?: string;
};
const ArrowCarouselIcon = ({ isLeft, className }: ArrowCarouselIconProps) => {
const ArrowCarouselIcon = ({
isLeft,
className,
color = "#000",
}: ArrowCarouselIconProps) => {
return (
<svg
className={`w-6 h-6 ${className ? className : ""} ${
className={`w-6 h-6 stroke-black ${className ? className : ""} ${
isLeft ? "rotate-180" : ""
}`}
role="presentation"
@@ -16,7 +21,7 @@ const ArrowCarouselIcon = ({ isLeft, className }: ArrowCarouselIconProps) => {
>
<polyline
fill="none"
stroke="#000000"
stroke={color}
strokeLinecap="butt"
strokeWidth="1"
points="0.5,0.5 8.5,8.5 0.5,16.5"
+13 -2
View File
@@ -1,6 +1,12 @@
const CrossIcon = () => {
type CrossIconProps = {
color?: string;
className?: string;
};
const CrossIcon = ({ color, className }: CrossIconProps) => {
return (
<svg
className={`${className ? className : ""}`}
role="presentation"
width="23px"
height="23px"
@@ -8,7 +14,12 @@ const CrossIcon = () => {
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<g stroke="none" stroke-width="1" fill="#fff" fill-rule="evenodd">
<g
stroke="none"
strokeWidth="1"
fill={color ? color : "#fff"}
fillRule="evenodd"
>
<rect
transform="translate(11.313708, 11.313708) rotate(-45.000000) translate(-11.313708, -11.313708) "
x="10.3137085"
+3 -1
View File
@@ -16,6 +16,8 @@
display: inline-block;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
height: 70px;
width: 50px;
padding: 10px 15px 10px 10px;
position: relative;
text-decoration: none;
@@ -52,7 +54,7 @@
-o-transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
transform: rotate(-135deg);
right: 10px;
right: 30px;
top: 50%;
width: 0;
}
+2 -2
View File
@@ -1,4 +1,4 @@
import MainPageSlider from "../../components/MainPage/Slider";
import MainPageSlider from "../../components/MainPage/Slider/Slider";
import Services from "../../components/MainPage/Services";
import LastProjects from "../../components/MainPage/LastProjects";
import AboutUs from "../../components/MainPage/AboutUs";
@@ -6,7 +6,7 @@ import Feedback from "../../components/MainPage/OftenQuestion";
const MainPage = () => {
return (
<div className="min-h-[calc(100vh-152px)]">
<div className="min-h-[calc(100vh-152px)] overflow-hidden">
<MainPageSlider />
<Services />
<LastProjects />
+5 -3
View File
@@ -2,9 +2,11 @@
export default {
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
// extend: {animation: {
// 'spin-slow': 'spin 3s linear infinite',
// }},
extend: {
backgroundImage: {
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
},
},
},
plugins: [],
};