Skip to main content
Impact: HIGH - Creates realistic chat interfaces with proper bubble styling and animations
This skill provides patterns for building WhatsApp, iMessage, and other chat-style interfaces with authentic animations and layouts.

Chat Bubble Layout

Use flexbox to align sent messages right, received messages left.
<div style={{ textAlign: "center" }}>
  {messages.map((msg) => (
    <div>{msg.text}</div>
  ))}
</div>
The maxWidth: "70%" constraint prevents messages from spanning the entire screen width, which looks unnatural in chat interfaces.

Staggered Message Entrances

Messages should appear one by one with slide + fade animations.
{
  messages.map((msg) => <Bubble text={msg.text} />);
}
Sent messages slide in from the right (40px), received messages from the left (-40px), mimicking the natural flow of conversation and matching the visual alignment.

Spring Bounce on Bubble Entrance

Add spring physics for organic bubble pop-in effect.
const bounce = spring({
  frame: frame - startFrame,
  fps,
  config: { damping: 12, stiffness: 170 }
});
const scaleValue = interpolate(bounce, [0, 1], [0.98, 1]);

<div style={{
  transform: `translateX(${slideX}px) scale(${scaleValue})`,
  transformOrigin: msg.sent ? "100% 100%" : "0% 100%"
}}>
The transformOrigin matches the bubble alignment - sent messages scale from bottom-right, received from bottom-left, creating a natural “pop” effect.

Dark Theme Colors (WhatsApp style)

const COLOR_BACKGROUND = "#0b141a";
const COLOR_SENT = "#1f8a70"; // Green for sent
const COLOR_RECEIVED = "#202c33"; // Dark gray for received
const COLOR_TEXT = "#e9edef"; // Light text
WhatsApp dark theme example

Light Theme Colors (iMessage style)

const COLOR_BACKGROUND = "#ffffff";
const COLOR_SENT = "#007AFF"; // Blue for sent
const COLOR_RECEIVED = "#E9E9EB"; // Light gray for received
const COLOR_TEXT_SENT = "#ffffff";
const COLOR_TEXT_RECEIVED = "#000000";

Key Patterns

Use justifyContent on the container:
justifyContent: msg.sent ? "flex-end" : "flex-start"
This aligns the entire message div, not just the text inside.
38 frames (~1.3 seconds at 30fps) between messages:
const STAGGER_DELAY = 38;
const startFrame = i * STAGGER_DELAY;
Mimics realistic typing and sending pace.
Slide direction matches alignment:
const slideX = msg.sent ? 40 : -40; // Right or left
Scale from the appropriate corner:
transformOrigin: msg.sent ? "100% 100%" : "0% 100%"
Sent: bottom-right, Received: bottom-left

Platform-Specific Details

Colors:
  • Sent: #1f8a70 (green)
  • Received: #202c33 (dark gray)
  • Background: #0b141a
Border Radius: 16px (highly rounded)Bubble Width: maxWidth: "70%"Tail: Optional, usually omitted for cleaner look

Common Mistakes to Avoid

Don’t center all bubbles - Chat messages should align left (received) or right (sent).
Don’t animate all messages at once - Stagger entrances to simulate realistic conversation flow.
Don’t use the same slide direction for all messages - Sent and received should slide from opposite directions.
Don’t use 100% width bubbles - Constrain to 65-70% of container width for authentic chat appearance.

Spring Physics

Configure bounce effects

Sequencing

Manage staggered timing

Typography

Add typing indicators

Build docs developers (and LLMs) love