Cnippet

Flow Hero-1

Heroes 104

About

Animated hero section with carousel.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Flow Hero-1 to your project and fits it to your theme.

Code

How Flow Hero-1 is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import Autoplay from "embla-carousel-autoplay";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { ArrowRight } from "lucide-react";
import Image from "next/image";
import { useCallback, useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import {
  Carousel,
  type CarouselApi,
  CarouselContent,
  CarouselItem,
} from "@/demos/ui/carousel";
import { cn } from "@/lib/utils";

const ITEMS_COUNT = 5;

export default function Hero() {
  const [mainApi, setMainApi] = useState<CarouselApi>();
  const [thumbApi, setThumbApi] = useState<CarouselApi>();
  const [selectedIndex, setSelectedIndex] = useState(0);

  const onThumbClick = useCallback(
    (index: number) => {
      if (!mainApi || !thumbApi) return;
      mainApi.scrollTo(index);
    },
    [mainApi, thumbApi],
  );

  const onSelect = useCallback(() => {
    if (!mainApi || !thumbApi) return;
    const index = mainApi.selectedScrollSnap();
    setSelectedIndex(index);
    thumbApi.scrollTo(index);
  }, [mainApi, thumbApi]);
  const refs = useRef<any[]>([]);
  const container = useRef(null);

  const createAnimation = () => {
    gsap.to(refs.current, {
      ease: "none",
      opacity: 1,
      scrollTrigger: {
        end: `+=${window.innerHeight / 1.5}`,
        scrub: true,
        start: "top",
        trigger: container.current,
      },
      stagger: 0.1,
    });
  };

  useEffect(() => {
    gsap.registerPlugin(ScrollTrigger);
    createAnimation();
  }, [createAnimation]);



  useEffect(() => {
    if (!mainApi) return;
    onSelect();
    mainApi.on("select", onSelect);
    mainApi.on("reInit", onSelect);
    return () => {
      mainApi.off("select", onSelect);
      mainApi.off("reInit", onSelect);
    };
  }, [mainApi, onSelect]);

  return (
    <div className="mx-auto w-full max-w-7xl p-4" ref={container}>
      <div className="relative w-full overflow-hidden rounded-xl">
        <Carousel
          className="w-full"
          plugins={[
            Autoplay({
              delay: 4000,
            }),
          ]}
          setApi={setMainApi}
        >
          <CarouselContent>
            {Array.from({ length: ITEMS_COUNT }).map((_, index) => (
              <CarouselItem key={index}>
                <div className="relative aspect-video w-full overflow-hidden bg-muted">
                  <Image
                    alt={`Slide ${index + 1}`}
                    className="object-cover"
                    fill
                    priority={index === 0}
                    src={`https://images.cnippet.dev/image/upload/v1770400411/h${index+2}.jpg`}
                  />
                </div>
              </CarouselItem>
            ))}
          </CarouselContent>
        </Carousel>

        <div className="absolute inset-x-0 bottom-0 bg-linear-to-t from-black/70 to-transparent p-4 transition-opacity duration-300">
          <div className="flex items-end justify-between px-10">
            <div className="relative w-full max-w-md">
              <Carousel
                className="w-full"
                opts={{
                  containScroll: "keepSnaps",
                  dragFree: true,
                }}
                setApi={setThumbApi}
              >
                <CarouselContent className="-ml-2 flex-row items-end">
                  {Array.from({ length: ITEMS_COUNT }).map((_, index) => (
                    <CarouselItem
                      className="basis-1/4 cursor-pointer pl-2 sm:basis-1/7"
                      key={index}
                      onClick={() => onThumbClick(index)}
                    >
                      <div
                        className={cn(
                          "relative overflow-hidden transition-all duration-300",
                          index === selectedIndex
                            ? "h-20 opacity-100"
                            : "aspect-square border-white/40 opacity-50 hover:opacity-80",
                        )}
                      >
                        <Image
                          alt={`Thumb ${index + 2}`}
                          className="object-cover h-full"
                          fill
                         src={`https://images.cnippet.dev/image/upload/v1770400411/h${index+2}.jpg`}
                        />
                      </div>
                    </CarouselItem>
                  ))}
                </CarouselContent>
              </Carousel>
            </div>
            <div className="flex max-w-sm flex-col items-end gap-6">
              <div className="flex items-center gap-3">
                <div className="flex gap-1">
                  {[...Array(4)].map((_, i) => (
                    <span className="text-2xl text-orange-500" key={i}>
                      ★
                    </span>
                  ))}
                  <span className="text-2xl text-gray-400">★</span>
                </div>
                <span className="font-semibold text-lg text-white">
                  4 / 5
                </span>
              </div>

              <p className="text-right text-lg text-white leading-relaxed">
                We crafts modern, clean, and purposeful digital experiences that
                elevate brands with simplicity, clarity, and strong visual
                design.
              </p>

              <Button
                className="group relative overflow-hidden px-2 font-normal text-lg text-white hover:bg-transparent"
                variant="ghost"
              >
                View Services <ArrowRight />
                <div className="absolute bottom-0 z-20 h-px w-full bg-gray-500" />
                <div className="absolute bottom-0 z-30 h-px w-full -translate-x-40 bg-white transition-all duration-700 ease-in-out group-hover:translate-x-0" />
              </Button>
            </div>
          </div>
          <div className="">
            <h1 className="text-center font-semibold text-8xl text-white tracking-wide">
              FLOW + STUDIO
            </h1>
          </div>
        </div>
      </div>
    
    </div>
  );
}

More by Cnippet

View all
  • Team

    Team

    1.3K
  • Davincho Hero-1

    Davincho Hero-1

    683
  • Aero Hero-3

    Aero Hero-3

    558
  • Features

    Features

    510
  • Random Letter Swap Navigation

    Random Letter Swap Navigation

    487
  • Services with Animated Hover Modal

    Services with Animated Hover Modal

    465
  • Blogs

    Blogs

    396
  • Aero Hero-1

    Aero Hero-1

    356

More in Heroes

View all
  • SaaS Template

    SaaS Template

    2.4K
  • Centered Hero with Image Fan

    Centered Hero with Image Fan

    930
  • Hero

    Hero

    1.2K
  • Responsive Hero Banner

    Responsive Hero Banner

    2K
  • Minimalist Hero Fashion

    Minimalist Hero Fashion

    285
  • Home Section

    Home Section

    66
  • Hero Section 6

    Hero Section 6

    881
  • Hero Golden Spiral

    Hero Golden Spiral

    101