Bob AI: Add 3D parallax effects to hero section

This commit is contained in:
kudinDmitriyUp
2026-06-17 07:25:00 +00:00
parent 99e7a23dc3
commit 76b16dffc2
9 changed files with 519 additions and 239 deletions

View File

@@ -1,251 +1,36 @@
import AboutTextSplit from '@/components/sections/about/AboutTextSplit';
import ContactCta from '@/components/sections/contact/ContactCta';
import FeaturesImageBento from '@/components/sections/features/FeaturesImageBento';
import FeaturesMediaCards from '@/components/sections/features/FeaturesMediaCards';
import HeroOverlayMarquee from '@/components/sections/hero/HeroOverlayMarquee';
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
import { Star, Waves } from "lucide-react";
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
// AUTO-GENERATED shell by per-section-migrate.
// Section bodies live in ./<PageBase>/sections/<X>.tsx. Edit the section
// files directly. Non-block content (wrappers, non-inlinable sections) is
// preserved inline; extracted section blocks become <XSection/> refs.
export default function HomePage() {
import React from 'react';
import HeroSection from './HomePage/sections/Hero';
import RoomsSection from './HomePage/sections/Rooms';
import DiningSection from './HomePage/sections/Dining';
import NatureSection from './HomePage/sections/Nature';
import WellnessSection from './HomePage/sections/Wellness';
import DiscoverSection from './HomePage/sections/Discover';
import BlogSection from './HomePage/sections/Blog';
import BookingSection from './HomePage/sections/Booking';
export default function HomePage(): React.JSX.Element {
return (
<>
<div id="hero" data-section="hero">
<SectionErrorBoundary name="hero">
<HeroOverlayMarquee
tag="Luxury Eco-Resort"
title="Set within the verdant pine and oak forest of Mljet National Park"
description="Experience unparalleled serenity on Croatia's greenest island, where the Adriatic Sea meets ancient Mediterranean woodlands."
primaryButton={{
text: "Book Now",
href: "#booking",
}}
secondaryButton={{
text: "Online Check-in",
href: "#check-in",
}}
items={[
{
text: "Adriatic Sea Views",
icon: Waves,
},
{
text: "National Park Access",
icon: Star,
},
{
text: "Wellness Sanctuary",
icon: Star,
},
]}
imageSrc="http://img.b2bpic.net/free-photo/vertical-shot-cabin-forest-surrounded-by-lot-green-trees-norway_181624-13703.jpg"
/>
</SectionErrorBoundary>
</div>
<>
<HeroSection />
<div id="rooms" data-section="rooms">
<SectionErrorBoundary name="rooms">
<MetricsMediaCards
tag="Accommodations"
title="Sweeping view of the Adriatic in your Room"
description="Experience our range of luxurious suites designed to blend Mediterranean comfort with natural elegance."
metrics={[
{
value: "Classic Room",
title: "01",
description: "Intimate space with garden views.",
imageSrc: "http://img.b2bpic.net/free-photo/diverse-young-people-being-digital-nomads-working-remotely-from-dreamy-locations_23-2151187936.jpg",
},
{
value: "Superior Room",
title: "02",
description: "Spacious retreat with balcony.",
imageSrc: "http://img.b2bpic.net/free-photo/sunbeds-with-coconuts-tree-by-sea_23-2148249118.jpg",
},
{
value: "Deluxe Room",
title: "03",
description: "Stunning sea vistas and en-suite.",
imageSrc: "http://img.b2bpic.net/free-photo/panoramic-lakeside-sauna-geometric-heaters-scandinavian-style_169016-68879.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
<RoomsSection />
<div id="dining" data-section="dining">
<SectionErrorBoundary name="dining">
<FeaturesImageBento
tag="Gastronomy"
title="Dining options with regional specialities"
description="A curated culinary journey featuring fresh, local Adriatic flavours."
items={[
{
title: "Restaurant Odisej",
description: "Panoramic bay view seafood.",
imageSrc: "http://img.b2bpic.net/free-photo/delicious-seafood-table-high-angle_23-2149410756.jpg",
},
{
title: "Levanat Pizzeria",
description: "Marina views, pizza & gelato.",
imageSrc: "http://img.b2bpic.net/free-photo/elegant-wedding-reception-room-with-sea-view-through-windows_637285-8612.jpg",
},
{
title: "Vista Mare",
description: "Beachfront cocktails & rattan.",
imageSrc: "http://img.b2bpic.net/free-photo/high-angle-picnic-with-snacks-wine_23-2149726438.jpg",
},
{
title: "Local Harvest",
description: "Regional olive oils and wine.",
imageSrc: "http://img.b2bpic.net/free-photo/street-cafe-old-town-lindos-greek-island-rhodes-view-aegean-sea-islands-dodecanese-archipelago-europe-travel-time_166373-3822.jpg",
},
{
title: "Catch of the Day",
description: "Freshly sourced seafood.",
imageSrc: "http://img.b2bpic.net/free-photo/friends-having-nice-barbeque-together_23-2149271923.jpg",
},
{
title: "Sunset Lounge",
description: "Twilight aperitifs by the sea.",
imageSrc: "http://img.b2bpic.net/free-photo/side-view-empty-glasses-martini-wooden-table_140725-12882.jpg",
},
{
title: "Private Dining",
description: "Exquisite forest side table.",
imageSrc: "http://img.b2bpic.net/free-photo/picnic-with-delicious-beautiful-food-table-close-up-outdoor-recreation-concept_169016-10291.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
<DiningSection />
<div id="nature" data-section="nature">
<SectionErrorBoundary name="nature">
<AboutTextSplit
title="Surrender yourself to the silent solitude of the wild."
descriptions={[
"A sanctuary of pine, oak, and ancient forests awaiting your discovery.",
"Connect deeply with the pristine natural rhythms of Mljet National Park.",
]}
/>
</SectionErrorBoundary>
</div>
<NatureSection />
<div id="wellness" data-section="wellness">
<SectionErrorBoundary name="wellness">
<FeaturesMediaCards
tag="Wellness"
title="Relaxing Treatments"
description="Rejuvenate your body and mind in our dedicated sanctuary space."
items={[
{
title: "Sea-water Pool",
description: "Natural healing waters.",
imageSrc: "http://img.b2bpic.net/free-photo/woman-doing-yoga-by-pool_23-2148732924.jpg",
},
{
title: "Holistic Massage",
description: "Deep forest-inspired therapy.",
imageSrc: "http://img.b2bpic.net/free-photo/beautiful-woman-practicing-yoga_1385-1450.jpg",
},
{
title: "Sauna & Beauty",
description: "Total rejuvenation sessions.",
imageSrc: "http://img.b2bpic.net/free-photo/fashion-portrait-caucasian-woman-bikini-blue-swimming-pool-vacation-coudy-day-natural-light_343596-2295.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
<WellnessSection />
<div id="discover" data-section="discover">
<SectionErrorBoundary name="discover">
<FeaturesImageBento
tag="Adventure"
title="Oak tree forest of Mljet National Park"
description="Discover Croatia's greenest island and its legendary myths."
items={[
{
title: "Forest Paths",
description: "Guided wilderness hiking.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-view-tanaro-river-winding-through-lush-piedmont-forest_1308-190390.jpg",
},
{
title: "Ulysses Myth",
description: "Ancient history explorations.",
imageSrc: "http://img.b2bpic.net/free-photo/rear-view-girls-going-down-river_23-2147617426.jpg",
},
{
title: "Bay Kayaking",
description: "Explore hidden sea coves.",
imageSrc: "http://img.b2bpic.net/free-photo/famous-road-with-arch-rock-called-defile-de-ruoms_268835-3688.jpg",
},
{
title: "Cycling Trails",
description: "Island-wide forest biking.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-drone-view-nature-romania_1268-19288.jpg",
},
{
title: "Wildlife Safari",
description: "Observing rare local flora.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-beautiful-shot-island-seashore-with-sea-side_181624-31485.jpg",
},
{
title: "Boat Excursions",
description: "Visit historic salt lakes.",
imageSrc: "http://img.b2bpic.net/free-photo/rocks-overgrown-with-greenery-seashore_169016-39188.jpg",
},
{
title: "Eco Tourism",
description: "Sustainable island travel.",
imageSrc: "http://img.b2bpic.net/free-photo/high-angle-view-tropical-trees-growing-forest_23-2147830980.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
<DiscoverSection />
<div id="blog" data-section="blog">
<SectionErrorBoundary name="blog">
<MetricsMediaCards
tag="Stories"
title="Beyond the Hotel"
description="Explore the culture, myths, and artisans of our island."
metrics={[
{
value: "Jewellery",
title: "A Bead in My Palm",
description: "Croatian beaded artistry tradition.",
imageSrc: "http://img.b2bpic.net/free-photo/artist-getting-pain-brush_181624-18431.jpg",
},
{
value: "Mythology",
title: "The Island of Ulysses",
description: "The legend of Odyssey in Mljet.",
imageSrc: "http://img.b2bpic.net/free-photo/fantasy-coast-landscape_23-2151515053.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
<BlogSection />
<div id="booking" data-section="booking">
<SectionErrorBoundary name="booking">
<ContactCta
tag="Escape"
text="Get Back to Nature"
primaryButton={{
text: "Book Your Stay",
href: "#",
}}
secondaryButton={{
text: "Contact Us",
href: "#contact",
}}
/>
</SectionErrorBoundary>
</div>
<BookingSection />
</>
);
}

View File

@@ -0,0 +1,34 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "blog" section.
import React from 'react';
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function BlogSection(): React.JSX.Element {
return (
<div id="blog" data-section="blog">
<SectionErrorBoundary name="blog">
<MetricsMediaCards
tag="Stories"
title="Beyond the Hotel"
description="Explore the culture, myths, and artisans of our island."
metrics={[
{
value: "Jewellery",
title: "A Bead in My Palm",
description: "Croatian beaded artistry tradition.",
imageSrc: "http://img.b2bpic.net/free-photo/artist-getting-pain-brush_181624-18431.jpg",
},
{
value: "Mythology",
title: "The Island of Ulysses",
description: "The legend of Odyssey in Mljet.",
imageSrc: "http://img.b2bpic.net/free-photo/fantasy-coast-landscape_23-2151515053.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
);
}

View File

@@ -0,0 +1,27 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "booking" section.
import React from 'react';
import ContactCta from '@/components/sections/contact/ContactCta';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function BookingSection(): React.JSX.Element {
return (
<div id="booking" data-section="booking">
<SectionErrorBoundary name="booking">
<ContactCta
tag="Escape"
text="Get Back to Nature"
primaryButton={{
text: "Book Your Stay",
href: "#",
}}
secondaryButton={{
text: "Contact Us",
href: "#contact",
}}
/>
</SectionErrorBoundary>
</div>
);
}

View File

@@ -0,0 +1,57 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "dining" section.
import React from 'react';
import FeaturesImageBento from '@/components/sections/features/FeaturesImageBento';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function DiningSection(): React.JSX.Element {
return (
<div id="dining" data-section="dining">
<SectionErrorBoundary name="dining">
<FeaturesImageBento
tag="Gastronomy"
title="Dining options with regional specialities"
description="A curated culinary journey featuring fresh, local Adriatic flavours."
items={[
{
title: "Restaurant Odisej",
description: "Panoramic bay view seafood.",
imageSrc: "http://img.b2bpic.net/free-photo/delicious-seafood-table-high-angle_23-2149410756.jpg",
},
{
title: "Levanat Pizzeria",
description: "Marina views, pizza & gelato.",
imageSrc: "http://img.b2bpic.net/free-photo/elegant-wedding-reception-room-with-sea-view-through-windows_637285-8612.jpg",
},
{
title: "Vista Mare",
description: "Beachfront cocktails & rattan.",
imageSrc: "http://img.b2bpic.net/free-photo/high-angle-picnic-with-snacks-wine_23-2149726438.jpg",
},
{
title: "Local Harvest",
description: "Regional olive oils and wine.",
imageSrc: "http://img.b2bpic.net/free-photo/street-cafe-old-town-lindos-greek-island-rhodes-view-aegean-sea-islands-dodecanese-archipelago-europe-travel-time_166373-3822.jpg",
},
{
title: "Catch of the Day",
description: "Freshly sourced seafood.",
imageSrc: "http://img.b2bpic.net/free-photo/friends-having-nice-barbeque-together_23-2149271923.jpg",
},
{
title: "Sunset Lounge",
description: "Twilight aperitifs by the sea.",
imageSrc: "http://img.b2bpic.net/free-photo/side-view-empty-glasses-martini-wooden-table_140725-12882.jpg",
},
{
title: "Private Dining",
description: "Exquisite forest side table.",
imageSrc: "http://img.b2bpic.net/free-photo/picnic-with-delicious-beautiful-food-table-close-up-outdoor-recreation-concept_169016-10291.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
);
}

View File

@@ -0,0 +1,158 @@
/* eslint-disable */
// @ts-nocheck — generated by catalog-eject; runtime-correct but TS strict-mode false-positives on inlined catalog body
import Button from "@/components/ui/Button";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import ScrollReveal from "@/components/ui/ScrollReveal";
import { cls } from "@/lib/utils";
const items = [
{
title: "Forest Paths",
description: "Guided wilderness hiking.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-view-tanaro-river-winding-through-lush-piedmont-forest_1308-190390.jpg"
},
{
title: "Ulysses Myth",
description: "Ancient history explorations.",
imageSrc: "http://img.b2bpic.net/free-photo/rear-view-girls-going-down-river_23-2147617426.jpg"
},
{
title: "Bay Kayaking",
description: "Explore hidden sea coves.",
imageSrc: "http://img.b2bpic.net/free-photo/famous-road-with-arch-rock-called-defile-de-ruoms_268835-3688.jpg"
},
{
title: "Cycling Trails",
description: "Island-wide forest biking.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-drone-view-nature-romania_1268-19288.jpg"
},
{
title: "Wildlife Safari",
description: "Observing rare local flora.",
imageSrc: "http://img.b2bpic.net/free-photo/aerial-beautiful-shot-island-seashore-with-sea-side_181624-31485.jpg"
},
{
title: "Boat Excursions",
description: "Visit historic salt lakes.",
imageSrc: "http://img.b2bpic.net/free-photo/rocks-overgrown-with-greenery-seashore_169016-39188.jpg"
},
{
title: "Eco Tourism",
description: "Sustainable island travel.",
imageSrc: "http://img.b2bpic.net/free-photo/high-angle-view-tropical-trees-growing-forest_23-2147830980.jpg"
}
];
type FeatureItem = {
title: string;
description: string;
href?: string;
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
interface FeaturesImageBentoProps {
tag: string;
title: string;
description: string;
primaryButton?: { text: string; href: string };
secondaryButton?: { text: string; href: string };
items: [FeatureItem, FeatureItem, FeatureItem, FeatureItem, FeatureItem, FeatureItem, FeatureItem];
}
const DiscoverInline = () => {
const gridClasses = [
"md:col-span-2",
"md:col-span-4",
"md:col-span-3",
"md:col-span-3",
"md:col-span-2",
"md:col-span-2",
"md:col-span-2",
];
const staggerDelays = [
0,
0.1,
0,
0.1,
0,
0.1,
0.2,
];
return (
<section aria-label="Features image bento section" className="py-20">
<div className="flex flex-col gap-8 md:gap-10">
<div className="flex flex-col items-center w-content-width mx-auto gap-2">
<div className="px-3 py-1 mb-1 text-sm card rounded w-fit">
<p>{"Adventure"}</p>
</div>
<TextAnimation
text={"Oak tree forest of Mljet National Park"}
variant="fade"
gradientText={true}
tag="h2"
className="md:max-w-8/10 text-6xl 2xl:text-7xl leading-[1.15] font-semibold text-center text-balance"
/>
<TextAnimation
text={"Discover Croatia's greenest island and its legendary myths."}
variant="fade"
gradientText={false}
tag="p"
className="md:max-w-7/10 text-lg md:text-xl leading-snug text-center text-balance"
/>
{(undefined || undefined) && (
<div className="flex flex-wrap justify-center gap-3 mt-2 md:mt-3">
{undefined && <Button text={undefined.text} href={undefined.href} variant="primary"/>}
{undefined && <Button text={undefined.text} href={undefined.href} variant="secondary" animationDelay={0.1} />}
</div>
)}
</div>
<div className="w-content-width mx-auto grid grid-cols-1 md:grid-cols-6 gap-3">
{items.map((item, index) => {
const content = (
<div className="relative h-80 xl:h-100 2xl:h-120 overflow-hidden">
<ImageOrVideo
imageSrc={item.imageSrc}
videoSrc={item.videoSrc}
className="rounded group-hover:scale-105 transition-transform duration-500"
/>
<div className="absolute inset-x-5 bottom-5 xl:inset-x-6 xl:bottom-6 2xl:inset-x-7 2xl:bottom-7 flex flex-col text-background">
<span className="text-2xl font-semibold leading-snug truncate">{item.title}</span>
<span className="text-base leading-snug truncate">{item.description}</span>
</div>
</div>
);
return (
<ScrollReveal key={index} variant="slide-up" delay={staggerDelays[index]} className={cls("col-span-1 group", gridClasses[index])}>
{item.href ? (
<a href={item.href} className="block overflow-hidden rounded">
{content}
</a>
) : (
<div className="overflow-hidden rounded">
{content}
</div>
)}
</ScrollReveal>
);
})}
</div>
</div>
</section>
);
};
export default function DiscoverSection() {
return (
<div data-webild-section="discover" id="discover">
<DiscoverInline />
</div>
);
}

View File

@@ -0,0 +1,120 @@
/* eslint-disable */
// @ts-nocheck — generated by catalog-eject; runtime-correct but TS strict-mode false-positives on inlined catalog body
import { Waves, Star } from 'lucide-react';
import type { LucideIcon } from "lucide-react";
import Button from "@/components/ui/Button";
import HeroBackgroundSlot from "@/components/ui/HeroBackgroundSlot";
import TextAnimation from "@/components/ui/TextAnimation";
import ImageOrVideo from "@/components/ui/ImageOrVideo";
import AvatarGroup from "@/components/ui/AvatarGroup";
const primaryButton = {
text: "Book Now",
href: "#booking"
};
const secondaryButton = {
text: "Online Check-in",
href: "#check-in"
};
const items = [
{
text: "Adriatic Sea Views",
icon: Waves
},
{
text: "National Park Access",
icon: Star
},
{
text: "Wellness Sanctuary",
icon: Star
}
];
type HeroOverlayMarqueeProps = {
tag: string;
title: string;
description: string;
primaryButton: { text: string; href: string };
secondaryButton: { text: string; href: string };
avatarsSrc?: string[];
avatarsLabel?: string;
items: { text: string; icon: LucideIcon }[];
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
const HeroInline = () => {
return (
<section
aria-label="Hero section"
className="relative overflow-hidden flex flex-col justify-between mb-20 w-full h-svh"
style={{ perspective: "1000px" }}
>
<HeroBackgroundSlot />
<ImageOrVideo
imageSrc={"http://img.b2bpic.net/free-photo/vertical-shot-cabin-forest-surrounded-by-lot-green-trees-norway_181624-13703.jpg"}
className="absolute inset-0 object-cover w-full h-full rounded-none"
style={{ transform: "translateZ(-100px) scale(1.2)" }}
/>
<div
className="absolute z-10 left-0 top-0 w-[150vw] h-[150vw] -translate-x-1/2 -translate-y-1/2 backdrop-blur mask-[radial-gradient(circle,black_20%,transparent_70%)]"
aria-hidden="true"
/>
<div className="relative z-10 mx-auto pt-35 w-content-width" style={{ transform: "translateZ(50px)" }}>
<div className="flex flex-col gap-3 w-full md:w-6/10 lg:w-1/2 xl:w-45/100 2xl:w-4/10">
<div className="mb-1 px-3 py-1 w-fit text-sm card rounded">
<p>{"Luxury Eco-Resort"}</p>
</div>
<TextAnimation
text={"Set within the verdant pine and oak forest of Mljet National Park"}
variant="fade"
gradientText={true}
tag="h1"
className="text-7xl 2xl:text-8xl leading-[1.15] font-semibold text-balance text-white"
/>
<TextAnimation
text={"Experience unparalleled serenity on Croatia's greenest island, where the Adriatic Sea meets ancient Mediterranean woodlands."}
variant="fade"
gradientText={false}
tag="p"
className="text-lg md:text-xl leading-snug text-balance text-white"
/>
<div className="flex flex-wrap gap-3 mt-2 md:mt-3">
<Button text={primaryButton.text} href={primaryButton.href} variant="primary" />
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary" animationDelay={0.1} />
</div>
{undefined && undefined.length > 0 && (
<div className="mt-3 md:mt-4">
<AvatarGroup size="lg" labelClassName="text-primary-cta-text" />
</div>
)}
</div>
</div>
<div className="relative z-10 overflow-hidden mx-auto pb-8 w-content-width mask-fade-x">
<div className="flex w-max animate-marquee-horizontal" style={{ animationDuration: "30s" }}>
{[...items, ...items, ...items, ...items].map((item, index) => (
<div key={index} className="flex items-center shrink-0 gap-1 mx-3 pl-2 pr-4 py-2 card rounded">
<item.icon className="h-(--text-base) text-foreground" />
<span className="whitespace-nowrap text-base font-medium text-foreground">{item.text}</span>
</div>
))}
</div>
</div>
</section>
);
};
export default function HeroSection() {
return (
<div data-webild-section="hero" id="hero">
<HeroInline />
</div>
);
}

View File

@@ -0,0 +1,22 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "nature" section.
import React from 'react';
import AboutTextSplit from '@/components/sections/about/AboutTextSplit';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function NatureSection(): React.JSX.Element {
return (
<div id="nature" data-section="nature">
<SectionErrorBoundary name="nature">
<AboutTextSplit
title="Surrender yourself to the silent solitude of the wild."
descriptions={[
"A sanctuary of pine, oak, and ancient forests awaiting your discovery.",
"Connect deeply with the pristine natural rhythms of Mljet National Park.",
]}
/>
</SectionErrorBoundary>
</div>
);
}

View File

@@ -0,0 +1,40 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "rooms" section.
import React from 'react';
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function RoomsSection(): React.JSX.Element {
return (
<div id="rooms" data-section="rooms">
<SectionErrorBoundary name="rooms">
<MetricsMediaCards
tag="Accommodations"
title="Sweeping view of the Adriatic in your Room"
description="Experience our range of luxurious suites designed to blend Mediterranean comfort with natural elegance."
metrics={[
{
value: "Classic Room",
title: "01",
description: "Intimate space with garden views.",
imageSrc: "http://img.b2bpic.net/free-photo/diverse-young-people-being-digital-nomads-working-remotely-from-dreamy-locations_23-2151187936.jpg",
},
{
value: "Superior Room",
title: "02",
description: "Spacious retreat with balcony.",
imageSrc: "http://img.b2bpic.net/free-photo/sunbeds-with-coconuts-tree-by-sea_23-2148249118.jpg",
},
{
value: "Deluxe Room",
title: "03",
description: "Stunning sea vistas and en-suite.",
imageSrc: "http://img.b2bpic.net/free-photo/panoramic-lakeside-sauna-geometric-heaters-scandinavian-style_169016-68879.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
);
}

View File

@@ -0,0 +1,37 @@
// AUTO-GENERATED by per-section-migrate. Edit freely — Bob will treat this
// file as the canonical source for the "wellness" section.
import React from 'react';
import FeaturesMediaCards from '@/components/sections/features/FeaturesMediaCards';
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
export default function WellnessSection(): React.JSX.Element {
return (
<div id="wellness" data-section="wellness">
<SectionErrorBoundary name="wellness">
<FeaturesMediaCards
tag="Wellness"
title="Relaxing Treatments"
description="Rejuvenate your body and mind in our dedicated sanctuary space."
items={[
{
title: "Sea-water Pool",
description: "Natural healing waters.",
imageSrc: "http://img.b2bpic.net/free-photo/woman-doing-yoga-by-pool_23-2148732924.jpg",
},
{
title: "Holistic Massage",
description: "Deep forest-inspired therapy.",
imageSrc: "http://img.b2bpic.net/free-photo/beautiful-woman-practicing-yoga_1385-1450.jpg",
},
{
title: "Sauna & Beauty",
description: "Total rejuvenation sessions.",
imageSrc: "http://img.b2bpic.net/free-photo/fashion-portrait-caucasian-woman-bikini-blue-swimming-pool-vacation-coudy-day-natural-light_343596-2295.jpg",
},
]}
/>
</SectionErrorBoundary>
</div>
);
}