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>
This commit is contained in:
219
marketing-videos/src/videos/TheSquad/ChatBubbles.tsx
Normal file
219
marketing-videos/src/videos/TheSquad/ChatBubbles.tsx
Normal file
@@ -0,0 +1,219 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user