iMessage UIv0.1.0

Components

InputBar

The auto-growing iMessage composer: pill textarea + spring-loaded send button. Enter sends (IME-safe, Shift+Enter for newlines), and it deliberately never steals focus — programmatic focus is what causes iOS Safari's keyboard bounce.

Riley
try sending something
"use client";

import { useState } from "react";
import { InputBar, ChatBubble, IMessageScreen } from "imessage-ui";

export default function InputBarDemo() {
  const [draft, setDraft] = useState("");
  const [sent, setSent] = useState<string[]>([]);

  return (
    <IMessageScreen className="w-full max-w-sm rounded-2xl p-4">
      <ChatBubble variant="received" text="try sending something" senderName="Riley" avatar={{ initial: "R", gradient: ["#FF9FB2", "#E0506E"] }} />
      {sent.map((text, i) => (
        <ChatBubble key={i} variant="sent" text={text} isNewlySent={i === sent.length - 1} />
      ))}
      {/* `embedded` keeps the bar in flow; Enter sends, Shift+Enter breaks. */}
      <div className="mt-3">
        <InputBar
          embedded
          value={draft}
          onChange={setDraft}
          onSend={text => {
            setSent(prev => [...prev, text]);
            setDraft("");
          }}
        />
      </div>
    </IMessageScreen>
  );
}

Usage

import { InputBar } from "imessage-ui";

<InputBar embedded value={draft} onChange={setDraft} onSend={send} />

Examples

Emphasis

"use client";

import { useState } from "react";
import { InputBar, IMessageScreen } from "imessage-ui";

/**
 * `emphasis` draws attention to the pill: "awaiting" is a subtle border tint
 * (the conversation is paused on the user), "highlight" is a golden glow for
 * a question aimed directly at them.
 */
export default function EmphasisDemo() {
  const [awaiting, setAwaiting] = useState("");
  const [highlight, setHighlight] = useState("");

  return (
    <IMessageScreen className="flex w-full max-w-sm flex-col gap-3 rounded-2xl p-4">
      <InputBar
        embedded
        emphasis="awaiting"
        placeholder="Riley is waiting on you…"
        value={awaiting}
        onChange={setAwaiting}
        onSend={() => setAwaiting("")}
      />
      <InputBar
        embedded
        emphasis="highlight"
        placeholder="This one's for you specifically"
        value={highlight}
        onChange={setHighlight}
        onSend={() => setHighlight("")}
      />
    </IMessageScreen>
  );
}

Liquid Glass

"use client";

import { useState } from "react";
import { InputBar, IMessageScreen } from "imessage-ui";

/** iOS 26 Liquid Glass styling with the leading "+" attachment button. */
export default function GlassInputDemo() {
  const [draft, setDraft] = useState("");

  return (
    <IMessageScreen
      variant="glass"
      wallpaper="/memorymap/images/memorymap-12.jpg"
      className="flex w-full max-w-sm flex-col justify-end overflow-hidden rounded-2xl p-4 pt-16"
    >
      <InputBar
        embedded
        glass
        onPlus={() => {}}
        value={draft}
        onChange={setDraft}
        onSend={() => setDraft("")}
      />
    </IMessageScreen>
  );
}

glass restyles the pill as iOS 26 glass; onPlus adds the leading attachment button.

API reference

PropTypeDefaultDescription
value*stringControlled draft value.
onChange*(next: string) => voidDraft updates.
onSend*(text: string) => voidCalled with the trimmed draft on send.
placeholderstring"iMessage"Pill placeholder.
disabledbooleanfalseDisable input + send.
emphasis"awaiting" | "highlight"Attention states: subtle border tint vs golden glow. Purely visual — pair with a matching placeholder.
submitOnEnterbooleantrueEnter sends (skips IME composition); Shift+Enter inserts a newline.
embeddedbooleanfalseNormal flow instead of the keyboard-tracked full-screen footer.
glassbooleanfalseiOS 26 Liquid Glass pill styling.
onPlus() => voidRenders the leading "+" capsule (glass mode only).
onFocus / onBlur() => voidFocus notifications (e.g. snap-scroll to bottom).

Accessibility

The textarea is labelled "Message", the send button "Send message"; send stays disabled until the trimmed draft has content.