Compare commits
12 Commits
version_1_
...
version_8_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76e4a68006 | ||
| d19f1afc4d | |||
|
|
cd15b4aa88 | ||
| 237b5d6dad | |||
|
|
e9e582d543 | ||
| 5189fba3e2 | |||
|
|
be75e69bf6 | ||
| 9abaace63e | |||
|
|
b65f797cc0 | ||
| 4375d60256 | |||
| f181b983b2 | |||
| af8aa2a23c |
@@ -1,73 +0,0 @@
|
|||||||
import Button from "@/components/ui/Button";
|
|
||||||
import HeroBackgroundSlot from "@/components/ui/HeroBackgroundSlot";
|
|
||||||
import TextAnimation from "@/components/ui/TextAnimation";
|
|
||||||
import ImageOrVideo from "@/components/ui/ImageOrVideo";
|
|
||||||
|
|
||||||
type HeroBillboardCarouselProps = {
|
|
||||||
tag: string;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
primaryButton: { text: string; href: string };
|
|
||||||
secondaryButton: { text: string; href: string };
|
|
||||||
items: ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never })[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const HeroBillboardCarousel = ({
|
|
||||||
tag,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
primaryButton,
|
|
||||||
secondaryButton,
|
|
||||||
items,
|
|
||||||
}: HeroBillboardCarouselProps) => {
|
|
||||||
const duplicated = [...items, ...items, ...items, ...items];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section
|
|
||||||
aria-label="Hero section"
|
|
||||||
className="relative flex flex-col items-center justify-center gap-8 w-full min-h-svh py-25"
|
|
||||||
>
|
|
||||||
<HeroBackgroundSlot />
|
|
||||||
<div className="flex flex-col items-center gap-2 w-content-width mx-auto text-center">
|
|
||||||
<span className="px-3 py-1 mb-1 text-sm card rounded">{tag}</span>
|
|
||||||
|
|
||||||
<TextAnimation
|
|
||||||
text={title}
|
|
||||||
variant="slide-up"
|
|
||||||
gradientText={true}
|
|
||||||
tag="h1"
|
|
||||||
className="text-6xl font-medium text-balance"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextAnimation
|
|
||||||
text={description}
|
|
||||||
variant="slide-up"
|
|
||||||
gradientText={false}
|
|
||||||
tag="p"
|
|
||||||
className="text-base md:text-lg leading-tight text-balance"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="flex flex-wrap justify-center gap-3 mt-3">
|
|
||||||
<Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>
|
|
||||||
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary"animationDelay={0.1} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-content-width mx-auto overflow-hidden mask-fade-x">
|
|
||||||
<div className="flex w-max animate-marquee-horizontal" style={{ animationDuration: "60s" }}>
|
|
||||||
{duplicated.map((item, i) => (
|
|
||||||
<div key={i} className="shrink-0 w-60 md:w-75 2xl:w-80 aspect-4/5 mr-3 md:mr-5 p-1.5 card rounded-lg overflow-hidden">
|
|
||||||
<ImageOrVideo
|
|
||||||
imageSrc={item.imageSrc}
|
|
||||||
videoSrc={item.videoSrc}
|
|
||||||
className="w-full h-full rounded-lg object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default HeroBillboardCarousel;
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ type HeroOverlayProps = {
|
|||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
primaryButton: { text: string; href: string };
|
primaryButton: { text: string; href: string };
|
||||||
secondaryButton: { text: string; href: string };
|
|
||||||
avatars?: { src: string }[];
|
avatars?: { src: string }[];
|
||||||
avatarsLabel?: string;
|
avatarsLabel?: string;
|
||||||
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
|
} & ({ imageSrc: string; videoSrc?: never } | { videoSrc: string; imageSrc?: never });
|
||||||
@@ -19,7 +18,6 @@ const HeroOverlay = ({
|
|||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
primaryButton,
|
primaryButton,
|
||||||
secondaryButton,
|
|
||||||
imageSrc,
|
imageSrc,
|
||||||
videoSrc,
|
videoSrc,
|
||||||
avatars,
|
avatars,
|
||||||
@@ -62,10 +60,7 @@ const HeroOverlay = ({
|
|||||||
className="text-lg md:text-xl text-primary-cta-text leading-tight text-balance"
|
className="text-lg md:text-xl text-primary-cta-text leading-tight text-balance"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-3 mt-3">
|
<Button text={primaryButton.text} href={primaryButton.href} variant="primary" className="w-full mt-3" />
|
||||||
<Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>
|
|
||||||
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary"animationDelay={0.1} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{avatars && avatars.length > 0 && (
|
{avatars && avatars.length > 0 && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ const HeroSplit = ({
|
|||||||
className="max-w-8/10 text-lg md:text-xl leading-tight text-center md:text-left"
|
className="max-w-8/10 text-lg md:text-xl leading-tight text-center md:text-left"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex flex-wrap max-md:justify-center gap-3 mt-3">
|
<div className="flex flex-wrap max-md:justify-center mt-3">
|
||||||
<Button text={primaryButton.text} href={primaryButton.href} variant="primary"/>
|
<Button text={primaryButton.text} href={primaryButton.href} variant="primary" className="rounded-r-none" />
|
||||||
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary"animationDelay={0.1} />
|
<Button text={secondaryButton.text} href={secondaryButton.href} variant="secondary" className="rounded-l-none" animationDelay={0.1} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -165,22 +165,24 @@ h6 {
|
|||||||
|
|
||||||
.primary-button {
|
.primary-button {
|
||||||
/* WEBILD_PRIMARY_BUTTON */
|
/* WEBILD_PRIMARY_BUTTON */
|
||||||
/* @primaryButtons/depth-layers */
|
/* @primaryButtons/full */
|
||||||
background: var(--color-primary-cta);
|
background: var(--color-primary-cta);
|
||||||
box-shadow: 0 1px 2px color-mix(in srgb, var(--color-primary-cta) 20%, transparent), 0 2px 4px color-mix(in srgb, var(--color-primary-cta) 20%, transparent), 0 4px 8px color-mix(in srgb, var(--color-primary-cta) 15%, transparent), 0 8px 16px color-mix(in srgb, var(--color-primary-cta) 10%, transparent), 0 16px 32px color-mix(in srgb, var(--color-primary-cta) 5%, transparent);
|
}
|
||||||
|
|
||||||
|
.primary-button:hover {
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-button:active {
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-button {
|
.secondary-button {
|
||||||
/* WEBILD_SECONDARY_BUTTON */
|
/* WEBILD_SECONDARY_BUTTON */
|
||||||
/* @secondaryButtons/layered */
|
/* @secondaryButtons/full */
|
||||||
background:
|
background: var(--color-secondary-cta);
|
||||||
linear-gradient(color-mix(in srgb, var(--color-accent) 5%, transparent) 0%, transparent 59.26%),
|
}
|
||||||
linear-gradient(var(--color-secondary-cta), var(--color-secondary-cta)),
|
|
||||||
linear-gradient(var(--color-secondary-cta), var(--color-secondary-cta)),
|
.secondary-button:hover {
|
||||||
linear-gradient(color-mix(in srgb, var(--color-accent) 5%, transparent) 0%, transparent 59.26%),
|
}
|
||||||
linear-gradient(color-mix(in srgb, var(--color-secondary-cta) 60%, transparent), color-mix(in srgb, var(--color-secondary-cta) 60%, transparent)),
|
|
||||||
var(--color-secondary-cta);
|
.secondary-button:active {
|
||||||
box-shadow:
|
|
||||||
2.10837px 3.16256px 9.48767px color-mix(in srgb, var(--color-accent) 10%, transparent);
|
|
||||||
border: 1px solid var(--color-secondary-cta);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import AboutTestimonial from '@/components/sections/about/AboutTestimonial';
|
import AboutTestimonial from '@/components/sections/about/AboutTestimonial';
|
||||||
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
|
||||||
import FeaturesTaggedCards from '@/components/sections/features/FeaturesTaggedCards';
|
import FeaturesMediaCards from '@/components/sections/features/FeaturesMediaCards';
|
||||||
import HeroOverlay from '@/components/sections/hero/HeroOverlay';
|
import HeroOverlay from '@/components/sections/hero/HeroOverlay';
|
||||||
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
|
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
|
||||||
import ProductRatingCards from '@/components/sections/product/ProductRatingCards';
|
import ProductRatingCards from '@/components/sections/product/ProductRatingCards';
|
||||||
@@ -18,13 +18,9 @@ export default function HomePage() {
|
|||||||
title="Transforming San Diego Landscapes"
|
title="Transforming San Diego Landscapes"
|
||||||
description="Expert landscaping services for residential and commercial properties in San Diego. From lush gardens to sustainable designs, we bring your vision to life."
|
description="Expert landscaping services for residential and commercial properties in San Diego. From lush gardens to sustainable designs, we bring your vision to life."
|
||||||
primaryButton={{
|
primaryButton={{
|
||||||
text: "Get a Free Estimate",
|
text: "Get a Free Estimate or View Our Services",
|
||||||
href: "#contact",
|
href: "#contact",
|
||||||
}}
|
}}
|
||||||
secondaryButton={{
|
|
||||||
text: "View Our Services",
|
|
||||||
href: "#services",
|
|
||||||
}}
|
|
||||||
imageSrc="http://img.b2bpic.net/free-photo/landscape-courtyard-monastery_1268-15252.jpg"
|
imageSrc="http://img.b2bpic.net/free-photo/landscape-courtyard-monastery_1268-15252.jpg"
|
||||||
avatarsLabel="Trusted by 500+ happy clients"
|
avatarsLabel="Trusted by 500+ happy clients"
|
||||||
avatars={[
|
avatars={[
|
||||||
@@ -50,31 +46,27 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<div id="services" data-section="services">
|
<div id="services" data-section="services">
|
||||||
<SectionErrorBoundary name="services">
|
<SectionErrorBoundary name="services">
|
||||||
<FeaturesTaggedCards
|
<FeaturesMediaCards
|
||||||
tag="Our Services"
|
tag="Our Services"
|
||||||
title="Comprehensive Landscaping Solutions"
|
title="Comprehensive Landscaping Solutions"
|
||||||
description="We offer a full range of landscaping services to enhance the beauty and functionality of your property, tailored to San Diego's unique climate."
|
description="We offer a full range of landscaping services to enhance the beauty and functionality of your property, tailored to San Diego's unique climate."
|
||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
tag: "Design & Planning",
|
|
||||||
title: "Custom Garden Design",
|
title: "Custom Garden Design",
|
||||||
description: "From conceptualization to execution, we craft bespoke garden designs that reflect your style and thrive in our local environment.",
|
description: "From conceptualization to execution, we craft bespoke garden designs that reflect your style and thrive in our local environment.",
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/blossomed-beautiful-colorful-west-indian-lantana-flowers_181624-30066.jpg",
|
imageSrc: "https://storage.googleapis.com/webild/users/user_3AJc0x1D8fz8hQeSgAZ5t4kfi3f/tmp/make-a-garden-1778354006288-58a0ef89.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: "Water Management",
|
|
||||||
title: "Efficient Irrigation Systems",
|
title: "Efficient Irrigation Systems",
|
||||||
description: "Minimize water waste and maintain lush landscapes with our expertly installed and maintained irrigation systems.",
|
description: "Minimize water waste and maintain lush landscapes with our expertly installed and maintained irrigation systems.",
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/woman-working-alone-sustainable-greenhouse_23-2149072113.jpg",
|
imageSrc: "https://pixabay.com/get/gee03c76caf2072a1410b6a90291c9fc2a15e13422de8717d3b37cf15dba7a3f1e04099aa7f6e3e7d85cf7719273d7c200642bf6b83aa462832eedd86198793b4_1280.jpg?id=2900029",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: "Plant Care",
|
|
||||||
title: "Tree & Shrub Services",
|
title: "Tree & Shrub Services",
|
||||||
description: "Keep your trees and shrubs healthy and beautiful with our professional pruning, removal, and plant health care programs.",
|
description: "Keep your trees and shrubs healthy and beautiful with our professional pruning, removal, and plant health care programs.",
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/cropped-view-gardening-worker-wearing-protective-gloves-while-trimming-plants_344912-2285.jpg",
|
imageSrc: "https://pixabay.com/get/gd04c1f5508662b2129847ab2da6c712392b6afe2db7416fdb3707e2fb50a3eaee99ff69ee8f054482c6c1d486f33ed08d073f38aaf82a8db2bb54007cec1c572_1280.jpg?id=5263781",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag: "Outdoor Living",
|
|
||||||
title: "Hardscaping & Patios",
|
title: "Hardscaping & Patios",
|
||||||
description: "Create stunning outdoor living spaces with custom patios, walkways, fire pits, and retaining walls using durable materials.",
|
description: "Create stunning outdoor living spaces with custom patios, walkways, fire pits, and retaining walls using durable materials.",
|
||||||
imageSrc: "http://img.b2bpic.net/free-photo/rustic-deck-with-patio-furniture-vegetation_23-2150698456.jpg",
|
imageSrc: "http://img.b2bpic.net/free-photo/rustic-deck-with-patio-furniture-vegetation_23-2150698456.jpg",
|
||||||
|
|||||||
Reference in New Issue
Block a user