From 8b2f6ba4e3853e3022b805995865170424eca256 Mon Sep 17 00:00:00 2001 From: Eduard Barrera <119897290+eduardbar@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:37:25 -0500 Subject: [PATCH] refactor(remotion): extract demo command and stage panels --- remotion/compositions/DriftReadmeDemo.tsx | 137 ++-------------- .../compositions/DriftReadmeDemoParts.tsx | 152 +++++++++++++++++- tests/remotion-drift-readme-parts.test.ts | 72 ++++++++- 3 files changed, 231 insertions(+), 130 deletions(-) diff --git a/remotion/compositions/DriftReadmeDemo.tsx b/remotion/compositions/DriftReadmeDemo.tsx index c11ffb8..9ac94e1 100644 --- a/remotion/compositions/DriftReadmeDemo.tsx +++ b/remotion/compositions/DriftReadmeDemo.tsx @@ -2,7 +2,7 @@ import type {CSSProperties} from 'react'; import {Easing, AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion'; -import {DemoBackground, FooterStats} from './DriftReadmeDemoParts'; +import {ACTIVE_STAGE_SCALE, CommandFlowPanel, DemoBackground, FooterStats, StagePanel} from './DriftReadmeDemoParts'; const palette = { bgA: '#050d1a', @@ -25,50 +25,16 @@ const shellStyle: CSSProperties = { backdropFilter: 'blur(14px)', }; -const commandRows = [ - '$ npx @eduardbar/drift scan .', - '$ drift guard src --budget 3', - '$ drift trust src --json > trust.json', -]; - -const stages = [ - { - phase: 'Stage 01', - name: 'Scan', - text: 'Parse boundaries and dependencies with AST-level context.', - accent: palette.blue, - }, - { - phase: 'Stage 02', - name: 'Evaluate', - text: 'Compare delta risk against baseline trust and budget.', - accent: palette.mint, - }, - { - phase: 'Stage 03', - name: 'Gate', - text: 'Enforce merge policy with deterministic trust checks.', - accent: palette.violet, - }, -]; - const BODY_START_FRAME = 10; const FOOTER_START_FRAME = 34; const OUTRO_FADE_START_OFFSET_FRAMES = 14; const SWEEP_START_FRAME = 12; const SWEEP_EDGE_OFFSET_PX = 220; const PULSE_PERIOD_FRAMES = 14; -const COMMAND_REVEAL_START_FRAME = 18; -const COMMAND_REVEAL_STAGGER_FRAMES = 10; -const COMMAND_REVEAL_DURATION_FRAMES = 8; -const COMMAND_REVEAL_OFFSET_PX = 10; -const EVALUATE_STAGE_START_FRAME = 72; -const GATE_STAGE_START_FRAME = 108; const PULSE_MIN_SCALE = 0.95; const PULSE_MAX_SCALE = 1.07; const TITLE_INITIAL_OFFSET_PX = 36; const BODY_INITIAL_OFFSET_PX = 28; -const ACTIVE_STAGE_SCALE = 1.02; export const DriftReadmeDemo = () => { const frame = useCurrentFrame(); @@ -110,8 +76,6 @@ export const DriftReadmeDemo = () => { }); const pulse = interpolate(Math.sin(frame / PULSE_PERIOD_FRAMES), [-1, 1], [PULSE_MIN_SCALE, PULSE_MAX_SCALE]); - const activeStage = frame < EVALUATE_STAGE_START_FRAME ? 0 : frame < GATE_STAGE_START_FRAME ? 1 : 2; - return ( { minHeight: 0, }} > -
-
- Typical PR check flow -
- {commandRows.map((line, index) => { - const start = COMMAND_REVEAL_START_FRAME + index * COMMAND_REVEAL_STAGGER_FRAMES; - const reveal = interpolate(frame, [start, start + COMMAND_REVEAL_DURATION_FRAMES], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - return ( -
- {line} -
- ); - })} -
- -
- {stages.map((stage, index) => { - const isActive = index === activeStage; - return ( -
-
- {stage.phase} -
-
{stage.name}
-
- {stage.text} -
-
- ); - })} -
+ + diff --git a/remotion/compositions/DriftReadmeDemoParts.tsx b/remotion/compositions/DriftReadmeDemoParts.tsx index 3301e5b..a8195c6 100644 --- a/remotion/compositions/DriftReadmeDemoParts.tsx +++ b/remotion/compositions/DriftReadmeDemoParts.tsx @@ -1,6 +1,41 @@ import type {CSSProperties, ReactNode} from 'react'; -import {AbsoluteFill} from 'remotion'; +import {AbsoluteFill, interpolate} from 'remotion'; + +const COMMAND_REVEAL_START_FRAME = 18; +const COMMAND_REVEAL_STAGGER_FRAMES = 10; +const COMMAND_REVEAL_DURATION_FRAMES = 8; +const COMMAND_REVEAL_OFFSET_PX = 10; +const EVALUATE_STAGE_START_FRAME = 72; +const GATE_STAGE_START_FRAME = 108; +export const ACTIVE_STAGE_SCALE = 1.02; + +const commandRows = [ + '$ npx @eduardbar/drift scan .', + '$ drift guard src --budget 3', + '$ drift trust src --json > trust.json', +]; + +const stages = [ + { + phase: 'Stage 01', + name: 'Scan', + text: 'Parse boundaries and dependencies with AST-level context.', + accent: '#67a7ff', + }, + { + phase: 'Stage 02', + name: 'Evaluate', + text: 'Compare delta risk against baseline trust and budget.', + accent: '#46d9b0', + }, + { + phase: 'Stage 03', + name: 'Gate', + text: 'Enforce merge policy with deterministic trust checks.', + accent: '#8a7dff', + }, +]; const GRID_INSET_PX = 120; const GLOW_TOP_OFFSET_PX = 120; @@ -79,3 +114,118 @@ export const FooterStats = ({mutedColor, opacity, shellStyle}: FooterStatsProps) ); }; + +type CommandFlowPanelProps = { + frame: number; + lineColor: string; + mutedColor: string; + shellStyle: CSSProperties; +}; + +export const CommandFlowPanel = ({frame, lineColor, mutedColor, shellStyle}: CommandFlowPanelProps): ReactNode => { + return ( +
+
+ Typical PR check flow +
+ {commandRows.map((line, index) => { + const start = COMMAND_REVEAL_START_FRAME + index * COMMAND_REVEAL_STAGGER_FRAMES; + const reveal = interpolate(frame, [start, start + COMMAND_REVEAL_DURATION_FRAMES], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ {line} +
+ ); + })} +
+ ); +}; + +type StagePanelProps = { + frame: number; + activeScale: number; + lineColor: string; + mutedColor: string; + shellStyle: CSSProperties; +}; + +export const StagePanel = ({frame, activeScale, lineColor, mutedColor, shellStyle}: StagePanelProps): ReactNode => { + const activeStage = frame < EVALUATE_STAGE_START_FRAME ? 0 : frame < GATE_STAGE_START_FRAME ? 1 : 2; + + return ( +
+ {stages.map((stage, index) => { + const isActive = index === activeStage; + return ( +
+
+ {stage.phase} +
+
{stage.name}
+
{stage.text}
+
+ ); + })} +
+ ); +}; diff --git a/tests/remotion-drift-readme-parts.test.ts b/tests/remotion-drift-readme-parts.test.ts index 2651804..8719555 100644 --- a/tests/remotion-drift-readme-parts.test.ts +++ b/tests/remotion-drift-readme-parts.test.ts @@ -1,7 +1,12 @@ import {createRequire} from 'node:module'; import {resolve} from 'node:path'; -import {DemoBackground, FooterStats} from '../remotion/compositions/DriftReadmeDemoParts'; +import { + CommandFlowPanel, + DemoBackground, + FooterStats, + StagePanel, +} from '../remotion/compositions/DriftReadmeDemoParts'; const runtimeRequire = createRequire(resolve(process.cwd(), 'package.json')); const {createElement} = runtimeRequire('react') as typeof import('react'); @@ -11,6 +16,12 @@ function render(component: Parameters[0], props: Record', '>'); + const escapedCommand = renderedCommand.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return markup.match(new RegExp(`
${escapedCommand}
`))?.[1] ?? ''; +} + describe('Remotion README demo extracted parts', () => { test('renders background layers and applies animation inputs to their styles', () => { const markup = render(DemoBackground, {pulse: 1.05, sweepX: 321}); @@ -38,4 +49,63 @@ describe('Remotion README demo extracted parts', () => { expect(markup).toContain('grid-template-columns:repeat(3, minmax(0, 1fr))'); expect(markup).toContain('color:#9eb6cb'); }); + + test.each([ + [0, '$ npx @eduardbar/drift scan .'], + [1, '$ drift guard src --budget 3'], + [2, '$ drift trust src --json > trust.json'], + ])('reveals command row %i at every reveal boundary', (index, command) => { + const start = 18 + index * 10; + const renderAt = (frame: number) => + render(CommandFlowPanel, { + frame, + lineColor: 'rgba(135, 179, 230, 0.22)', + mutedColor: '#9eb6cb', + shellStyle: {borderRadius: 30}, + }); + + const beforeReveal = renderAt(start - 1); + const atReveal = renderAt(start); + const afterReveal = renderAt(start + 8); + + expect(commandRowStyle(beforeReveal, command)).toContain('opacity:0'); + expect(commandRowStyle(beforeReveal, command)).toContain('translateY(10px)'); + expect(commandRowStyle(atReveal, command)).toContain('opacity:0'); + expect(commandRowStyle(atReveal, command)).toContain('translateY(10px)'); + expect(commandRowStyle(afterReveal, command)).toContain('opacity:1'); + expect(commandRowStyle(afterReveal, command)).toContain('translateY(0px)'); + }); + + test.each([0, 71, 72, 107, 108])('keeps the correct stage active at frame %i boundary', (frame) => { + const markup = render(StagePanel, { + frame, + activeScale: 1.02, + lineColor: 'rgba(135, 179, 230, 0.22)', + mutedColor: '#9eb6cb', + shellStyle: {borderRadius: 30}, + }); + + const expectedActiveIndex = frame < 72 ? 0 : frame < 108 ? 1 : 2; + const transforms = [...markup.matchAll(/transform:translateY\((-2|0)px\) scale\((1\.02|1)\)/g)].map( + ([, offset, scale]) => `${offset}:${scale}`, + ); + + expect(markup).toContain('Stage 01'); + expect(markup).toContain('Stage 02'); + expect(markup).toContain('Stage 03'); + expect(transforms).toHaveLength(3); + expect(transforms[expectedActiveIndex]).toBe('-2:1.02'); + expect(transforms.filter((transform) => transform === '0:1')).toHaveLength(2); + + const accents = ['#67a7ff', '#46d9b0', '#8a7dff']; + const activeAccent = accents[expectedActiveIndex]; + expect(markup).toContain(`border:1px solid ${activeAccent}`); + expect(markup).toContain( + `background:linear-gradient(145deg, rgba(255,255,255,0.16), rgba(255,255,255,0.06)), radial-gradient(circle at 100% 0%, ${activeAccent}33, transparent 60%)`, + ); + expect(markup).toContain(`box-shadow:0 12px 24px ${activeAccent}22`); + expect(markup.match(/border:1px solid rgba\(135, 179, 230, 0\.22\)/g) ?? []).toHaveLength(2); + expect(markup.match(/background:rgba\(7, 19, 38, 0\.64\)/g) ?? []).toHaveLength(2); + expect(markup.match(/box-shadow:none/g) ?? []).toHaveLength(2); + }); });