Files
Sportstime/marketing-videos/src/videos/TheSquad/ChatBubbles.tsx
Trey t dbb0099776 chore: remove scraper, add docs, add marketing-videos gitignore
- Remove Scripts/ directory (scraper no longer needed)
- Add themed background documentation to CLAUDE.md
- Add .gitignore for marketing-videos to prevent node_modules tracking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 18:13:12 -06:00

220 lines
6.0 KiB
TypeScript

import React from "react";
import {
AbsoluteFill,
useCurrentFrame,
useVideoConfig,
spring,
interpolate,
} from "remotion";
import { theme } from "../../components/shared/theme";
type Message = {
text: string;
sender: string;
color: string;
side: "left" | "right";
};
const messages: Message[] = [
{ text: "Lakers game?", sender: "Mike", color: "#552583", side: "left" },
{ text: "Dodgers?", sender: "Sarah", color: "#005A9C", side: "right" },
{ text: "Both??", sender: "Jake", color: "#007AFF", side: "left" },
{ text: "When though", sender: "Sarah", color: "#005A9C", side: "right" },
{ text: "idk June maybe", sender: "Mike", color: "#552583", side: "left" },
{ text: "too many options 😩", sender: "Jake", color: "#007AFF", side: "right" },
];
export const ChatBubbles: React.FC = () => {
const frame = useCurrentFrame();
const { fps, width } = useVideoConfig();
return (
<AbsoluteFill
style={{
background: theme.colors.background,
padding: 40,
paddingTop: 100,
}}
>
{/* Header - looks like a group chat */}
<div
style={{
display: "flex",
alignItems: "center",
gap: 16,
marginBottom: 40,
paddingBottom: 20,
borderBottom: "1px solid rgba(255,255,255,0.1)",
}}
>
{/* Avatar stack */}
<div style={{ display: "flex", marginLeft: 20 }}>
{["#FF6B6B", "#4ECDC4", "#45B7D1"].map((color, i) => (
<div
key={i}
style={{
width: 40,
height: 40,
borderRadius: "50%",
background: color,
border: `3px solid ${theme.colors.background}`,
marginLeft: i > 0 ? -15 : 0,
zIndex: 3 - i,
}}
/>
))}
</div>
<div>
<div
style={{
fontFamily: theme.fonts.display,
fontSize: 22,
fontWeight: 600,
color: theme.colors.text,
}}
>
LA Trip Planning
</div>
<div
style={{
fontFamily: theme.fonts.text,
fontSize: 16,
color: theme.colors.textMuted,
}}
>
3 people
</div>
</div>
</div>
{/* Messages */}
<div
style={{
display: "flex",
flexDirection: "column",
gap: 12,
}}
>
{messages.map((message, index) => {
// Stagger each message
const messageDelay = index * 6;
const localFrame = frame - messageDelay;
const entranceProgress = spring({
frame: localFrame,
fps,
config: theme.animation.snappy,
});
const opacity = interpolate(
localFrame,
[0, 5],
[0, 1],
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
);
const translateX = message.side === "left"
? interpolate(entranceProgress, [0, 1], [-50, 0])
: interpolate(entranceProgress, [0, 1], [50, 0]);
const scale = interpolate(entranceProgress, [0, 1], [0.8, 1]);
return (
<div
key={index}
style={{
display: "flex",
justifyContent: message.side === "left" ? "flex-start" : "flex-end",
opacity,
transform: `translateX(${translateX}px) scale(${scale})`,
}}
>
<div
style={{
maxWidth: "75%",
display: "flex",
flexDirection: "column",
alignItems: message.side === "left" ? "flex-start" : "flex-end",
}}
>
{/* Sender name */}
<span
style={{
fontFamily: theme.fonts.text,
fontSize: 14,
color: theme.colors.textMuted,
marginBottom: 4,
marginLeft: message.side === "left" ? 12 : 0,
marginRight: message.side === "right" ? 12 : 0,
}}
>
{message.sender}
</span>
{/* Bubble */}
<div
style={{
background: message.side === "left" ? "#2C2C2E" : message.color,
padding: "14px 20px",
borderRadius: 22,
borderBottomLeftRadius: message.side === "left" ? 6 : 22,
borderBottomRightRadius: message.side === "right" ? 6 : 22,
}}
>
<span
style={{
fontFamily: theme.fonts.text,
fontSize: 20,
color: theme.colors.text,
}}
>
{message.text}
</span>
</div>
</div>
</div>
);
})}
</div>
</AbsoluteFill>
);
};
// "Stop the chaos" text overlay
export const StopTheChaos: React.FC = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const progress = spring({
frame,
fps,
config: theme.animation.smooth,
});
const opacity = interpolate(progress, [0, 1], [0, 1]);
const translateY = interpolate(progress, [0, 1], [30, 0]);
return (
<AbsoluteFill
style={{
background: theme.colors.background,
justifyContent: "center",
alignItems: "center",
}}
>
<div
style={{
opacity,
transform: `translateY(${translateY}px)`,
fontFamily: theme.fonts.display,
fontSize: 56,
fontWeight: 700,
color: theme.colors.text,
}}
>
Stop the chaos.
</div>
</AbsoluteFill>
);
};