Magic UI Components

Magic UI is a collection of re-usable animated components.

Usage

Backend AI UI exports a set of magic components that you can use in your project. You can import them from the @backend-ai/ui/components/magic module:

React

// Example:
import { AnimatedBeam } from "@backend-ai/ui/components/magic";

Animated Beam

animated-beam
Gemini

React

import type { ForwardedRef, ReactNode } from "react";
import { useRef } from "react";

import { cn } from "@backend-ai/ui/utils";

import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@backend-ai/ui/components";
import { BoxIcon, OrigamiIcon, UserIcon } from "lucide-react";

import { AnimatedBeam } from "@backend-ai/ui/components/magic";

import OpenAI from "@/components/icons/openai";
import Gemini from "@/components/icons/gemini";
import Microsoft from "@/components/icons/microsoft";
import MicrosoftAzure from "@/components/icons/microsoftAzure";

interface iCircleProps {
  ref: ForwardedRef<HTMLDivElement>;
  title: string;
  className?: string;
  children?: ReactNode;
}

const Circle = (props: iCircleProps) => {
  return (
    <TooltipProvider>
      <Tooltip delayDuration={0}>
        <TooltipTrigger asChild>
          <div
            ref={props.ref}
            className={cn(
              "z-10 flex size-12 items-center justify-center rounded-full border-2 bg-white p-3 dark:border-neutral-800 dark:bg-neutral-900",
              props.className,
            )}
          >
            {props.children}
          </div>
        </TooltipTrigger>
        <TooltipContent>
          <p>{props.title}</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
};

Circle.displayName = "Circle";

const AnimatedBeamExample = ({ className }: { className?: string }) => {
  const containerRef = useRef<HTMLDivElement>(null);

  const div0Ref = useRef<HTMLDivElement>(null);
  const div1Ref = useRef<HTMLDivElement>(null);
  const div2Ref = useRef<HTMLDivElement>(null);
  const div3Ref = useRef<HTMLDivElement>(null);
  const div4Ref = useRef<HTMLDivElement>(null);
  const div5Ref = useRef<HTMLDivElement>(null);
  const div7Ref = useRef<HTMLDivElement>(null);

  const lucideIconSize = 20;
  const logoSize = 22;

  return (
    <div
      className={cn(
        "relative flex w-full items-center justify-center overflow-hidden",
        className,
      )}
      ref={containerRef}
    >
      <div className="flex size-full max-w-lg flex-row items-stretch justify-between gap-10">
        <div className="flex flex-col justify-center">
          <Circle title="You" ref={div7Ref}>
            <UserIcon size={lucideIconSize} />
          </Circle>
        </div>
        <div className="flex flex-col justify-center">
          <Circle title="Backend AI" ref={div0Ref} className="size-16">
            <OrigamiIcon size={28} strokeWidth={1.5} />
          </Circle>
        </div>
        <div className="flex flex-col justify-center gap-2">
          <Circle title="OpenAI" ref={div1Ref}>
            <OpenAI width={logoSize} height={logoSize} />
          </Circle>
          <Circle title="Gemini" ref={div2Ref}>
            <Gemini width={logoSize} height={logoSize} />
          </Circle>
          <Circle title="Microsoft Presidio" ref={div3Ref}>
            <Microsoft width={logoSize} height={logoSize} />
          </Circle>
          <Circle title="Azure" ref={div4Ref}>
            <MicrosoftAzure width={logoSize} height={logoSize} />
          </Circle>
          <Circle title="Sandbox AI" ref={div5Ref}>
            <BoxIcon width={logoSize} height={logoSize} />
          </Circle>
        </div>
      </div>

      {/* AnimatedBeams */}
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div1Ref}
        toRef={div0Ref}
        duration={3}
      />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div2Ref}
        toRef={div0Ref}
        duration={3}
      />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div3Ref}
        toRef={div0Ref}
        duration={3}
      />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div4Ref}
        toRef={div0Ref}
        duration={3}
      />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div5Ref}
        toRef={div0Ref}
        duration={3}
      />
      <AnimatedBeam
        containerRef={containerRef}
        fromRef={div0Ref}
        toRef={div7Ref}
        duration={3}
      />
    </div>
  );
};

export default AnimatedBeamExample;

Ripple

ripple

Playground

Acceder

React

import { Ripple } from "@backend-ai/ui/components/magic";
import { ExternalLink, buttonVariants } from "@backend-ai/ui/components";
import { ArrowUpRightIcon } from "lucide-react";

const RippleExample = () => {
  return (
    <div className="bg-background relative flex h-[220px] w-full flex-col items-center justify-center overflow-hidden">
      <div className="flex flex-col items-center justify-center gap-1.5">
        <p className="z-10 whitespace-pre-wrap text-center text-4xl font-semibold tracking-tighter text-black md:text-5xl dark:text-white">
          Playground
        </p>
        <ExternalLink
          href="https://playground.atm-maggioli.es"
          className={buttonVariants({
            variant: "link",
            size: "lg",
            className:
              "hover:text-blacks space-x-1 text-neutral-600 dark:text-neutral-400 hover:dark:text-white",
          })}
        >
          <span>Acceder</span>
          <ArrowUpRightIcon size={12} />
        </ExternalLink>
      </div>
      <Ripple mainCircleSize={320} />
    </div>
  );
};

export default RippleExample;