For the complete documentation index, see llms.txt. Markdown variants are available by appending .md to any URL or sending an Accept: text/markdown header. An agent skill is available at /.well-known/agent-skills/site-skill.md.
/
144
Sponsor

Message Bubble

A chat message bubble with rise-in animation.

Yep, pushing it live now
🔥
Customize

Installation

$ pnpm dlx shadcn@latest add @framecn/message-bubble

Usage

import { MessageBubble } from "@/components/ui/message-bubble";
<MessageBubble variant="incoming" state="visible">
  Yep, pushing it live now
</MessageBubble>

Smooth transitions

The docs preview reveals the bubble with useMessageBubbleTransition, then pops in a reaction badge with a spring-driven reactionStyle:

import {
  interpolate,
  spring,
  useCurrentFrame,
  useVideoConfig,
} from "@/lib/framecn-ui";
import { MessageBubble } from "@/components/framecn/message-bubble";
import { useMessageBubbleTransition } from "@/components/framecn/use-message-bubble-transition";
 
const REVEAL_AT = 16;
const REACT_AT = 44;
 
export const Scene = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
 
  const bubbleStyle = useMessageBubbleTransition([
    { at: REVEAL_AT, state: "visible", duration: 14 },
  ]);
 
  const reactionStyle = {
    opacity: interpolate(frame, [REACT_AT, REACT_AT + 5], [0, 1], {
      extrapolateLeft: "clamp",
      extrapolateRight: "clamp",
    }),
    scale: spring({
      fps,
      frame: frame - REACT_AT,
      config: { damping: 11, stiffness: 220, mass: 0.6 },
    }),
  };
 
  return (
    <MessageBubble
      variant="incoming"
      style={bubbleStyle}
      reaction="🔥"
      reactionStyle={reactionStyle}
    >
      Yep, pushing it live now
    </MessageBubble>
  );
};

style takes precedence over state when both are provided. Drive reactionStyle separately to animate the emoji badge independently from the bubble body.

API Reference

MessageBubble

PropTypeDefault
state"hidden" | "visible""hidden"
styleMessageBubbleStyle- (takes precedence over state)
variant"incoming" | "outgoing""incoming"
childrenReact.ReactNode-
reactionstring-
reactionStyleMessageBubbleReactionStyle-
maxWidthnumber | string460
themePartial<FramecnTheme>-
classNamestring-