HQ About page + Marasi fixes
|
After Width: | Height: | Size: 496 KiB |
|
After Width: | Height: | Size: 185 KiB |
|
After Width: | Height: | Size: 282 KiB |
|
After Width: | Height: | Size: 115 KiB |
|
After Width: | Height: | Size: 720 KiB |
|
After Width: | Height: | Size: 929 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 907 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 950 KiB |
|
After Width: | Height: | Size: 423 KiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 2.9 MiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 2.8 MiB |
@@ -1,106 +1,338 @@
|
||||
import { useRef } from "react"
|
||||
import MarasiDriveNeighboursSliderMobile from "./MarasiDriveNeighboursSliderMobile"
|
||||
import MarasiDriveNeighboursSliderTablet from "./MarasiDriveNeighboursSliderTablet"
|
||||
import { useScroll } from "motion/react"
|
||||
import ScrollSlider from "./ScrollSlider"
|
||||
import { marasiDriveFeatures } from "../data/aboutMarasiDrive"
|
||||
import { useRef, useState } from "react"
|
||||
import { AnimatePresence, motion, useInView, useScroll } from "motion/react"
|
||||
import AboutHQScrollSlider from "./AboutHQ/AboutHQSlider"
|
||||
import { marasiDriveMapCards } from "../data/aboutMarasiDrive"
|
||||
|
||||
import clsx from "clsx"
|
||||
import EqualIcon from "./icons/EqualIcon"
|
||||
import PlusIcon from "./icons/map/PlusIcon"
|
||||
import MarasiDriveMapMobile from "./MarasiDriveMapMobile"
|
||||
import MarasiDriveMapCard from "./MarasiDriveMapCard"
|
||||
import BrochureButton from "./ui/BrochureButton"
|
||||
import AboutHQSliderTablet from "./AboutHQ/AboutHQSliderTablet"
|
||||
import AboutHQSliderMobile from "./AboutHQ/AboutHQSliderMobile"
|
||||
import { hqDescription, hqSlider } from "../data/aboutHQ"
|
||||
import UnitTypesSlider from "./AboutHQ/UnitTypesSlider"
|
||||
import UnitTypesSliderMobile from "./AboutHQ/UnitTypesSliderMobile"
|
||||
|
||||
export default function AboutHQ() {
|
||||
return (
|
||||
<div className="relative ">
|
||||
<AboutHQHero/>
|
||||
<AboutHQSlider/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AboutHQHero() {
|
||||
return (
|
||||
<div className="2xl:sticky relative 2xl:top-[4.444vw]">
|
||||
|
||||
<section className="w-full 2xl:h-[calc(100dvh-4.444vw)] relative md:h-[calc(100dvh-4rem)] h-[calc(100dvh-3.15rem)] max-md:max-h-[162.222vw] flex flex-col justify-between bg-white 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 overflow-hidden">
|
||||
<div className="2xl:size-[100vw] md:size-[118.75vw] size-[137.5vw] rounded-full absolute 2xl:top-1/2 2xl:-translate-y-1/2 2xl:left-[36.667vw] md:top-[46.484vw] md:left-1/2 max-2xl:-translate-x-1/2 left-1/2 top-[48.611vw] -translate-y-0 bg-[#F3F3F2]"/>
|
||||
|
||||
<img src="/images/about-complex/hq/main_bg.png" alt="" className="absolute 2xl:h-[103%] 2xl:right-[-10vw] md:bottom-0 md:right-[-35vw] md:h-[85%] max-md:h-auto max-md:bottom-0 max-md:left-0" />
|
||||
|
||||
<div className="2xl:space-y-[1.667vw] md:max-2xl:space-y-6 space-y-4 relative">
|
||||
<h1 className="2xl:text-[5vw] md:max-2xl:text-7xl text-[32px] leading-none tracking-[-0.07em] font-mixcase-unmixed font-medium whitespace-pre-line">
|
||||
{`Rove Home HQ —
|
||||
Work looks different
|
||||
here`}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="2xl:space-y-[1.111vw] md:max-2xl:space-y-6 relative max-md:hidden">
|
||||
<img src="/images/about-complex/hq/logo.svg" alt="" className=" md:max-2xl:flex hidden mb-[6.25vw]" />
|
||||
<h4 className="text-h4 text-[#00BED7] font-medium whitespace-pre-line">
|
||||
{`Welcome to the office you
|
||||
actually want to show up for`}
|
||||
</h4>
|
||||
<p className="text-s opacity-70 2xl:w-1/4 md:max-2xl:w-1/3">
|
||||
HQ by Rove was born out of a question: what if the
|
||||
office could feel alive again? Now, the first
|
||||
ever hospitality-branded office building in Dubai is here to
|
||||
answer it. Starting in Marasi Bay
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<img src="/images/about-complex/hq/logo.svg" alt="" className="absolute 2xl:top-[1.806vw] 2xl:right-[2.222vw] 2xl:w-[6.111vw] md:max-2xl:hidden w-[17.778vw] max-md:left-1/2 max-md:top-[39.444vw] max-md:-translate-x-1/2" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div className="space-y-6 bg-white px-4 py-8 md:hidden">
|
||||
<h4 className="text-h4 text-[#00BED7] font-medium whitespace-pre-line ">
|
||||
{`Welcome to the office you
|
||||
actually want to show up for`}
|
||||
</h4>
|
||||
<p className="text-s opacity-70 2xl:w-1/4 md:max-2xl:w-1/3">
|
||||
HQ by Rove was born out of a question: what if the
|
||||
office could feel alive again? Now, the first
|
||||
ever hospitality-branded office building in Dubai is here to
|
||||
answer it. Starting in Marasi Bay
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AboutHQSlider() {
|
||||
const target = useRef<HTMLDivElement>(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target,
|
||||
target,
|
||||
});
|
||||
return (
|
||||
<div className="2xl:sticky relative 2xl:top-[-134vw]">
|
||||
<section
|
||||
className="bg-white w-full overflow-clip 2xl:h-[calc(27.639vw*5)] 2xl:pt-[9.444vw] 2xl:px-[2.222vw] 2xl:pb-[2.222vw] md:max-2xl:pt-[104px] md:max-2xl:px-6 md:max-2xl:pb-8 pt-16 px-4 pb-8"
|
||||
ref={target}
|
||||
>
|
||||
<div className="flex flex-col 2xl:gap-[4.444vw] 2xl:sticky top-[5vw]">
|
||||
<div className="flex flex-col items-center 2xl:gap-[2.222vw]">
|
||||
<h2 className="font-mixcase-unmixed text-h1 text-center whitespace-pre-line max-md:mb-[24px] md:max-2xl:mb-8 opacity-100">
|
||||
<span className="opacity-40">More than an office,</span> a lifestyle.
|
||||
const [selectedCategorySlider, setSelectedCategorySlider] =
|
||||
useState<keyof typeof hqSlider>("Modular Office Collection");
|
||||
|
||||
const sliderRef = useRef(null);
|
||||
const isSliderInView = useInView(sliderRef, {
|
||||
once: true,
|
||||
amount: 0.1,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="relative bg-white">
|
||||
|
||||
{/* Hero */}
|
||||
<div className="2xl:sticky relative 2xl:top-[4.444vw] ">
|
||||
<section className="w-full 2xl:h-[calc(100dvh-4.444vw)] relative md:h-[calc(100dvh-4rem)] h-[calc(100dvh-3.15rem)] md:max-h-[125vw] max-md:max-h-[162.222vw] flex flex-col justify-between bg-white 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 overflow-hidden">
|
||||
|
||||
<div className="2xl:size-[100vw] md:size-[118.75vw] size-[137.5vw] rounded-full absolute 2xl:top-1/2 2xl:-translate-y-1/2 2xl:left-[36.667vw] md:top-[46.484vw] md:left-1/2 max-2xl:-translate-x-1/2 left-1/2 top-[48.611vw] -translate-y-0 bg-[#F3F3F2]"/>
|
||||
<img src="/images/about-complex/hq/main_bg.png" alt="" className="absolute 2xl:h-[103%] 2xl:left-[46.528vw] md:bottom-0 md:right-[-35vw] md:h-[85%] max-md:h-auto max-md:bottom-0 max-md:left-0" />
|
||||
|
||||
<div className="2xl:space-y-[1.667vw] md:max-2xl:space-y-6 space-y-4 relative">
|
||||
<h1 className="2xl:text-[5vw] md:max-2xl:text-7xl text-[32px] leading-none tracking-[-0.07em] font-mixcase-unmixed font-medium whitespace-pre-line">
|
||||
{`Rove Home HQ —
|
||||
Work looks different
|
||||
here`}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className="2xl:space-y-[1.111vw] md:max-2xl:space-y-6 relative max-md:hidden">
|
||||
<img src="/images/about-complex/hq/logo.svg" alt="" className=" md:max-2xl:flex hidden mb-[6.25vw]" />
|
||||
<h4 className="text-h4 text-[#00BED7] font-medium whitespace-pre-line">
|
||||
{`Welcome to the office you
|
||||
actually want to show up for`}
|
||||
</h4>
|
||||
<p className="text-s opacity-70 2xl:w-1/4 md:max-2xl:w-1/3">
|
||||
HQ by Rove was born out of a question: what if the
|
||||
office could feel alive again? Now, the first
|
||||
ever hospitality-branded office building in Dubai is here to
|
||||
answer it. Starting in Marasi Bay
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<img src="/images/about-complex/hq/logo.svg" alt="" className="absolute 2xl:top-[1.806vw] 2xl:right-[2.222vw] 2xl:w-[6.111vw] md:max-2xl:hidden w-[17.778vw] max-md:left-1/2 max-md:top-[39.444vw] max-md:-translate-x-1/2" />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div className="space-y-6 bg-white px-4 py-8 md:hidden">
|
||||
<h4 className="text-h4 text-[#00BED7] font-medium whitespace-pre-line ">
|
||||
{`Welcome to the office you
|
||||
actually want to show up for`}
|
||||
</h4>
|
||||
<p className="text-s opacity-70 2xl:w-1/4 md:max-2xl:w-1/3">
|
||||
HQ by Rove was born out of a question: what if the
|
||||
office could feel alive again? Now, the first
|
||||
ever hospitality-branded office building in Dubai is here to
|
||||
answer it. Starting in Marasi Bay
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* Slider */}
|
||||
<div className="2xl:sticky relative 2xl:top-[-134vw]">
|
||||
<section
|
||||
className="bg-white w-full overflow-clip 2xl:h-[calc(27.639vw*7)] 2xl:pt-[9.444vw] 2xl:px-[2.222vw] 2xl:pb-[2.222vw] md:max-2xl:pt-[104px] md:max-2xl:px-6 md:max-2xl:pb-8 pt-16 px-4 pb-8"
|
||||
ref={target}
|
||||
>
|
||||
<div className="flex flex-col 2xl:gap-[2.222vw] 2xl:sticky top-[5vw]">
|
||||
<div className="flex flex-col items-center 2xl:gap-[2.222vw]">
|
||||
<h2 className="font-mixcase-unmixed text-h1 text-center whitespace-pre-line max-md:mb-[24px] md:max-2xl:mb-8 opacity-100">
|
||||
<span className="opacity-40">More than an office,</span> <br className="2xl:hidden" /> a lifestyle.
|
||||
</h2>
|
||||
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal max-md:mb-12 md:max-2xl:mb-16">
|
||||
{`Living rooms became boardrooms, kitchens became creative hubs.
|
||||
But as the world returned, the office didn’t keep up. HQ by Rove is the
|
||||
answer - an office with a living touch.`}
|
||||
</p>
|
||||
</div>
|
||||
<AboutHQScrollSlider
|
||||
scrollYProgress={scrollYProgress}
|
||||
/>
|
||||
<AboutHQSliderTablet />
|
||||
<AboutHQSliderMobile />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* Features */}
|
||||
<div className="flex relative bg-white flex-col items-center pt-[4.444vw] px-8 gap-[4.444vw] max-md:px-[4.444vw] max-2xl:pr-[3.125vw] max-2xl:-mr-[3.125vw] max-2xl:p-6 max-2xl:items-start max-2xl:gap-[4.167vw]">
|
||||
<h1 className="font-mixcase-unmixed 2xl:text-[3.889vw] text-[#0D1922] tracking-[-0.05em] max-md:text-2xl max-2xl:text-[7.292vw] max-2xl:self-center">
|
||||
Dubai, <span className="text-[#0D192266]">within reach</span>
|
||||
</h1>
|
||||
<UnitTypesSliderMobile />
|
||||
<div
|
||||
className="z-1 flex w-full text-[#0D1922]/40 gap-[1.111vw] max-md:hidden
|
||||
max-2xl:overflow-x-auto max-2xl:self-start max-2xl:snap-x max-2xl:snap-mandatory
|
||||
max-2xl:[scrollbar-width:none] max-2xl:mt-[4.167vw]"
|
||||
>
|
||||
{hqDescription.map((descriptionItem) => (
|
||||
<div
|
||||
key={descriptionItem.title}
|
||||
className="2xl:flex-1 text-center flex flex-col gap-[1.111vw] cursor-pointer hover:text-[#0D1922B2] transition-all duration-200
|
||||
max-2xl:w-[45.833vw] max-2xl:h-[12.76vw] max-2xl:shrink-0"
|
||||
onClick={() =>
|
||||
setSelectedCategorySlider(descriptionItem.title )
|
||||
}
|
||||
>
|
||||
<div className="h-[2px] bg-gray-300 w-full"></div>
|
||||
<h5
|
||||
className={clsx(
|
||||
"text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500]",
|
||||
descriptionItem.title === selectedCategorySlider &&
|
||||
"text-[#00BED7]"
|
||||
)}
|
||||
>
|
||||
{descriptionItem.title}
|
||||
</h5>
|
||||
<p
|
||||
className={clsx(
|
||||
"text-s leading-[125%] tracking-[-0.02em] w-[16.389vw] self-center max-2xl:w-[30.729vw] ",
|
||||
descriptionItem.title === selectedCategorySlider &&
|
||||
"text-[#0D1922]"
|
||||
)}
|
||||
>
|
||||
{descriptionItem.description}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<AnimatePresence mode="wait">
|
||||
<div
|
||||
ref={sliderRef}
|
||||
className="flex flex-col gap-8 max-md:hidden"
|
||||
>
|
||||
<motion.div
|
||||
key={`slider-${selectedCategorySlider}`}
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
animate={
|
||||
isSliderInView
|
||||
? { opacity: 1, y: 0 }
|
||||
: { opacity: 0, y: 140 }
|
||||
}
|
||||
exit={{ opacity: 0, y: -40 }}
|
||||
transition={{ duration: 0.6, ease: "easeIn" }}
|
||||
>
|
||||
<UnitTypesSlider categoryName={selectedCategorySlider} />
|
||||
</motion.div>
|
||||
</div>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Apartments */}
|
||||
<div className="text-center relative w-full flex flex-col items-center gap-[2.222vw] bg-white max-md:gap-[6.667vw] max-2xl:gap-[3.125vw]">
|
||||
<h1 className="font-mixcase-unmixed text-[3.889vw] text-[#0D1922] w -[44.861vw] leading-[100%] tracking-[-0.05em] pt-[8.056vw] max-md:text-[6.667vw] max-md:w-full max-2xl:text-[7.292vw] max-2xl:w-[84.115vw]">
|
||||
{`Modular Office Collection:`}
|
||||
<p className="opacity-40">
|
||||
Combinable units
|
||||
</p>
|
||||
</h1>
|
||||
<p className="text-s text-[#0D1922B2] leading-[140%] tracking-[-0.02em] whitespace-pre-line">
|
||||
{`Enjoy the option to combine 2 offices and create a
|
||||
larger space and configuration.`}
|
||||
</p>
|
||||
<div className="flex gap-4 relative max-md:flex-col max-md:gap-[2.222vw] max-md:w-full max-md:px-[4.444vw] max-2xl:mt-[7.292vw]">
|
||||
<div
|
||||
className="w-[19.028vw] text-[#0D1922] h-[27.778vw] p-[1.667vw] rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Studio.png)] bg-[length:16.806vw_16.806vw] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[75.556vw] max-md:bg-[length:47.778vw_47.778vw] max-md:p-[4.444vw] max-2xl:w-[25.521vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Studio
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
className="w-10 h-10 rounded-full bg-[#0D1922] flex items-center justify-center absolute left-[18.500vw] self-center
|
||||
max-md:top-[71.111vw] max-md:left-[45vw] max-2xl:top-[14.583vw] max-2xl:left-[24vw]"
|
||||
>
|
||||
<span className="w-5 h-5 text-white">
|
||||
<PlusIcon />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-[19.028vw] text-[#0D1922] h-[27.778vw] p-6 rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Studio.png)] bg-[length:16.806vw_16.806vw] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[75.556vw] max-md:bg-[length:47.778vw_47.778vw] max-md:p-[4.444vw] max-2xl:w-[25.521vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Studio
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
className="w-10 h-10 rounded-full bg-[#0D1922] flex items-center justify-center absolute left-[38.333vw] self-center
|
||||
max-md:top-[148.611vw] max-md:left-[45vw] max-2xl:top-[14.583vw] max-2xl:left-[52vw]"
|
||||
>
|
||||
<span className="w-5 h-5 text-white">
|
||||
<EqualIcon />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-[30.972vw] text-[#0D1922] h-[27.778vw] p-6 rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Deluxe.png)] bg-[length:25vw_25vw] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[111.111vw] max-md:bg-[length:71.111vw_71.111vw] max-md:p-[4.444vw] max-2xl:w-[40.625vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Deluxe
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<h5 className="2xl:hidden text-h5 text-[#0D1922B2] max-md:block">
|
||||
or
|
||||
</h5>
|
||||
<div className="flex gap-4 relative max-md:flex-col max-md:gap-[2.222vw] max-md:w-full max-md:px-[4.444vw]">
|
||||
<div
|
||||
className="w-[19.028vw] text-[#0D1922] h-[27.778vw] p-6 rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Studio.png)] bg-[length:16.806vw_16.806vw] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[75.556vw] max-md:bg-[length:38.889vw_52.5vw] max-md:p-[4.444vw] max-2xl:w-[25.521vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Studio
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
className="w-10 h-10 rounded-full bg-[#0D1922] flex items-center justify-center absolute left-[18.500vw] self-center
|
||||
max-md:top-[71.111vw] max-md:left-[45vw] max-2xl:top-[14.583vw] max-2xl:left-[24vw]"
|
||||
>
|
||||
<span className="w-5 h-5 text-white">
|
||||
<PlusIcon />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-[30.972vw] text-[#0D1922] h-[27.778vw] p-6 rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Deluxe.png)] bg-[length:25vw_25vw] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[75.556vw] max-md:bg-[length:71.111vw_71.111vw] max-md:p-[4.444vw] max-2xl:w-[33.073vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Deluxe
|
||||
</h4>
|
||||
</div>
|
||||
<div
|
||||
className="w-10 h-10 rounded-full bg-[#0D1922] flex items-center justify-center absolute left-[50.300vw] self-center
|
||||
max-md:top-[148.611vw] max-md:left-[45vw] max-2xl:top-[14.583vw] max-2xl:left-[59vw]"
|
||||
>
|
||||
<span className="w-5 h-5 text-white">
|
||||
<EqualIcon />
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="w-[43.125vw] text-[#0D1922] h-[27.778vw] p-6 rounded-2xl bg-[#F3F3F2] text-left bg-[url(/images/about-complex/hq/combinable/Executive.png)] bg-no-repeat bg-center
|
||||
max-md:w-full max-md:h-[111.111vw] 2xl:bg-[length:36.111vw-36.111vw] md:bg-[length:30.208vw_30.208vw] bg-[length:91.111vw_91.111vw] max-md:p-[4.444vw] max-2xl:w-[33.073vw] max-2xl:h-[34.375vw]"
|
||||
>
|
||||
<h4 className="text-h4 tracking-[-0.02em] font-[500] max-md:text-h5">
|
||||
Executive
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Map */}
|
||||
<section className="bg-white relative w-full overflow-clip flex flex-col gap-[3.333vw] 2xl:pt-[9.444vw] 2xl:px-[2.222vw] 2xl:pb-[2.222vw] md:max-2xl:pt-[104px] md:max-2xl:px-6 pt-16 px-4 pb-8 md:max-2xl:pb-6 md:max-2xl:gap-[6.25vw]">
|
||||
<div className="flex flex-col gap-[2.222vw] items-center max-md:gap-[8.889vw] md:max-2xl:gap-[4.167vw]">
|
||||
<h2 className="text-h1 font-mixcase-unmixed">
|
||||
Seamlessly connected
|
||||
</h2>
|
||||
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:mb-[48px] max-md:whitespace-normal">
|
||||
{`From the Dubai Canal at your doorstep to Sheikh Zayed Road in minutes, with
|
||||
Downtown, DIFC and d3 all close by, you’re never far from the city’s pulse.`}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-6 grid-rows-5 gap-x-[1.111vw] gap-y-[0.556vw] max-2xl:hidden">
|
||||
{marasiDriveMapCards.map((card) => (
|
||||
<MarasiDriveMapCard {...card} key={card.title} />
|
||||
))}
|
||||
<div className="col-start-3 col-span-full row-start-1 row-span-full">
|
||||
<img
|
||||
src="/images/about-complex/marasi-drive/map/map.png"
|
||||
alt=""
|
||||
className="object-cover size-full 2xl:rounded-[1.667vw]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<MarasiDriveMapMobile />
|
||||
</section>
|
||||
|
||||
{/* Brochures */}
|
||||
<section className="bg-white relative w-full overflow-clip flex items-stretch justify-center gap-[1.111vw] 2xl:px-[10.278vw] 2xl:pt-[9.444vw] 2xl:pb-[15vw] md:max-2xl:py-[104px] md:mx-2xl:px-6 max-md:pt-20 max-md:pb-12 px-4 max-2xl:flex-col-reverse md:max-2xl:gap-[6.25vw] md:max-2xl:px-6 max-mdmb-[13.333vw]">
|
||||
<div className="flex-shrink-0 2xl:w-[39.167vw] 2xl:h-[19.861vw] md:w-full md:h-[52.083vw] w-[91.111vw] h-[111.111vw]">
|
||||
<img
|
||||
src="/images/about-complex/hq/brochures.jpg"
|
||||
className="object-cover size-full rounded-[1.667vw] max-md:mt-[48px] max-md:aspect-[328/400] max-md:rounded-[6.667vw] md:max-2xl:rounded-[3.125vw] md:max-2xl:aspect-[720/400]"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div className="px-[2.778vw] flex flex-col gap-[3.333vw] max-2xl:px-0 md:max-2xl:gap-[6.25vw]">
|
||||
<div className="space-y-[1.111vw]">
|
||||
<h2 className="whitespace-pre-line text-h2 font-medium max-2xl:mb-4">
|
||||
{`Work looks different here`}
|
||||
</h2>
|
||||
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal max-md:mb-12 md:max-2xl:mb-16">
|
||||
{`Living rooms became boardrooms, kitchens became creative hubs.
|
||||
But as the world returned, the office didn’t keep up. HQ by Rove is the
|
||||
answer - an office with a living touch.`}
|
||||
<p className="opacity-40 text-s max-md:mb-[32px] md:max-2xl:max-w-[57.943vw]">
|
||||
{`HQ by Rove sets its own standard. A place designed with people at
|
||||
its heart, where hospitality meets productivity, and work finds its flow.`}
|
||||
</p>
|
||||
</div>
|
||||
<ScrollSlider
|
||||
scrollYProgress={scrollYProgress}
|
||||
images={marasiDriveFeatures}
|
||||
/>
|
||||
|
||||
{/* TODO: update */}
|
||||
<MarasiDriveNeighboursSliderTablet />
|
||||
<MarasiDriveNeighboursSliderMobile />
|
||||
<div className="space-y-[1.111vw]">
|
||||
<h5 className="text-h5 font-medium max-md:mb-[16px] md:max-2xl:mb-[2.083vw]">
|
||||
Download our brochures
|
||||
</h5>
|
||||
<div className="space-y-[0.833vw] max-md:space-y-[3.333vw] md:max-2xl:space-y-[1.563vw]">
|
||||
<BrochureButton
|
||||
title={"Main Brochure"}
|
||||
link="/files/marasi-drive/Main Brochure.pdf"
|
||||
/>
|
||||
<BrochureButton
|
||||
title={"Technical Brochure"}
|
||||
link="/files/marasi-drive/Amenties Brochure.pdf"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
)
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { motion, AnimatePresence, useTransform, MotionValue, useMotionValueEvent } from 'motion/react';
|
||||
import { hqFeatures } from "../../data/aboutHQ"
|
||||
import { useState } from 'react';
|
||||
|
||||
export default function AboutHQSlider({ scrollYProgress }: { scrollYProgress: MotionValue<number> }) {
|
||||
const percentageOfScroll = useTransform(scrollYProgress, [0.2, 0.8], [0, 100]);
|
||||
const offset = useTransform(scrollYProgress, [1/5, 4/5], ["4%", "-128%"]);
|
||||
const imageBaseWidth = "20.139vw";
|
||||
const imageExpandedWidth = "36.944vw";
|
||||
const [activeImageIndex, setActiveImageIndex] = useState(1);
|
||||
|
||||
|
||||
useMotionValueEvent(percentageOfScroll, "change", (latest) => {
|
||||
const thresholds = [10, 30, 50, 70, 90];
|
||||
const newIndex = thresholds.findIndex(threshold => latest <= threshold) + 1;
|
||||
setActiveImageIndex(newIndex === 0 ? 6 : newIndex);
|
||||
});
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="flex items-center 2xl:gap-[4.965vw] gap-[9.375vw] 2xl:min-h-[27.639vw] max-2xl:hidden"
|
||||
style={{ x: offset }}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{hqFeatures.map(({ name, image }, index) => (
|
||||
<motion.div
|
||||
key={name}
|
||||
className="flex flex-col shrink-0 items-center 2xl:gap-[1.667vw] gap-6"
|
||||
animate={{ width: index === activeImageIndex ? imageExpandedWidth : imageBaseWidth }}
|
||||
>
|
||||
<img
|
||||
src={image}
|
||||
alt={name}
|
||||
className="2xl:rounded-[1.667vw] rounded-[3.125vw] aspect-[290/205] object-cover w-full pointer-events-none"
|
||||
/>
|
||||
<p className={"text-h4 text-center font-medium"}>{name}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { hqFeatures } from "../../data/aboutHQ";
|
||||
import { useRef } from "react";
|
||||
import CustomScrollBar from "../ui/ScrollBar";
|
||||
|
||||
function AboutHQSliderMobile() {
|
||||
const hqFeaturesRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={hqFeaturesRef}
|
||||
className="max-md:flex hidden max-md:flex-nowrap max-md:overflow-x-scroll max-md:gap-x-[8px] max-md:overflow-y-hidden max-md:justify-start max-md:snap-x max-md:snap-mandatory [&::-webkit-scrollbar]:h-[1.111vw] [&::-webkit-scrollbar]:w-[none] [&::-webkit-scrollbar-thumb]:bg-transparent [&::-webkit-scrollbar-thumb]:w-4 [&::-webkit-scrollbar-thumb]:rounded-full max-md:-mx-4 max-md:px-4"
|
||||
>
|
||||
{hqFeatures.map(({ image, name }) => (
|
||||
<div
|
||||
key={name}
|
||||
className="relative md:max-2xl:w-[30.208vw] max-md:w-full max-md:max-w-[520px] max-md:flex-shrink-0 max-md:snap-center"
|
||||
>
|
||||
<img
|
||||
src={image}
|
||||
alt={name}
|
||||
className="object-cover object-center 2xl:rounded-[1.667vw] max-md:!aspect-[328/430] max-md:rounded-2xl max-md:max-h-[690px]"
|
||||
/>
|
||||
<div className="md:hidden text-black text-h5 mx-auto text-center text-nowrap mt-4 mb-6 font-medium">
|
||||
{name}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<CustomScrollBar
|
||||
containerRef={hqFeaturesRef}
|
||||
inlinePadding={16}
|
||||
trackStyle="md:hidden"
|
||||
thumbStyle="md:hidden"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AboutHQSliderMobile;
|
||||
@@ -0,0 +1,100 @@
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import { useState } from "react";
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
import { hqFeatures } from "../../data/aboutHQ";
|
||||
import Button from "../ui/Button";
|
||||
import ChevronLeftIcon from "../icons/ChevronLeftIcon";
|
||||
import clsx from "clsx";
|
||||
import ChevronRightIcon from "../icons/ChevronRightIcon";
|
||||
|
||||
function AboutHQSliderTablet() {
|
||||
const [currentIndex, setCurrentIndex] = useState(1);
|
||||
|
||||
const handlers = useSwipeable({
|
||||
onSwipedLeft: () =>
|
||||
setCurrentIndex(
|
||||
Math.min(currentIndex + 1, hqFeatures.length - 1)
|
||||
),
|
||||
onSwipedRight: () => setCurrentIndex(Math.max(currentIndex - 1, 0)),
|
||||
preventScrollOnSwipe: true,
|
||||
touchEventOptions: {
|
||||
passive: false,
|
||||
},
|
||||
trackMouse: true,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative hidden md:max-2xl:block min-h-[calc(47.135vw*11/9)]"
|
||||
{...handlers}
|
||||
>
|
||||
<motion.div
|
||||
className="flex items-center gap-[9.375vw]"
|
||||
animate={{
|
||||
transform: `translateX(calc(-31.641vw - 24px - ${
|
||||
currentIndex - 1
|
||||
} * 47.135vw))`,
|
||||
}}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{hqFeatures.map(({ image, name }, index) => (
|
||||
<motion.div
|
||||
animate={{
|
||||
width: index === currentIndex ? "69.141vw" : "37.76vw",
|
||||
}}
|
||||
exit={{
|
||||
width: index !== currentIndex ? "69.141vw" : "37.76vw",
|
||||
}}
|
||||
key={name}
|
||||
className="shrink-0 flex flex-col"
|
||||
>
|
||||
<motion.img
|
||||
src={image}
|
||||
alt={name}
|
||||
className="object-cover rounded-[3.125vw] pointer-events-none aspect-[12/9] object-center"
|
||||
animate={{
|
||||
marginBottom: index !== currentIndex ? "32px" : "24px",
|
||||
}}
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
/>
|
||||
<p
|
||||
className={clsx(
|
||||
"text-h4 text-center font-medium",
|
||||
index !== currentIndex && "opacity-40"
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
<Button
|
||||
onlyIcon
|
||||
disabled={currentIndex === 0}
|
||||
onClick={() => setCurrentIndex(Math.max(currentIndex - 1, 0))}
|
||||
className="absolute left-[calc((100%-69.141vw)/2-56px)] bottom-1/2"
|
||||
>
|
||||
<span className="size-5">
|
||||
<ChevronLeftIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
onlyIcon
|
||||
disabled={currentIndex === hqFeatures.length - 1}
|
||||
className="absolute right-[calc((100%-69.141vw)/2-56px)] bottom-1/2"
|
||||
onClick={() =>
|
||||
setCurrentIndex(
|
||||
Math.min(currentIndex + 1, hqFeatures.length - 1)
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="size-5">
|
||||
<ChevronRightIcon />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AboutHQSliderTablet;
|
||||
@@ -0,0 +1,136 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import ArrowLeftIcon from "../icons/ArrowLeftIcon";
|
||||
import ArrowRightIcon from "../icons/ArrowRightIcon";
|
||||
import { hqSlider } from "../../data/aboutHQ";
|
||||
import { AnimatePresence, motion } from "motion/react";
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
import Button from "../ui/Button";
|
||||
|
||||
function UnitTypesSlider({
|
||||
categoryName,
|
||||
}: {
|
||||
categoryName: "Modular Office Collection" | "A La Carte" | "Loft Office Collection";
|
||||
}) {
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
const [direction, setDirection] = useState(-1);
|
||||
|
||||
const handleNextSlide = () => {
|
||||
if (currentSlide < hqSlider[categoryName].length - 1) {
|
||||
setDirection(1);
|
||||
setCurrentSlide(currentSlide + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePreviousSlide = () => {
|
||||
if (currentSlide > 0) {
|
||||
setDirection(-1);
|
||||
setCurrentSlide(currentSlide - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handlers = useSwipeable({
|
||||
onSwipedLeft: handleNextSlide,
|
||||
onSwipedRight: handlePreviousSlide,
|
||||
preventScrollOnSwipe: true,
|
||||
touchEventOptions: {
|
||||
passive: false,
|
||||
},
|
||||
trackMouse: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentSlide(0);
|
||||
}, [categoryName]);
|
||||
|
||||
useEffect(() => {
|
||||
if(currentSlide === 0) {
|
||||
setDirection(1);
|
||||
}
|
||||
else if(currentSlide === hqSlider[categoryName].length - 1) {
|
||||
setDirection(-1);
|
||||
}
|
||||
}, [currentSlide]);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...handlers}
|
||||
className="relative w-[63.333vw] h-[27.639vw] rounded-3xl overflow-hidden max-md:w-[91.111vw] max-md:h-[110.556vw] max-2xl:w-[93.75vw] max-2xl:h-[51.823vw]"
|
||||
>
|
||||
<AnimatePresence custom={direction} initial={false}>
|
||||
<motion.div
|
||||
key={currentSlide}
|
||||
className="absolute inset-0 bg-cover bg-no-repeat bg-center before:absolute before:inset-0 before:bg-[#0D1922]/20 before:z-[1]"
|
||||
style={{
|
||||
backgroundImage: `url(${hqSlider[categoryName][currentSlide].image})`,
|
||||
}}
|
||||
custom={direction}
|
||||
initial={{ x: direction > 0 ? "100%" : "-100%" }}
|
||||
animate={{ x: 0, transition: { duration: 0.5, ease: "easeInOut" } }}
|
||||
exit={{
|
||||
x: direction < 0 ? "100%" : "-100%",
|
||||
transition: { duration: 0.8, ease: "easeInOut" },
|
||||
}}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
<div className="z-[1] flex relative flex-col justify-between p-6 w-full h-full">
|
||||
<div className="flex flex-col gap-4">
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.h3
|
||||
key={`title-${currentSlide}`}
|
||||
className="text-h3 max-md:text-h5 text-white"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
{hqSlider[categoryName][currentSlide].title}
|
||||
</motion.h3>
|
||||
</AnimatePresence>
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.p
|
||||
key={`desc-${currentSlide}`}
|
||||
className="text-s w-[19.861vw] tracking-[-0.02em] leading-[140%] text-white max-md:w-full max-md:text-caption-m max-2xl:w-[37.24vw]"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
{hqSlider[categoryName][currentSlide].description}
|
||||
</motion.p>
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
<div className="flex items-center gap-[0.556vw] relative max-md:gap-[2.222vw]">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onlyIcon
|
||||
onClick={handlePreviousSlide}
|
||||
disabled={currentSlide === 0}
|
||||
className="disabled:!bg-[#fff] disabled:!bg-opacity-80 disabled:!cursor-default hover:bg-[#F3F3F2] transition-all duration-200"
|
||||
>
|
||||
<span className="size-5">
|
||||
<ArrowLeftIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<div className="text-s text-white">
|
||||
{currentSlide + 1}/{hqSlider[categoryName].length}
|
||||
</div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onlyIcon
|
||||
onClick={handleNextSlide}
|
||||
disabled={
|
||||
currentSlide === hqSlider[categoryName].length - 1
|
||||
}
|
||||
className="disabled:!bg-[#fff] disabled:!bg-opacity-80 disabled:!cursor-default hover:bg-[#F3F3F2] transition-all duration-200"
|
||||
>
|
||||
<span className="size-5">
|
||||
<ArrowRightIcon />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default UnitTypesSlider;
|
||||
@@ -0,0 +1,87 @@
|
||||
import { useScroll, useTransform, motion } from 'motion/react';
|
||||
import { useRef } from 'react'
|
||||
import UnitTypesSlider from './UnitTypesSlider';
|
||||
|
||||
export default function UnitTypesSliderMobile() {
|
||||
const sliderMobileRef = useRef(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: sliderMobileRef,
|
||||
offset: ["start start", "end end"],
|
||||
});
|
||||
|
||||
const opacityFirstSlide = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 1 / 3],
|
||||
[1, 0]
|
||||
);
|
||||
const opacitySecondSlide = useTransform(
|
||||
scrollYProgress,
|
||||
[ 2 / 3, 1],
|
||||
[ 1, 0]
|
||||
);
|
||||
const opacityThirdSlide = useTransform(
|
||||
scrollYProgress,
|
||||
[ 2 / 3, 1],
|
||||
[ 1, 1]
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className="md:hidden flex flex-col gap-[6.667vw]"
|
||||
ref={sliderMobileRef}
|
||||
>
|
||||
<motion.div
|
||||
className="sticky top-[18vw] h-full flex flex-col gap-[6.667vw]"
|
||||
style={{ opacity: opacityFirstSlide }}
|
||||
>
|
||||
<div className="h-[2px] bg-gray-300 w-full"></div>
|
||||
<h5
|
||||
className={
|
||||
"text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500] text-[#00BED7] text-center р-10"
|
||||
}
|
||||
>
|
||||
Modular Office Collection
|
||||
</h5>
|
||||
<p className="text-m text-center text-[#0D1922]/70 mt-[-2.222vw]">
|
||||
Spaces that easily expand and adapt
|
||||
</p>
|
||||
<UnitTypesSlider categoryName="Modular Office Collection" />
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="sticky h-full top-[18vw] flex flex-col gap-[6.667vw] bg-white"
|
||||
style={{ opacity: opacitySecondSlide }}
|
||||
>
|
||||
<div className="h-[2px] bg-gray-300 w-full"></div>
|
||||
<h5
|
||||
className={
|
||||
"text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500] text-[#00BED7] text-center"
|
||||
}
|
||||
>
|
||||
A La Carte
|
||||
</h5>
|
||||
<p className="text-m text-center text-[#0D1922]/70 mt-[-2.222vw]">
|
||||
Bespoke offices designed around you
|
||||
</p>
|
||||
<UnitTypesSlider categoryName="A La Carte" />
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className="sticky h-full top-[18vw] flex flex-col gap-[6.667vw] bg-white"
|
||||
style={{ opacity: opacityThirdSlide }}
|
||||
>
|
||||
<div className="h-[2px] bg-gray-300 w-full"></div>
|
||||
<h5
|
||||
className={
|
||||
"text-h5 tracking-[-0.02em] mt-[0.556vw] font-[500] text-[#00BED7] text-center"
|
||||
}
|
||||
>
|
||||
Loft Office Collection
|
||||
</h5>
|
||||
<p className="text-m text-center text-[#0D1922]/70 mt-[-2.222vw] h-10">
|
||||
Double-height ceilings and the warm atmosphere of home
|
||||
</p>
|
||||
<UnitTypesSlider categoryName="Loft Office Collection" />
|
||||
</motion.div>
|
||||
{/* <div className="h-[40vw]"></div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -28,7 +28,7 @@ function AboutMarasiDrive() {
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="2xl:sticky relative 2xl:top-[4.444vw]">
|
||||
<section className="w-full 2xl:h-[calc(100dvh-4.444vw)] relative md:h-[calc(100dvh-4rem)] h-[calc(100dvh-3.15rem)] flex flex-col justify-between bg-white 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 overflow-hidden">
|
||||
<section className="w-full 2xl:h-[calc(100dvh-4.444vw)] relative md:h-[calc(100dvh-4rem)] h-[calc(100dvh-3.15rem)] md:max-h-[125vw] max-md:max-h-[162.222vw] flex flex-col justify-between bg-white 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 overflow-hidden">
|
||||
<div className="2xl:size-[140vw] md:size-[130vw] size-[120vw] rounded-full absolute 2xl:top-1/2 2xl:left-[104vw] md:top-[100%] left-1/2 top-[100%] md:left-1/2 -translate-x-1/2 -translate-y-1/2 bg-[#F3F3F2]" />
|
||||
<img
|
||||
src="/images/about-complex/marasi-drive/main_bg.png"
|
||||
|
||||
@@ -6,7 +6,7 @@ function MarasiDriveMapMobile() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
<div className="hidden relative max-md:flex flex-col">
|
||||
<div className="hidden relative max-2xl:flex flex-col">
|
||||
<div className="max-md:aspect-[328/544] md:max-2xl:aspect[1/1] max-2xl:mb-4">
|
||||
<img
|
||||
src="/images/about-complex/marasi-drive/map/map.png"
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import { motion, AnimatePresence, useTransform, MotionValue } from 'motion/react';
|
||||
|
||||
interface ScrollSliderProps {
|
||||
scrollYProgress: MotionValue<number>;
|
||||
images: { name: string; image: string }[];
|
||||
}
|
||||
|
||||
export default function ScrollSlider({ scrollYProgress, images }: ScrollSliderProps) {
|
||||
const x = useTransform(scrollYProgress, [0, 1 / 3], ["4.236vw", "-20.868vw"]);
|
||||
|
||||
const width1 = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 1 / 3],
|
||||
["20.139vw", "20.139vw"]
|
||||
);
|
||||
|
||||
const width2 = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 1 / 3],
|
||||
["36.944vw", "20.139vw"]
|
||||
);
|
||||
|
||||
const width3 = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 1 / 3],
|
||||
["20.139vw", "36.944vw"]
|
||||
);
|
||||
|
||||
const width4 = useTransform(
|
||||
scrollYProgress,
|
||||
[0, 1 / 3],
|
||||
["20.139vw", "20.139vw"]
|
||||
);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className="flex items-center 2xl:gap-[4.965vw] gap-[9.375vw] 2xl:min-h-[27.639vw] max-2xl:hidden"
|
||||
style={{ x }}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{images.map(({ name, image }, index) => (
|
||||
<motion.div
|
||||
key={name}
|
||||
className="flex flex-col shrink-0 items-center 2xl:gap-[1.667vw] gap-6"
|
||||
style={{ width: [width1, width2, width3, width4][index] }}
|
||||
>
|
||||
<img
|
||||
src={image}
|
||||
alt={name}
|
||||
className="2xl:rounded-[1.667vw] rounded-[3.125vw] aspect-[290/205] object-cover w-full pointer-events-none"
|
||||
/>
|
||||
<p className={"text-h4 text-center font-medium"}>{name}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
export const hqFeatures = [
|
||||
{
|
||||
name: "Reception Lounge",
|
||||
image: "/images/about-complex/hq/features/reception_lounge.png",
|
||||
},
|
||||
{
|
||||
name: "Beauty Lounge",
|
||||
image: "/images/about-complex/hq/features/beauty_lounge.png",
|
||||
},
|
||||
{
|
||||
name: "Spa Pod",
|
||||
image: "/images/about-complex/hq/features/spa_pod.png",
|
||||
},
|
||||
{
|
||||
name: "Rentable Space",
|
||||
image: "/images/about-complex/hq/features/rentable_space.png",
|
||||
},
|
||||
{
|
||||
name: "Upresso Animated",
|
||||
image: "/images/about-complex/hq/features/upresso_animated.png",
|
||||
},
|
||||
{
|
||||
name: "Podium",
|
||||
image: "/images/about-complex/hq/features/podium.png",
|
||||
},
|
||||
{
|
||||
name: "Foodhall",
|
||||
image: "/images/about-complex/hq/features/foodhall.png",
|
||||
},
|
||||
{
|
||||
name: "Spa Pool",
|
||||
image: "/images/about-complex/hq/features/spa_pool.png",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const hqDescription = [
|
||||
{
|
||||
title: "Modular Office Collection",
|
||||
description: "Spaces that easily expand and adapt",
|
||||
},
|
||||
{
|
||||
title: "A La Carte",
|
||||
description: "Bespoke offices designed around you",
|
||||
},
|
||||
{
|
||||
title: "Loft Office Collection",
|
||||
description: "Double-height ceilings and the warm atmosphere of home",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export const hqSlider = {
|
||||
"Modular Office Collection": [
|
||||
{
|
||||
title: "Studio",
|
||||
description: "Efficient spaces that merge intelligent design with everyday practicality, available in open and closed layouts to suit your style.",
|
||||
image: "/images/about-complex/hq/slider/modularOffice/Studio.png",
|
||||
},
|
||||
{
|
||||
title: "Deluxe",
|
||||
description: "Double the size, enjoy dedicated meeting rooms, upgraded furnishings, and the option to tailor.",
|
||||
image: "/images/about-complex/hq/slider/modularOffice/Deluxe.png",
|
||||
},
|
||||
{
|
||||
title: "Executive",
|
||||
description: "Triple-sized with expanded seating, generous storage, and versatile layouts - available in open, semi-open, or closed configurations to suit growing teams.",
|
||||
image: "/images/about-complex/hq/slider/modularOffice/Executive.png",
|
||||
},
|
||||
{
|
||||
title: "Simplex Edge",
|
||||
description: "Nestled on the edge, most expansive setting, with generous layouts premium furniture, and a statement-making workspace.",
|
||||
image: "/images/about-complex/hq/slider/modularOffice/SimplexEdge.png",
|
||||
},
|
||||
],
|
||||
"A La Carte": [
|
||||
{
|
||||
title: "Semi-Olympic Leisure Pool",
|
||||
description:
|
||||
"Overlooking the city, enjoy a leisurely swim, do your daily 25-meter laps or just unwind at one of the cozy cabanas,",
|
||||
image: "/images/about-complex/dubai-marina/fitness1.jpg",
|
||||
},
|
||||
{
|
||||
title: "Boutique Fitness Studio",
|
||||
description:
|
||||
"Elevate your fitness regime at flagship Crank Ride & Shape studios – blending fitness, fun, and thrill vibes.",
|
||||
image: "/images/about-complex/dubai-marina/fitness2.jpg",
|
||||
},
|
||||
],
|
||||
"Loft Office Collection": [
|
||||
{
|
||||
title: "Loft Edge",
|
||||
description:
|
||||
"Soaring double-height ceilings, curated design details, and a warm living touch that makes the office feel like home.",
|
||||
image: "/images/about-complex/hq/slider/loftOffice/LoftEdge.png",
|
||||
},
|
||||
{
|
||||
title: "Penthouse Lofts",
|
||||
description:
|
||||
"Enjoy more of space, style, and comfort. With integrated stair seating, a private kitchenette, and an in-office washroom, these lofts blend thoughtful design with premium interiors to create a workspace that feels truly complete.",
|
||||
image: "/images/about-complex/hq/slider/loftOffice/PenthouseLofts.png",
|
||||
},
|
||||
{
|
||||
title: "Presedential Loft",
|
||||
description:
|
||||
"Step into a panoramic Presidential Loft Office on the highest floors - spacious, light-filled, and beautifully designed with a living touch",
|
||||
image: "/images/about-complex/hq/slider/loftOffice/PresidentialLoft.png",
|
||||
}
|
||||
]
|
||||
};
|
||||