โ Catalog
Edit Props (live)
config
config
Source
429 linesimport React from "react";
import {
AbsoluteFill,
useCurrentFrame,
useVideoConfig,
interpolate,
spring,
Easing,
} from "remotion";
import { loadFont as loadInter } from "@remotion/google-fonts/Inter";
import { loadFont as loadJetMono } from "@remotion/google-fonts/JetBrainsMono";
loadInter("normal", { weights: ["400", "500", "600", "700"] });
loadJetMono("normal", { weights: ["400", "500", "700"] });
const UI_FONT = "'Inter', sans-serif";
const CODE_FONT = "'JetBrains Mono', monospace";
// VS Code Dark+ palette โ accurate enough to feel like the real thing
const C = {
bgChrome: "#1f1f1f",
bgSide: "#181818",
bgEdit: "#1f1f1f",
bgTerm: "#181818",
bgActBar: "#181818",
bgStatus: "#0078d4",
border: "#2b2b2b",
ink: "#cccccc",
mute: "#9d9d9d",
faint: "#6e7681",
accent: "#3794ff",
// Syntax
comment: "#6a9955",
string: "#ce9178",
number: "#b5cea8",
keyword: "#569cd6",
type: "#4ec9b0",
fn: "#dcdcaa",
prop: "#9cdcfe",
punct: "#d4d4d4",
};
interface VSCodeUIProps {
backgroundColor?: string;
// Show the full window chrome at this scale (1 = native 1080w)
scale?: number;
}
// Token-coloured code line
const tok = (txt: string, color: string, key?: number) => (
<span key={key} style={{ color }}>{txt}</span>
);
const SkillFile: React.FC<{ name: string; active?: boolean; opacity?: number }> = ({ name, active, opacity = 1 }) => (
<div style={{
display: "flex",
alignItems: "center",
gap: 8,
padding: "3px 16px 3px 32px",
background: active ? "#2a2d2e" : "transparent",
borderLeft: active ? `2px solid ${C.accent}` : "2px solid transparent",
color: active ? "#fff" : C.ink,
fontFamily: UI_FONT,
fontSize: 17,
opacity,
}}>
<span style={{ color: "#519aba", fontSize: 14 }}>โธ</span>
<span>๐</span>
<span>{name}</span>
</div>
);
export const VSCodeUI: React.FC<VSCodeUIProps> = ({ backgroundColor = "#0a0b10", scale = 1 }) => {
const frame = useCurrentFrame();
const { fps, width, height } = useVideoConfig();
const t = frame / fps;
// Window enters with a tiny scale-up + fade
const winSp = spring({ frame, fps, config: { damping: 14, stiffness: 100, mass: 0.6 } });
const winScale = interpolate(winSp, [0, 1], [0.96, 1]);
const winOp = interpolate(frame, [0, 12], [0, 1], { extrapolateRight: "clamp" });
// Sidebar fades in first (0..0.4s)
const sideOp = interpolate(t, [0.05, 0.35], [0, 1], { extrapolateRight: "clamp", extrapolateLeft: "clamp" });
// === Cursor choreography ===
// Single move: from top-right โ terminal panel โ click โ zoom + typing.
// Sidebar files stay visible the whole time (no folder-collapse step).
const startX = 0.82, startY = 0.18;
const termX = 0.55, termY = 0.71; // 0.71 = inside terminal area (top ~0.63, bottom ~0.74)
const moveT = interpolate(t, [0.40, 1.95], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: Easing.inOut(Easing.cubic) });
const cx = startX + (termX - startX) * moveT;
const cy = startY + (termY - startY) * moveT;
const cursorVisible = t < 2.30;
// Code reveals line-by-line during the cursor's slow approach
const codeReveal = interpolate(t, [0.40, 1.85], [0, 1], {
extrapolateLeft: "clamp", extrapolateRight: "clamp",
});
// Terminal types after the click
const termStart = 2.10;
const termCmd = "$ claude /skill pdf";
const termTypedChars = Math.max(0, Math.floor((t - termStart) * 26));
const termTyped = termCmd.slice(0, Math.min(termTypedChars, termCmd.length));
const termResult = t > termStart + 1.2
? "โ pdf skill loaded โ ready"
: "";
// Active editor cursor blink in terminal
const blink = Math.floor((frame / fps) * 2) % 2 === 0;
// Window dims โ fits the 1080ร1920 frame with margins
const winW = Math.floor(1080 * 0.94);
const winH = Math.floor(1920 * 0.66);
const winX = Math.floor((1080 - winW) / 2);
const winY = Math.floor(1920 * 0.10);
// Sidebar, editor, terminal split inside the window
const actBarW = 50;
const sideW = 240;
const termH = 220;
const tabH = 42;
const titleH = 40;
const statusH = 34;
const editorH = winH - titleH - tabH - termH - statusH;
// === Zoom into terminal after the click ===
// Pin the terminal's top-left text origin to a comfortable left margin so
// the prompt ("$ claude...") is never cropped at any zoom level.
// Terminal text starts at: editor col left + 18px padding.
const termTextLeftInWin = actBarW + sideW + 18;
const termTextTopInWin = winH - statusH - termH + 40; // command line y
const termOriginXAbs = winX + termTextLeftInWin;
const termOriginYAbs = winY + termTextTopInWin;
const zoomT = interpolate(t, [2.00, 2.60], [0, 1], {
extrapolateLeft: "clamp", extrapolateRight: "clamp",
easing: Easing.inOut(Easing.cubic),
});
const zoom = 1 + 0.55 * zoomT; // 1.55x โ enough impact, terminal stays in view
// Land the text origin at frame (90, 760) โ left margin, slightly above center
const dx = (90 - termOriginXAbs) * zoomT;
const dy = (760 - termOriginYAbs) * zoomT;
// Skills list rendered inside sidebar
const skills = [
"pdf.md",
"docx.md",
"xlsx.md",
"pptx.md",
"canvas-design.md",
"frontend-design.md",
"mcp-builder.md",
"skill-creator.md",
"webapp-testing.md",
"claude-api.md",
];
// PDF.md content (token-coloured)
const codeLines: React.ReactNode[][] = [
[tok("# pdf โ Extract text + tables from PDFs", C.comment)],
[],
[tok("name", C.prop), tok(": ", C.punct), tok("pdf", C.string)],
[tok("description", C.prop), tok(": ", C.punct), tok("PDF extraction skill โ text, tables, metadata", C.string)],
[tok("inputs", C.prop), tok(":", C.punct)],
[tok(" - ", C.punct), tok("file", C.prop), tok(": ", C.punct), tok("path", C.type)],
[tok(" - ", C.punct), tok("pages", C.prop), tok(": ", C.punct), tok("optional[range]", C.type)],
[],
[tok("steps", C.prop), tok(":", C.punct)],
[tok(" 1. ", C.number), tok("open ", C.keyword), tok("pdfplumber", C.fn), tok(".load(file)", C.punct)],
[tok(" 2. ", C.number), tok("for ", C.keyword), tok("page ", C.prop), tok("in ", C.keyword), tok("doc", C.prop), tok(": extract_text()", C.punct)],
[tok(" 3. ", C.number), tok("detect_tables", C.fn), tok("(page) โ write_csv()", C.punct)],
[tok(" 4. ", C.number), tok("return ", C.keyword), tok("structured_json", C.type)],
[],
[tok("examples", C.prop), tok(":", C.punct)],
[tok(" - ", C.punct), tok('"extract invoice line items from receipt.pdf"', C.string)],
[tok(" - ", C.punct), tok('"summarize 200-page Q3 report"', C.string)],
];
// Reveal full lines at a time โ feels like fast paste/load, not slow type
const linesToShow = Math.floor(codeReveal * codeLines.length + 0.001);
const renderedLines = codeLines.map((line, li) => li < linesToShow ? line : []);
return (
<AbsoluteFill style={{
background: `radial-gradient(ellipse at 50% 35%, #14161e 0%, #06070b 75%)`,
overflow: "hidden",
}}>
{/* Zoom wrapper โ scales the entire UI (window + cursor) into terminal */}
<div style={{
position: "absolute",
inset: 0,
transform: `translate(${dx}px, ${dy}px) scale(${zoom})`,
transformOrigin: `${termOriginXAbs}px ${termOriginYAbs}px`,
}}>
{/* Decorative blurred light */}
<div style={{
position: "absolute",
top: "8%", left: "20%",
width: 600, height: 600,
background: "radial-gradient(circle, rgba(55,148,255,0.10) 0%, transparent 60%)",
filter: "blur(40px)",
pointerEvents: "none",
}} />
{/* Window */}
<div style={{
position: "absolute",
left: winX, top: winY,
width: winW, height: winH,
background: C.bgEdit,
borderRadius: 14,
boxShadow: "0 30px 80px rgba(0,0,0,0.65), 0 0 0 1px rgba(255,255,255,0.04)",
overflow: "hidden",
opacity: winOp,
transform: `scale(${winScale})`,
transformOrigin: "center center",
display: "flex",
flexDirection: "column",
}}>
{/* Title bar */}
<div style={{
height: titleH,
background: C.bgChrome,
borderBottom: `1px solid ${C.border}`,
display: "flex",
alignItems: "center",
padding: "0 16px",
gap: 8,
flexShrink: 0,
}}>
{/* mac traffic lights */}
<div style={{ width: 12, height: 12, borderRadius: "50%", background: "#ff5f57" }} />
<div style={{ width: 12, height: 12, borderRadius: "50%", background: "#febc2e" }} />
<div style={{ width: 12, height: 12, borderRadius: "50%", background: "#28c840" }} />
<div style={{ flex: 1, textAlign: "center", color: C.mute, fontFamily: UI_FONT, fontSize: 15 }}>
anthropics/skills โ Visual Studio Code
</div>
<div style={{ width: 36 }} />
</div>
{/* Body row: activity bar | sidebar | editor */}
<div style={{ display: "flex", flex: 1, minHeight: 0 }}>
{/* Activity bar */}
<div style={{
width: actBarW, background: C.bgActBar,
borderRight: `1px solid ${C.border}`,
display: "flex", flexDirection: "column", alignItems: "center",
padding: "12px 0", gap: 18,
}}>
{["๐","๐","๐","๐","๐งฉ"].map((ic, i) => (
<div key={i} style={{
fontSize: 22,
opacity: i === 0 ? 1 : 0.45,
borderLeft: i === 0 ? `2px solid #fff` : "2px solid transparent",
paddingLeft: 4,
width: "100%", textAlign: "center",
}}>{ic}</div>
))}
</div>
{/* Sidebar */}
<div style={{
width: sideW, background: C.bgSide,
borderRight: `1px solid ${C.border}`,
opacity: sideOp,
overflow: "hidden",
}}>
<div style={{
padding: "10px 16px", color: C.mute,
fontFamily: UI_FONT, fontSize: 13, letterSpacing: 1.2,
textTransform: "uppercase",
}}>
Explorer
</div>
<div style={{
padding: "4px 16px",
fontFamily: UI_FONT, fontSize: 15,
color: "#fff", display: "flex", alignItems: "center", gap: 6,
}}>
<span style={{ color: C.mute }}>โพ</span>
<span style={{ fontWeight: 600 }}>SKILLS</span>
</div>
{skills.map((s, i) => (
<SkillFile key={s} name={s} opacity={interpolate(t, [0.10 + i * 0.025, 0.25 + i * 0.025], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" })} />
))}
</div>
{/* Editor column (tabs + content + terminal) */}
<div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
{/* Tab strip */}
<div style={{
height: tabH,
background: C.bgChrome,
borderBottom: `1px solid ${C.border}`,
display: "flex", alignItems: "stretch",
flexShrink: 0,
}}>
<div style={{
background: C.bgEdit,
borderRight: `1px solid ${C.border}`,
padding: "0 18px",
display: "flex", alignItems: "center", gap: 8,
color: "#fff", fontFamily: UI_FONT, fontSize: 15,
borderTop: `2px solid ${C.accent}`,
}}>
<span style={{ color: "#519aba" }}>โธ</span>
pdf.md
<span style={{ color: C.mute, marginLeft: 6, fontSize: 18 }}>ร</span>
</div>
</div>
{/* Code area */}
<div style={{
flex: 1,
background: C.bgEdit,
padding: "16px 0 16px 0",
overflow: "hidden",
fontFamily: CODE_FONT,
fontSize: 18,
lineHeight: 1.55,
color: C.ink,
position: "relative",
}}>
{renderedLines.map((line, i) => (
<div key={i} style={{ display: "flex", paddingLeft: 16, paddingRight: 16 }}>
<span style={{ width: 36, color: C.faint, textAlign: "right", marginRight: 16, userSelect: "none" }}>
{i + 1}
</span>
<span style={{ flex: 1 }}>
{line.length === 0 ? "\u00A0" : line}
{/* Typewriter caret on the last visible line */}
{i === renderedLines.findIndex((l, ix) => ix > 0 && renderedLines[ix].length === 0 && (renderedLines[ix - 1].length > 0)) - 1 && codeReveal < 1 && (
<span style={{ background: C.ink, opacity: blink ? 1 : 0.2, marginLeft: 1 }}> </span>
)}
</span>
</div>
))}
</div>
{/* Terminal panel */}
<div style={{
height: termH,
background: C.bgTerm,
borderTop: `1px solid ${C.border}`,
padding: "10px 18px",
flexShrink: 0,
fontFamily: CODE_FONT,
}}>
{/* Terminal tabs */}
<div style={{ display: "flex", gap: 18, marginBottom: 10, color: C.mute, fontFamily: UI_FONT, fontSize: 13, letterSpacing: 1.2 }}>
<span style={{ color: "#fff", borderBottom: `1px solid ${C.accent}`, paddingBottom: 4 }}>TERMINAL</span>
<span style={{ paddingBottom: 4, opacity: 0.65 }}>PROBLEMS</span>
<span style={{ paddingBottom: 4, opacity: 0.65 }}>OUTPUT</span>
<span style={{ paddingBottom: 4, opacity: 0.65 }}>DEBUG CONSOLE</span>
</div>
<div style={{ color: C.ink, fontSize: 17, lineHeight: 1.5 }}>
<span>{termTyped}</span>
{termTypedChars < termCmd.length && (
<span style={{ background: C.ink, opacity: blink ? 1 : 0.2, marginLeft: 1 }}> </span>
)}
</div>
{termResult && (
<div style={{ color: "#73c991", fontSize: 17, marginTop: 6 }}>
{termResult}
</div>
)}
</div>
</div>
</div>
{/* Status bar */}
<div style={{
height: statusH,
background: C.bgStatus,
color: "#fff",
fontFamily: UI_FONT,
fontSize: 13,
display: "flex",
alignItems: "center",
padding: "0 14px",
gap: 18,
flexShrink: 0,
}}>
<span>โ main</span>
<span>โป 0 โ 0</span>
<span style={{ flex: 1 }} />
<span>YAML</span>
<span>UTF-8</span>
<span>LF</span>
<span>Ln {Math.min(17, Math.floor(codeReveal * 17) + 1)}, Col 1</span>
</div>
</div>
{/* Cursor */}
{cursorVisible && (
<svg width="32" height="42" viewBox="0 0 34 44" style={{
position: "absolute",
left: `${cx * 100}%`,
top: `${cy * 100}%`,
transform: "translate(-4px, -2px)",
filter: "drop-shadow(0 3px 5px rgba(0,0,0,0.6))",
zIndex: 10,
}}>
<path d="M4 4 L4 32 L11 26 L16 38 L20 36 L15 24 L24 24 Z" fill="#fff" stroke="#000" strokeWidth="1.5" />
</svg>
)}
{/* Click ripple โ terminal */}
{t > 1.95 && t < 2.45 && (
<div style={{
position: "absolute",
left: `${termX * 100}%`,
top: `${termY * 100}%`,
width: 100, height: 100,
marginLeft: -50, marginTop: -50,
borderRadius: "50%",
border: `3px solid ${C.accent}`,
opacity: interpolate(t, [1.95, 2.45], [0.95, 0]),
transform: `scale(${interpolate(t, [1.95, 2.45], [0.4, 2.0])})`,
pointerEvents: "none",
}} />
)}
</div>
</AbsoluteFill>
);
};
Schema (Zod)
// Auto-extracted from Props interface โ see source for authoritative types.
// Component: VSCodeUI
// 2 props detected ยท 0 port(s)
VSCode UI
vs_code_uiVSCode UI โ Andy's hand-crafted Remotion scene. 2 props. no ports detected โ source-only preview.
Workflow Inputs (0)
This block has no workflow-connected inputs.
Config Fields (2)
scalebackgroundColor
Meta
- Updated
- 4/21/2026