Something new is coming.Join the waitlist

Hero 2

Previous

A hero section with a dithering background and a floating navbar.

Turn every visit into a conversation.

Chatbot which understands your product and answers visitors, without adding to your support queue.

Installation

bash npx shadcn@latest add "https://ui.srb.codes/r/hero2"

Copy and paste the following code into your project.

"use client";

import { cn } from "@/lib/utils";
import { GradientBorderButton } from "@/components/components/gradient-border-button";
import { Button } from "@/components/ui/button";
import { Dithering } from "@paper-design/shaders-react";
import { ArrowRight } from "lucide-react";
import { type Transition, motion } from "motion/react";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";

const SHADER = {
  colorFront: "#2196F3",
  shape: "warp" as const,
  type: "4x4" as const,
  size: 1.5,
  speed: 1,
  fit: "cover" as const
} as const;

const SHADER_BACK_LIGHT = "#ffffff";
const SHADER_BACK_DARK = "#000000";

const stagger: Transition = {
  type: "spring",
  stiffness: 260,
  damping: 24
};

function useShaderBackgroundColor() {
  const { resolvedTheme } = useTheme();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return SHADER_BACK_LIGHT;
  }

  return resolvedTheme === "dark" ? SHADER_BACK_DARK : SHADER_BACK_LIGHT;
}

function Hero2Background({ colorBack }: { colorBack: string }) {
  return (
    <div
      aria-hidden
      className="pointer-events-none absolute inset-0 overflow-hidden"
    >
      <Dithering
        className="absolute inset-0 size-full opacity-20"
        colorBack={colorBack}
        colorFront={SHADER.colorFront}
        shape={SHADER.shape}
        type={SHADER.type}
        size={SHADER.size}
        speed={SHADER.speed}
        fit={SHADER.fit}
      />
      <div className="absolute inset-0 bg-linear-to-r from-background/95 via-background/55 to-background/20 md:from-background/90 md:via-background/40" />
    </div>
  );
}

export interface Hero2Props {
  /** Extra classes forwarded to the outer section. */
  className?: string;
}

export function Hero2({ className }: Hero2Props) {
  const colorBack = useShaderBackgroundColor();

  return (
    <section
      data-slot="hero2"
      className={cn("relative isolate w-full overflow-hidden", className)}
    >
      <Hero2Background colorBack={colorBack} />

      <div className="relative flex min-h-[70vh] w-full items-center px-6 py-20 sm:px-8 md:py-28 lg:py-32">
        <div className="mx-auto w-full max-w-6xl">
          <div className="max-w-xl">
            <motion.h1
              initial={{ opacity: 0, y: 16, filter: "blur(6px)" }}
              animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
              transition={{ ...stagger, delay: 0.08 }}
              className="text-balance font-serif text-4xl font-medium tracking-tight text-foreground sm:text-5xl md:text-[3.25rem] md:leading-[1.08]"
            >
              Turn every visit into a{" "}
              <span className="text-primary">conversation</span>.
            </motion.h1>

            <motion.p
              initial={{ opacity: 0, y: 16, filter: "blur(6px)" }}
              animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
              transition={{ ...stagger, delay: 0.16 }}
              className="text-muted-foreground mt-5 max-w-lg text-pretty text-base leading-relaxed sm:text-lg"
            >
              Chatbot which understands your product and answers visitors,
              without adding to your support queue.
            </motion.p>

            <motion.div
              initial={{ opacity: 0, y: 16, filter: "blur(6px)" }}
              animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
              transition={{ ...stagger, delay: 0.24 }}
              className="mt-10 flex w-full flex-col gap-3 sm:w-auto sm:flex-row sm:items-center sm:gap-4"
            >
              <GradientBorderButton size="lg" asChild>
                <a href="/docs">Get Started</a>
              </GradientBorderButton>
              <Button variant="outline" size="lg" asChild>
                <a href="/docs" className="justify-center">
                  View Docs
                  <ArrowRight className="size-4" />
                </a>
              </Button>
            </motion.div>
          </div>
        </div>
      </div>
    </section>
  );
}

export Hero2;

Update the import paths to match your project setup.