Saurabh

BeUI Dynamic Island

Cards 99

About

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds BeUI Dynamic Island to your project and fits it to your theme.

Code

How BeUI Dynamic Island is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";

import { motion, useReducedMotion } from "motion/react";
import { Music, Phone, PhoneOff, Timer } from "lucide-react";
import { useEffect, useState, type ReactNode } from "react";
import {
  DynamicIsland,
  DynamicIslandView,
  NumberTicker,
  cn,
} from "@/components/ui/be-ui-dynamic-island";

type IslandView = "call" | "timer" | "music" | null;

const BAR_DELAYS = [0, 0.18, 0.09, 0.27];

function Button({
  children,
  onClick,
  variant = "secondary",
}: {
  children: ReactNode;
  onClick?: () => void;
  variant?: "secondary" | "ghost";
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "inline-flex h-9 items-center justify-center rounded-full px-4 text-sm font-medium transition-transform active:scale-[0.97]",
        variant === "secondary" &&
          "border border-border bg-card text-foreground hover:bg-muted",
        variant === "ghost" &&
          "text-muted-foreground hover:bg-muted hover:text-foreground",
      )}
    >
      {children}
    </button>
  );
}

function EqBars() {
  const reduce = useReducedMotion();

  return (
    <span className="flex h-4 items-end gap-0.5" aria-hidden>
      {BAR_DELAYS.map((delay) => (
        <motion.span
          key={delay}
          animate={
            reduce ? undefined : { scaleY: [0.4, 1, 0.55, 0.9, 0.4] }
          }
          transition={{
            duration: 1.1,
            repeat: Infinity,
            ease: "easeInOut",
            delay,
          }}
          className="h-full w-0.5 origin-bottom rounded-full bg-emerald-500"
          style={{ scaleY: 0.6 }}
        />
      ))}
    </span>
  );
}

function formatClock(totalSeconds: number) {
  const m = Math.floor(totalSeconds / 60);
  const s = totalSeconds % 60;

  return `${m}:${String(s).padStart(2, "0")}`;
}

export default function DynamicIslandPreview() {
  const [view, setView] = useState<IslandView>(null);
  const [seconds, setSeconds] = useState(154);

  useEffect(() => {
    if (view !== "timer") return;

    const id = window.setInterval(() => {
      setSeconds((s) => (s > 0 ? s - 1 : 0));
    }, 1000);

    return () => window.clearInterval(id);
  }, [view]);

  return (
    <div className="flex w-full flex-col items-center gap-4">
      <div className="flex h-32 w-full items-start justify-center pt-2">
        <DynamicIsland
          view={view}
          compact={
            <>
              <span className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
              <span>9:41</span>
            </>
          }
        >
          <DynamicIslandView id="call" className="gap-4">
            <div className="flex flex-col">
              <span className="text-[10px] uppercase tracking-wider opacity-60">
                Incoming call
              </span>
              <span className="text-sm font-semibold">Saurabh</span>
            </div>

            <div className="flex items-center gap-2">
              <button
                type="button"
                aria-label="Decline"
                onClick={() => setView(null)}
                className="flex h-8 w-8 items-center justify-center rounded-full bg-red-500 text-white"
              >
                <PhoneOff className="h-3.5 w-3.5" />
              </button>

              <button
                type="button"
                aria-label="Accept"
                onClick={() => setView(null)}
                className="flex h-8 w-8 items-center justify-center rounded-full bg-emerald-500 text-white"
              >
                <Phone className="h-3.5 w-3.5" />
              </button>
            </div>
          </DynamicIslandView>

          <DynamicIslandView id="timer" className="gap-3">
            <Timer className="h-4 w-4 text-orange-500" />

            <span className="text-[10px] uppercase tracking-wider opacity-60">
              Timer
            </span>

            <NumberTicker
              value={seconds}
              format={formatClock}
              startOnView={false}
              duration={0.5}
              className="text-sm font-semibold"
            />
          </DynamicIslandView>

          <DynamicIslandView id="music" className="gap-3">
            <span className="flex h-7 w-7 items-center justify-center rounded-lg bg-background/15">
              <Music className="h-3.5 w-3.5" />
            </span>

            <div className="flex flex-col text-left">
              <span className="text-xs font-semibold leading-tight">
                Midnight City
              </span>
              <span className="text-[10px] opacity-60">M83</span>
            </div>

            <EqBars />
          </DynamicIslandView>
        </DynamicIsland>
      </div>

      <div className="flex flex-wrap items-center justify-center gap-2">
        <Button onClick={() => setView("call")}>Call</Button>

        <Button
          onClick={() => {
            setSeconds(154);
            setView("timer");
          }}
        >
          Timer
        </Button>

        <Button onClick={() => setView("music")}>Music</Button>

        <Button variant="ghost" onClick={() => setView(null)}>
          Dismiss
        </Button>
      </div>
    </div>
  );
}

Dependencies

More by Saurabh

View all
  • BeUI Tilt Card

    BeUI Tilt Card

    363
  • BeUI Expandable Tabs

    BeUI Expandable Tabs

    337
  • BeUI File Upload

    BeUI File Upload

    286
  • BeUI Create Menu

    BeUI Create Menu

    199
  • BeUI Bouncy Accordion

    BeUI Bouncy Accordion

    198
  • BeUI Expanable Action Bar

    BeUI Expanable Action Bar

    181
  • Loader

    Loader

    171
  • BeUI OTP Input

    BeUI OTP Input

    166

More in Cards

View all
  • Course Design Cards

    Course Design Cards

    1.1K
  • Stats cards with links

    Stats cards with links

    119
  • Statistics Card 2

    Statistics Card 2

    258
  • Card

    Card

    55
  • Statistics Card 7

    Statistics Card 7

    288
  • The Item one

    The Item one

    3
  • Card Studio

    Card Studio

    9
  • Weather Card

    Weather Card

    52