Baktiyar Ablaikhan

Notch

Source
Aceternity UI ↗
Author
Aceternity UI
Licence
Aceternity UI licence (free component)

Loading…

A floating notch morphs into an option list that recolours and realigns the card above.

Code

"use client";
import React, { useState } from "react";
import { Notch, type NotchItem } from "@/lab/aceternity/ui/notch";
import { cn } from "@/lib/utils";

const COLORS = [
  { id: "#3b82f6", label: "Blue" },
  { id: "#8b5cf6", label: "Violet" },
  { id: "#10b981", label: "Emerald" },
  { id: "#f43f5e", label: "Rose" },
];

const ALIGNMENTS = [
  { id: "left", label: "Left" },
  { id: "center", label: "Center" },
  { id: "right", label: "Right" },
];

export default function NotchDemo() {
  const [bg, setBg] = useState("#3b82f6");
  const [align, setAlign] = useState<"left" | "center" | "right">("center");

  const items: NotchItem[] = [
    {
      id: "background",
      label: "Background",
      options: COLORS,
      value: bg,
      onChange: (id) => setBg(id),
    },
    {
      id: "alignment",
      label: "Alignment",
      options: ALIGNMENTS,
      value: align,
      onChange: (id) => setAlign(id as "left" | "center" | "right"),
    },
  ];

  const alignClass =
    align === "left"
      ? "items-start text-left"
      : align === "right"
        ? "items-end text-right"
        : "items-center text-center";

  return (
    <div className="@container relative flex h-full w-full translate-z-0 flex-col items-center overflow-hidden bg-neutral-100 pt-[3%] pb-16 dark:bg-neutral-950">
      <div
        className={cn(
          `relative flex h-full max-h-[22rem] w-full max-w-[18rem] flex-col justify-center gap-1 overflow-hidden rounded-2xl px-1 pt-1 pb-[3%] text-white shadow-xl transition-colors duration-300`,
          alignClass,
        )}
      >
        <div
          style={{ background: bg }}
          className={cn(
            "absolute inset-0 mask-t-from-10% transition-colors duration-300",
          )}
        ></div>
        {/* eslint-disable-next-line @next/next/no-img-element */}
        <img
          src="https://images.unsplash.com/photo-1559825481-12a05cc00344?q=80&w=800&auto=format&fit=crop"
          alt="The serenity of the sea"
          className="relative z-20 min-h-0 w-full flex-1 rounded-xl object-cover shadow-2xl"
        />
        <div className="px-3">
          <h3 className="relative mt-1 text-sm font-semibold @md:mt-3 @md:text-xl">
            The serenity of the sea
          </h3>
          <p className="relative hidden text-sm text-white/80 @md:block">
            Use the notch below to change my background color and text
            alignment.
          </p>
        </div>
      </div>

      <div className="absolute bottom-14 left-[calc(50%+9.5rem)] z-30 hidden items-center gap-1.5 text-neutral-600 @2xl:flex dark:text-neutral-300">
        <svg
          viewBox="0 0 120 80"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
          className="h-14 w-20"
        >
          <path d="M110 18 C70 0, 20 20, 12 60" strokeDasharray="6 6" />
          <path d="M4 48l8 14" />
          <path d="M28 56l-16 6" />
        </svg>
        <span className="text-xs font-medium">Click over here</span>
      </div>

      <Notch items={items} position="bottom" offset={12} />
    </div>
  );
}
Prompt

Build "Notch", a navigation animation. What it does: A floating notch morphs into an option list that recolours and realigns the card above. Write it as a single self-contained React component in TypeScript that fills its parent (w-full h-full), styled with Tailwind CSS, using motion. Technique: the Motion library, inline SVG. It sits on a light background, in a 16:10 frame. Respect prefers-reduced-motion with a still state, pause work when the element is off screen, and keep it accessible. Original: https://ui.aceternity.com/components/notch (Aceternity UI, Aceternity UI licence (free component)).