diff --git a/public/images/about-complex/hq/brochures.jpg b/public/images/about-complex/hq/brochures.jpg new file mode 100644 index 0000000..2488b1e Binary files /dev/null and b/public/images/about-complex/hq/brochures.jpg differ diff --git a/public/images/about-complex/hq/combinable/Deluxe.png b/public/images/about-complex/hq/combinable/Deluxe.png new file mode 100644 index 0000000..06dbe4c Binary files /dev/null and b/public/images/about-complex/hq/combinable/Deluxe.png differ diff --git a/public/images/about-complex/hq/combinable/Executive.png b/public/images/about-complex/hq/combinable/Executive.png new file mode 100644 index 0000000..40d7402 Binary files /dev/null and b/public/images/about-complex/hq/combinable/Executive.png differ diff --git a/public/images/about-complex/hq/combinable/Studio.png b/public/images/about-complex/hq/combinable/Studio.png new file mode 100644 index 0000000..5920dac Binary files /dev/null and b/public/images/about-complex/hq/combinable/Studio.png differ diff --git a/public/images/about-complex/hq/features/beauty_lounge.png b/public/images/about-complex/hq/features/beauty_lounge.png new file mode 100644 index 0000000..f23faf4 Binary files /dev/null and b/public/images/about-complex/hq/features/beauty_lounge.png differ diff --git a/public/images/about-complex/hq/features/foodhall.png b/public/images/about-complex/hq/features/foodhall.png new file mode 100644 index 0000000..6d9fd44 Binary files /dev/null and b/public/images/about-complex/hq/features/foodhall.png differ diff --git a/public/images/about-complex/hq/features/podium.png b/public/images/about-complex/hq/features/podium.png new file mode 100644 index 0000000..9f66efa Binary files /dev/null and b/public/images/about-complex/hq/features/podium.png differ diff --git a/public/images/about-complex/hq/features/reception_lounge.png b/public/images/about-complex/hq/features/reception_lounge.png new file mode 100644 index 0000000..9117d59 Binary files /dev/null and b/public/images/about-complex/hq/features/reception_lounge.png differ diff --git a/public/images/about-complex/hq/features/rentable_space.png b/public/images/about-complex/hq/features/rentable_space.png new file mode 100644 index 0000000..1f66923 Binary files /dev/null and b/public/images/about-complex/hq/features/rentable_space.png differ diff --git a/public/images/about-complex/hq/features/spa_pod.png b/public/images/about-complex/hq/features/spa_pod.png new file mode 100644 index 0000000..38f1dc1 Binary files /dev/null and b/public/images/about-complex/hq/features/spa_pod.png differ diff --git a/public/images/about-complex/hq/features/spa_pool.png b/public/images/about-complex/hq/features/spa_pool.png new file mode 100644 index 0000000..945ff2f Binary files /dev/null and b/public/images/about-complex/hq/features/spa_pool.png differ diff --git a/public/images/about-complex/hq/features/upresso_animated.png b/public/images/about-complex/hq/features/upresso_animated.png new file mode 100644 index 0000000..6298a03 Binary files /dev/null and b/public/images/about-complex/hq/features/upresso_animated.png differ diff --git a/public/images/about-complex/hq/slider/loftOffice/LoftEdge.png b/public/images/about-complex/hq/slider/loftOffice/LoftEdge.png new file mode 100644 index 0000000..b303591 Binary files /dev/null and b/public/images/about-complex/hq/slider/loftOffice/LoftEdge.png differ diff --git a/public/images/about-complex/hq/slider/loftOffice/PenthouseLofts.png b/public/images/about-complex/hq/slider/loftOffice/PenthouseLofts.png new file mode 100644 index 0000000..0fa1806 Binary files /dev/null and b/public/images/about-complex/hq/slider/loftOffice/PenthouseLofts.png differ diff --git a/public/images/about-complex/hq/slider/loftOffice/PresidentialLoft.png b/public/images/about-complex/hq/slider/loftOffice/PresidentialLoft.png new file mode 100644 index 0000000..863780d Binary files /dev/null and b/public/images/about-complex/hq/slider/loftOffice/PresidentialLoft.png differ diff --git a/public/images/about-complex/hq/slider/modularOffice/Deluxe.png b/public/images/about-complex/hq/slider/modularOffice/Deluxe.png new file mode 100644 index 0000000..0da02e1 Binary files /dev/null and b/public/images/about-complex/hq/slider/modularOffice/Deluxe.png differ diff --git a/public/images/about-complex/hq/slider/modularOffice/Executive.png b/public/images/about-complex/hq/slider/modularOffice/Executive.png new file mode 100644 index 0000000..524d10b Binary files /dev/null and b/public/images/about-complex/hq/slider/modularOffice/Executive.png differ diff --git a/public/images/about-complex/hq/slider/modularOffice/SimplexEdge.png b/public/images/about-complex/hq/slider/modularOffice/SimplexEdge.png new file mode 100644 index 0000000..a66bfe8 Binary files /dev/null and b/public/images/about-complex/hq/slider/modularOffice/SimplexEdge.png differ diff --git a/public/images/about-complex/hq/slider/modularOffice/Studio.png b/public/images/about-complex/hq/slider/modularOffice/Studio.png new file mode 100644 index 0000000..a20b13e Binary files /dev/null and b/public/images/about-complex/hq/slider/modularOffice/Studio.png differ diff --git a/src/components/AboutHQ.tsx b/src/components/AboutHQ.tsx index d7fb2c6..4a13d0f 100644 --- a/src/components/AboutHQ.tsx +++ b/src/components/AboutHQ.tsx @@ -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 ( -
- - -
- ) -} - -function AboutHQHero() { - return ( -
- -
-
- - - -
-

- {`Rove Home HQ — - Work looks different - here`} -

-
- -
- -

- {`Welcome to the office you - actually want to show up for`} -

-

- 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 -

-
- - -
- -
-
-

- {`Welcome to the office you - actually want to show up for`} -

-

- 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 -

-
-
- -
- ) -} - -function AboutHQSlider() { const target = useRef(null); const { scrollYProgress } = useScroll({ - target, + target, }); - return ( -
-
-
-
-

- More than an office, a lifestyle. + const [selectedCategorySlider, setSelectedCategorySlider] = + useState("Modular Office Collection"); + + const sliderRef = useRef(null); + const isSliderInView = useInView(sliderRef, { + once: true, + amount: 0.1, + }); + + return ( +
+ + {/* Hero */} +
+
+ +
+ + +
+

+ {`Rove Home HQ — + Work looks different + here`} +

+
+ +
+ +

+ {`Welcome to the office you + actually want to show up for`} +

+

+ 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 +

+
+ + +
+ +
+
+

+ {`Welcome to the office you + actually want to show up for`} +

+

+ 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 +

+
+
+
+ + {/* Slider */} +
+
+
+
+

+ More than an office,
a lifestyle. +

+

+ {`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.`} +

+
+ + + +
+
+
+ + {/* Features */} +
+

+ Dubai, within reach +

+ +
+ {hqDescription.map((descriptionItem) => ( +
+ setSelectedCategorySlider(descriptionItem.title ) + } + > +
+
+ {descriptionItem.title} +
+

+ {descriptionItem.description} +

+
+ ))} +
+ +
+ + + +
+
+
+ + {/* Apartments */} +
+

+ {`Modular Office Collection:`} +

+ Combinable units +

+

+

+ {`Enjoy the option to combine 2 offices and create a + larger space and configuration.`} +

+
+
+

+ Studio +

+
+
+ + + +
+
+

+ Studio +

+
+
+ + + +
+
+

+ Deluxe +

+
+
+
+ or +
+
+
+

+ Studio +

+
+
+ + + +
+
+

+ Deluxe +

+
+
+ + + +
+
+

+ Executive +

+
+
+
+ + {/* Map */} +
+
+

+ Seamlessly connected +

+

+ {`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.`} +

+
+
+ {marasiDriveMapCards.map((card) => ( + + ))} +
+ +
+
+ +
+ + {/* Brochures */} +
+
+ +
+
+
+

+ {`Work looks different here`}

-

- {`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.`} +

+ {`HQ by Rove sets its own standard. A place designed with people at + its heart, where hospitality meets productivity, and work finds its flow.`}

- - - {/* TODO: update */} - - +
+
+ Download our brochures +
+
+ + +
+
-
- - ) +

+ ) } \ No newline at end of file diff --git a/src/components/AboutHQ/AboutHQSlider.tsx b/src/components/AboutHQ/AboutHQSlider.tsx new file mode 100644 index 0000000..e56c666 --- /dev/null +++ b/src/components/AboutHQ/AboutHQSlider.tsx @@ -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 }) { + 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 ( + + + {hqFeatures.map(({ name, image }, index) => ( + + {name} +

{name}

+
+ ))} +
+
+ ); +} diff --git a/src/components/AboutHQ/AboutHQSliderMobile.tsx b/src/components/AboutHQ/AboutHQSliderMobile.tsx new file mode 100644 index 0000000..f7559d7 --- /dev/null +++ b/src/components/AboutHQ/AboutHQSliderMobile.tsx @@ -0,0 +1,40 @@ +import { hqFeatures } from "../../data/aboutHQ"; +import { useRef } from "react"; +import CustomScrollBar from "../ui/ScrollBar"; + +function AboutHQSliderMobile() { + const hqFeaturesRef = useRef(null); + + return ( + <> +
+ {hqFeatures.map(({ image, name }) => ( +
+ {name} +
+ {name} +
+
+ ))} +
+ + + ); +} + +export default AboutHQSliderMobile; diff --git a/src/components/AboutHQ/AboutHQSliderTablet.tsx b/src/components/AboutHQ/AboutHQSliderTablet.tsx new file mode 100644 index 0000000..2d9ea30 --- /dev/null +++ b/src/components/AboutHQ/AboutHQSliderTablet.tsx @@ -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 ( +
+ + + {hqFeatures.map(({ image, name }, index) => ( + + setCurrentIndex(index)} + /> +

+ {name} +

+
+ ))} +
+
+ + +
+ ); +} + +export default AboutHQSliderTablet; diff --git a/src/components/AboutHQ/UnitTypesSlider.tsx b/src/components/AboutHQ/UnitTypesSlider.tsx new file mode 100644 index 0000000..2bb7088 --- /dev/null +++ b/src/components/AboutHQ/UnitTypesSlider.tsx @@ -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 ( +
+ + 0 ? "100%" : "-100%" }} + animate={{ x: 0, transition: { duration: 0.5, ease: "easeInOut" } }} + exit={{ + x: direction < 0 ? "100%" : "-100%", + transition: { duration: 0.8, ease: "easeInOut" }, + }} + /> + +
+
+ + + {hqSlider[categoryName][currentSlide].title} + + + + + {hqSlider[categoryName][currentSlide].description} + + +
+
+ +
+ {currentSlide + 1}/{hqSlider[categoryName].length} +
+ +
+
+
+ ); +} + +export default UnitTypesSlider; \ No newline at end of file diff --git a/src/components/AboutHQ/UnitTypesSliderMobile.tsx b/src/components/AboutHQ/UnitTypesSliderMobile.tsx new file mode 100644 index 0000000..f7498e7 --- /dev/null +++ b/src/components/AboutHQ/UnitTypesSliderMobile.tsx @@ -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 ( +
+ +
+
+ Modular Office Collection +
+

+ Spaces that easily expand and adapt +

+ +
+ +
+
+ A La Carte +
+

+ Bespoke offices designed around you +

+ +
+ +
+
+ Loft Office Collection +
+

+ Double-height ceilings and the warm atmosphere of home +

+ +
+ {/*
*/} +
+ ); + } diff --git a/src/components/AboutMarasiDrive.tsx b/src/components/AboutMarasiDrive.tsx index 46326b0..a8a3bef 100644 --- a/src/components/AboutMarasiDrive.tsx +++ b/src/components/AboutMarasiDrive.tsx @@ -28,7 +28,7 @@ function AboutMarasiDrive() { return (
-
+
(null); return ( -
+
; - 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 ( - - - {images.map(({ name, image }, index) => ( - - {name} -

{name}

-
- ))} -
-
- ); -} diff --git a/src/data/aboutHQ.ts b/src/data/aboutHQ.ts index e69de29..056bb2a 100644 --- a/src/data/aboutHQ.ts +++ b/src/data/aboutHQ.ts @@ -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", + } + ] +}; \ No newline at end of file