About Marasi Drive Table Mobile

This commit is contained in:
2025-07-18 17:25:10 +05:00
parent 8bbb4413b0
commit a68d001ef9
7 changed files with 222 additions and 29 deletions
+3
View File
@@ -12,6 +12,7 @@
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"date-fns-tz": "^3.2.0",
"eruda": "^3.4.3",
"gsap": "^3.12.7",
"ky": "^1.8.1",
"motion": "^12.6.3",
@@ -314,6 +315,8 @@
"enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="],
"eruda": ["eruda@3.4.3", "", {}, "sha512-J2TsF4dXSspOXev5bJ6mljv0dRrxj21wklrDzbvPmYaEmVoC+2psylyRi70nUPFh1mTQfIBsSusUtAMZtUN+/w=="],
"esbuild": ["esbuild@0.25.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.2", "@esbuild/android-arm": "0.25.2", "@esbuild/android-arm64": "0.25.2", "@esbuild/android-x64": "0.25.2", "@esbuild/darwin-arm64": "0.25.2", "@esbuild/darwin-x64": "0.25.2", "@esbuild/freebsd-arm64": "0.25.2", "@esbuild/freebsd-x64": "0.25.2", "@esbuild/linux-arm": "0.25.2", "@esbuild/linux-arm64": "0.25.2", "@esbuild/linux-ia32": "0.25.2", "@esbuild/linux-loong64": "0.25.2", "@esbuild/linux-mips64el": "0.25.2", "@esbuild/linux-ppc64": "0.25.2", "@esbuild/linux-riscv64": "0.25.2", "@esbuild/linux-s390x": "0.25.2", "@esbuild/linux-x64": "0.25.2", "@esbuild/netbsd-arm64": "0.25.2", "@esbuild/netbsd-x64": "0.25.2", "@esbuild/openbsd-arm64": "0.25.2", "@esbuild/openbsd-x64": "0.25.2", "@esbuild/sunos-x64": "0.25.2", "@esbuild/win32-arm64": "0.25.2", "@esbuild/win32-ia32": "0.25.2", "@esbuild/win32-x64": "0.25.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ=="],
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+38 -27
View File
@@ -5,15 +5,21 @@ import {
} from "../data/aboutMarasiDrive";
import MarariDriveNeighboursSliderDesktop from "./MarasiDriveNeighboursSliderDesktop";
import MarasiDriveInteriorsSlider from "./MarasiDriveInteriorsSlider";
import MarasiDriveInteriorsSliderMobile from "./MarasiDriveInteriorsSliderMobile";
import MarasiDriveNeighboursSliderMobile from "./MarasiDriveNeighboursSliderMobile";
import MarasiDriveMapMobile from "./MarasiDriveMapMobile";
import TextBox from "./ui/TextBox";
import { useRef } from "react";
import { useScroll } from "motion/react";
import MarasiDriveMapCard from "./MarasiDriveMapCard";
import BrochureButton from "./ui/BrochureButton";
import MarasiDriveNeighboursSliderTablet from "./MarasiDriveNeighboursSliderTablet";
import CustomScrollBar from "./ui/ScrollBar";
import BrochureButton from "./ui/BrochureButton";
function AboutMarasiDrive() {
const target = useRef<HTMLDivElement>(null);
const homeSliderRef = useRef<HTMLDivElement>(null);
const { scrollYProgress } = useScroll({
target,
@@ -22,7 +28,7 @@ function AboutMarasiDrive() {
return (
<div className="relative">
<div className="2xl:sticky relative 2xl:top-[4.444vw]">
<section className="w-full bg-white 2xl:h-[calc(100dvh-4.444vw)] md:max-2xl:h-[calc(100dvh-64px)] h-[calc(100dvh-56px)] 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 flex flex-col justify-between">
<section className="w-full bg-white 2xl:h-[calc(100dvh-4.444vw)] md:max-2xl:h-[calc(100dvh-64px)] h-[calc(100dvh-56px)] max-md:h-[calc(100vw*1.62)] 2xl:p-[2.222vw] 2xl:pt-[5vw] md:max-2xl:p-6 md:max-2xl:pt-10 p-4 pt-8 flex flex-col justify-between">
<div className="absolute inset-0">
<img
src="/images/about-complex/marasi-drive/main_c.jpg"
@@ -37,7 +43,7 @@ function AboutMarasiDrive() {
<img
src="/images/about-complex/marasi-drive/main-mobile_c.jpg"
alt=""
className="object-cover md:hidden size-full"
className="object-cover md:hidden max-md:w-[100%]"
/>
</div>
@@ -67,7 +73,7 @@ function AboutMarasiDrive() {
</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">
<h4 className="text-h4 text-[#00BED7] font-medium whitespace-pre-line ">
{`A home for the young
and young in heart`}
</h4>
@@ -86,23 +92,25 @@ function AboutMarasiDrive() {
{`What makes
a Rove Home?`}
</h2>
<p className="opacity-70 text-s whitespace-pre-line text-center">
<p className="opacity-70 text-s whitespace-pre-line text-center max-md:whitespace-normal">
{`Experience the difference with Rove Home where modern amenities, trendy
interiors, and smart features cater to your unique style. Rove Home is your
destination for artful inspiration and cleverly activated spaces.`}
</p>
</div>
<div className="flex max-2xl:flex-wrap max-2xl:justify-center 2xl:gap-[0.556vw] gap-2 md:max-2xl:w-[93.75vw]">
<div ref={homeSliderRef} className="flex max-2xl:flex-wrap max-2xl:justify-center 2xl:gap-[0.556vw] gap-2 md:max-2xl:w-[93.75vw] max-md:flex-row max-md:flex-nowrap max-md:overflow-x-scroll 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">
{marasiDriveFeatures.map(({ image, name }) => (
<div key={name} className="md:max-2xl:w-[30.208vw]">
<div key={name} className="relative md:max-2xl:w-[30.208vw] max-md:w-full max-md:max-w-[530px] max-md:flex-shrink-0 max-md:snap-center">
<img
src={image}
alt={name}
className="object-cover rounded-[1.667vw]"
className="object-cover object-center 2xl:rounded-[1.667vw] max-md:!aspect-[328/287] max-md:rounded-2xl md:max-2xl:rounded-[3.125vw]"
/>
<span className="md:hidden absolute bottom-[16px] text-white text-h5 left-1/2 -translate-x-1/2 text-center text-nowrap">{name}</span>
</div>
))}
</div>
<CustomScrollBar containerRef={homeSliderRef} inlinePadding={16} trackStyle="min-md:hidden" thumbStyle="min-md:hidden" />
</section>
<section className="bg-white w-full overflow-clip flex flex-col 2xl:gap-[4.444vw] gap-12 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">
<div className="flex flex-col 2xl:gap-[2.222vw] md:max-2xl:gap-8 gap-6 items-center">
@@ -110,7 +118,7 @@ function AboutMarasiDrive() {
{`Expandable living
solutions`}
</h2>
<p className="text-s opacity-70 whitespace-pre-line text-center">
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal">
{`ORI introduces a revolutionary solution to apartment living,
where space is not just a constraint but an opportunity.`}
</p>
@@ -144,12 +152,12 @@ function AboutMarasiDrive() {
</div>
</div>
</section>
<section className="bg-white w-full overflow-clip flex flex-col 2xl:gap-[4.444vw] gap-12 2xl:pt-[9.444vw] 2xl:pb-[15vw] 2xl:px-[2.222vw] md:max-2xl:pt-[104px] md:max-2xl:px-6 md:max-2xl:pb-8 pt-16 px-4 max-md:pb-8">
<div className="flex flex-col 2xl:gap-[2.222vw] md:max-2xl:gap-8 gap-6 items-center">
<section className="bg-white w-full overflow-clip flex flex-col 2xl:gap-[4.444vw] gap-12 2xl:pt-[9.444vw] 2xl:pb-[15vw] 2xl:px-[2.222vw] md:max-2xl:pt-[104px] md:max-2xl:px-6 md:max-2xl:pb-8 pt-16 px-4 max-md:pb-8 max-md:gap-0">
<div className="flex flex-col 2xl:gap-[2.222vw] md:max-2xl:gap-8 gap-6 items-center ">
<h2 className="font-mixcase-unmixed text-h1 text-center">
Inspired interiors
</h2>
<p className="text-s opacity-70 whitespace-pre-line text-center">
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal max-md:mb-10">
{`Smart, flexible designs maximize every inch. The ORI Cloud Bed
expands space by 33%, while the Flexibed transforms living areas
into bedrooms. Multipurpose layouts adapt effortlessly—blending
@@ -157,6 +165,7 @@ function AboutMarasiDrive() {
</p>
</div>
<MarasiDriveInteriorsSlider />
<MarasiDriveInteriorsSliderMobile/>
</section>
</div>
<div className="2xl:sticky relative">
@@ -166,7 +175,7 @@ function AboutMarasiDrive() {
{`A home for the young
and young in heart`}
</h2>
<p className="text-s opacity-70 whitespace-pre-line text-center">
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal">
{`The dynamic essence of Rove comes to life at our new
location in Marasi Drive, Business Bay. Enjoy an urban
living experience beyond the ordinary.`}
@@ -184,10 +193,10 @@ function AboutMarasiDrive() {
>
<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">
<h2 className="font-mixcase-unmixed text-h1 text-center whitespace-pre-line max-md:mb-[24px] md:max-2xl:mb-8">
{`Explore the neighbourhood`}
</h2>
<p className="text-s opacity-70 whitespace-pre-line text-center">
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:whitespace-normal max-md:mb-12 md:max-2xl:mb-16">
{`With Dubai's trendiest spots right at your doorstep, explore nearby
entertainment and dining experiences in just 15 minutes. Live your best life
at Rove Home Marasi Drive!`}
@@ -197,20 +206,21 @@ function AboutMarasiDrive() {
scrollYProgress={scrollYProgress}
/>
<MarasiDriveNeighboursSliderTablet />
<MarasiDriveNeighboursSliderMobile />
</div>
</section>
<section className="bg-white 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 md:max-2xl:pb-8 pt-16 px-4 pb-8">
<div className="flex flex-col gap-[2.222vw] items-center">
<section className="bg-white 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">
Rove around the city
</h2>
<p className="text-s opacity-70 whitespace-pre-line text-center">
<p className="text-s opacity-70 whitespace-pre-line text-center max-md:mb-[48px] max-md:whitespace-normal">
{`Located in the heart of Dubai Marina, Rove Home Dubai Marina is where active
living meets modern convenience. Enjoy an energetic lifestyle surrounded by
trendy cafés, shops, and entertainment options - all within reach.`}
</p>
</div>
<div className="grid grid-cols-6 grid-rows-5 gap-x-[1.111vw] gap-y-[0.556vw]">
<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} />
))}
@@ -222,29 +232,30 @@ function AboutMarasiDrive() {
/>
</div>
</div>
<MarasiDriveMapMobile/>
</section>
<section className="bg-white 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">
<div>
<section className="bg-white 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">
<div >
<img
src="/images/about-complex/marasi-drive/podium.png"
className="object-cover size-full rounded-[1.667vw]"
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]">
<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">
<h2 className="whitespace-pre-line text-h2 font-medium max-2xl:mb-4">
{`Live Different
with Rove Home`}
</h2>
<p className="opacity-40 text-s">
<p className="opacity-40 text-s max-md:mb-[32px] md:max-2xl:max-w-[57.943vw]">
{`Experience the difference with Rove Home where modern amenities,
trendy interiors, and smart features cater to your unique style.`}
</p>
</div>
<div className="space-y-[1.111vw]">
<h5 className="text-h5 font-medium">Download our brochures</h5>
<div className="space-y-[0.833vw]">
<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"
@@ -0,0 +1,29 @@
import { marasiDriveInspiredInteriors } from "../data/aboutMarasiDrive";
import CustomScrollBar from "./ui/ScrollBar";
import { useRef } from "react";
function MarasiDriveInteriorsSliderMobile(){
const interiorsRef = useRef<HTMLDivElement>(null)
return(
<>
<div ref={interiorsRef} className="flex min-md: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">
{marasiDriveInspiredInteriors.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={interiorsRef} inlinePadding={16} trackStyle="min-md:hidden" thumbStyle="min-md:hidden"/>
</>
)
}
export default MarasiDriveInteriorsSliderMobile;
+44
View File
@@ -0,0 +1,44 @@
import { useRef } from "react";
import { marasiDriveMapCards } from "../data/aboutMarasiDrive";
import CustomScrollBar from "./ui/ScrollBar";
function MarasiDriveMapMobile() {
const containerRef = useRef<HTMLDivElement>(null);
return (
<div className="min-2xl:hidden relative 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"
alt=""
className="object-cover size-full rounded-[6.667vw] md:max-2xl:rounded-[3.125vw]"
/>
</div>
<div
ref={containerRef}
className="flex flex-nowrap overflow-x-scroll scroll-pl-4 gap-x-[16px] overflow-y-hidden justify-start snap-x snap-mandatory [&::-webkit-scrollbar]:h-[1.111vw] [&::-webkit-scrollbar]:w-[none] [&::-webkit-scrollbar-thumb]:bg-[#FFFFFF] [&::-webkit-scrollbar-thumb]:w-4 [&::-webkit-scrollbar-thumb]:rounded-full -mx-4 px-4 "
>
{marasiDriveMapCards.map((card, index) => (
<div key={index} className="snap-start">
<div
className={`rounded-[6.667vw] px-[4.444vw] py-[3.333vw] w-[51.111vw] aspect-[184/122] bg-[#F3F3F2] flex-shrink-0 flex flex-col justify-between relative md:max-2xl:w-[25vw] md:max-2xl:rounded-[3.125vw] md:max-2xl:px-[2.083vw] md:max-2xl:py-[1.563vw]`}
>
<div className="space-y-[0.278vw]">
<p className="text-m">{card.title}</p>
<p className="text-s text-[#73787C]">{`${card.mins} mins`}</p>
</div>
<img
src={card.image}
className="rounded-[0.278vw] size-[13.333vw] object-cover absolute bottom-[4.444vw] right-[3.333vw] md:max-2xl:size-[6.25vw] md:max-2xl:bottom-[1.563vw] md:max-2xl:right-[2.083vw]"
alt={card.title}
/>
</div>
</div>
))}
</div>
<CustomScrollBar containerRef={containerRef} inlinePadding={16} trackStyle="min-2xl:hidden max-2xl:translate-y-5" thumbStyle="min-2xl:hidden"/>
</div>
);
}
export default MarasiDriveMapMobile;
@@ -0,0 +1,28 @@
import { marasiDriveNeighbours } from "../data/aboutMarasiDrive";
import { useRef } from "react";
import CustomScrollBar from "./ui/ScrollBar";
function MarasiDriveNeighboursSliderMobile(){
const neighboursRef = useRef<HTMLDivElement>(null);
return(
<>
<div ref={neighboursRef} className="flex min-md: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">
{marasiDriveNeighbours.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={neighboursRef} inlinePadding={16} trackStyle="min-md:hidden" thumbStyle="min-md:hidden"/>
</>
)
}
export default MarasiDriveNeighboursSliderMobile
@@ -73,7 +73,7 @@ function MarasiDriveNeighboursSliderTablet() {
onlyIcon
disabled={currentIndex === 0}
onClick={() => setCurrentIndex(Math.max(currentIndex - 1, 0))}
className="absolute left-[8.203vw] bottom-1/2"
className="absolute left-[calc((100%-69.141vw)/2-56px)] bottom-1/2"
>
<span className="size-5">
<ChevronLeftIcon />
@@ -82,7 +82,7 @@ function MarasiDriveNeighboursSliderTablet() {
<Button
onlyIcon
disabled={currentIndex === marasiDriveNeighbours.length - 1}
className="absolute left-[83.594vw] bottom-1/2"
className="absolute right-[calc((100%-69.141vw)/2-56px)] bottom-1/2"
onClick={() =>
setCurrentIndex(
Math.min(currentIndex + 1, marasiDriveNeighbours.length - 1)
+78
View File
@@ -0,0 +1,78 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react";
import useWindowSize from "../../hooks/useWindowSize";
interface CustomScrollBarProps {
containerRef: React.RefObject<HTMLElement | null>;
inlinePadding: number;
trackStyle?: string;
thumbStyle?: string;
}
function CustomScrollBar({
containerRef,
inlinePadding,
trackStyle = "",
thumbStyle = "",
}: CustomScrollBarProps) {
const [scrollLeft, setScrollLeft] = useState<number>(0);
const [totalWidth, setTotalWidth] = useState<number>(0);
const [containerWidth, setContainerWidth] = useState<number>(0);
const [thumbVisible, setThumbVisible] = useState<boolean>(false);
const windowSize = useWindowSize();
function GetContainer(): HTMLElement {
if (!containerRef.current) {
throw new Error("Container reference is not valid");
}
return containerRef.current;
}
useEffect(() => {
setTotalWidth(GetContainer().scrollWidth);
setContainerWidth(GetContainer().clientWidth);
}, [windowSize]);
useEffect(() => {
const container = GetContainer();
let hideThumbTimeout: ReturnType<typeof setTimeout> | null = null;
function handleContainerScroll() {
setScrollLeft(container.scrollLeft);
if (!thumbVisible) setThumbVisible(true);
if (hideThumbTimeout) clearTimeout(hideThumbTimeout);
hideThumbTimeout = setTimeout(() => {
setThumbVisible(false);
}, 750);
}
container.addEventListener("scroll", handleContainerScroll);
return () => {
container.removeEventListener("scroll", handleContainerScroll);
};
}, [containerRef]);
const scrollPercent =
totalWidth > containerWidth
? (scrollLeft / (totalWidth - containerWidth)) * 100
: 0;
const thumbPosition =
(scrollPercent / 100) * (containerWidth - 20 - inlinePadding * 2); // 20px - ширина ползунка
return (
<div
className={`relative h-1 w-full bg-transparent rounded-full ${trackStyle}`}
>
<div
className={`absolute w-5 h-1 bg-[#E2E2DC] rounded-full transition-opacity duration-250 ease-out ${
thumbVisible ? "opacity-100" : "opacity-0"
} ${thumbStyle}`}
style={{ transform: `translateX(${thumbPosition}px)` }}
/>
</div>
);
}
export default CustomScrollBar;