iMessage UIv0.1.0

Components

LiquidGlass

A real refraction lens over live DOM (re-exported from liquid-glass-web-react). Unlike a backdrop-filter hack, the lens refracts its children — which stay selectable, clickable and scrollable. WebGL generates the displacement map; the render is a plain SVG filter.

"use client";

import { ChatBubble, IMessageScreen, LiquidGlass } from "imessage-ui";

/**
 * A real refraction lens (WebGL-generated displacement map) over live,
 * interactive DOM. Drag the pill around — the messages bend through it.
 */
export default function LiquidGlassDemo() {
  return (
    <IMessageScreen className="relative w-full max-w-sm overflow-hidden rounded-2xl p-4">
      <LiquidGlass width={200} height={64} radius="auto" draggable y={0.35}>
        <div className="flex flex-col gap-1 py-6">
          <ChatBubble variant="received" text="drag the glass pill over this thread" senderName="Riley" avatar={{ initial: "R", gradient: ["#FF9FB2", "#E0506E"] }} />
          <ChatBubble variant="sent" text="the content stays live underneath" />
          <ChatBubble variant="sent" text="clicks, selection, everything" />
          <ChatBubble variant="received" text="that's the whole point ✨" />
        </div>
      </LiquidGlass>
    </IMessageScreen>
  );
}

Usage

import { LiquidGlass } from "imessage-ui";

<LiquidGlass width={220} height={56} radius="auto" draggable>
  <Messages />
</LiquidGlass>

API reference

Accepts every engine option as an optional prop (strength, blur, depth, curvature, splay, glow, edgeHighlight, specular, quality, …) plus the layout props below. Full option reference ships with the types (LiquidGlassProps).

PropTypeDefaultDescription
width / height*numberLens size in px.
radius*number | "auto"Corner radius; "auto" = fully-rounded pill/circle.
children*ReactNodeThe content the lens refracts — stays live.
x / ynumber0.5Lens centre as a fraction of the container.
draggablebooleanfalseLet the user drag the lens.
shadowboolean | stringtrueDefault rim shadow, a custom box-shadow, or none.
onMove(x, y) => voidFires while the lens moves.
refLiquidGlassHandleelement / engine / setPosition(x, y) for per-frame moves without re-rendering React.