diff --git a/packages/cli/src/commands/init.test.ts b/packages/cli/src/commands/init.test.ts index 33248460be..9c18fdfd89 100644 --- a/packages/cli/src/commands/init.test.ts +++ b/packages/cli/src/commands/init.test.ts @@ -43,6 +43,26 @@ function expectScaffoldedScripts(target: string): void { } describe("hyperframes init flag rename", () => { + it("warm-grain without a video guards its optional A-roll timeline", () => { + const dir = mkdtempSync(join(tmpdir(), "hf-init-test-")); + const target = join(dir, "proj"); + try { + const res = runInit([ + target, + "--example", + "warm-grain", + "--non-interactive", + "--skip-skills", + ]); + expect(res.status).toBe(0); + const html = readFileSync(join(target, "index.html"), "utf-8"); + expect(html).not.toContain('id="a-roll"'); + expect(html).toContain("if (aRoll) {"); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + it("--example blank scaffolds a bundled project with npm scripts", () => { const dir = mkdtempSync(join(tmpdir(), "hf-init-test-")); const target = join(dir, "proj"); diff --git a/registry/examples/warm-grain/compositions/captions.html b/registry/examples/warm-grain/compositions/captions.html index 9e9820b88a..1333f42a35 100644 --- a/registry/examples/warm-grain/compositions/captions.html +++ b/registry/examples/warm-grain/compositions/captions.html @@ -115,35 +115,12 @@ const box = document.querySelector('[data-composition-id="captions"] #caption-box'); const textEl = document.querySelector('[data-composition-id="captions"] #caption-text'); - lines.forEach((line, index) => { - // Fade in and set text - tl.set(box, { visibility: "visible" }, line.start); - tl.to( - box, - { - opacity: 1, - duration: 0.1, - ease: "power2.out", - onStart: () => { - textEl.textContent = line.text; - }, - }, - line.start, - ); - - // Fade out at the end of the line - tl.to( - box, - { - opacity: 0, - duration: 0.1, - ease: "power2.in", - }, - line.end, - ); - - // Hard kill to ensure caption is hidden - tl.set(box, { opacity: 0, visibility: "hidden" }, line.end + 0.1); + lines.forEach((line) => { + // Switch captions atomically so contrast checks never sample a + // translucent text/background pair during a fade. + tl.set(textEl, { textContent: line.text }, line.start); + tl.set(box, { opacity: 1, visibility: "visible" }, line.start); + tl.set(box, { opacity: 0, visibility: "hidden" }, line.end); }); window.__timelines = window.__timelines || {}; diff --git a/registry/examples/warm-grain/compositions/graphics.html b/registry/examples/warm-grain/compositions/graphics.html index 97cb376590..5b743504b6 100644 --- a/registry/examples/warm-grain/compositions/graphics.html +++ b/registry/examples/warm-grain/compositions/graphics.html @@ -74,7 +74,7 @@ [data-composition-id="graphics"] #moment-2 { width: 500px; height: 220px; - background-color: #cc8832; + background-color: #a65f16; border-radius: 110px; left: 710px; top: 90px; diff --git a/registry/examples/warm-grain/compositions/intro.html b/registry/examples/warm-grain/compositions/intro.html index 393459d599..bf31fefae1 100644 --- a/registry/examples/warm-grain/compositions/intro.html +++ b/registry/examples/warm-grain/compositions/intro.html @@ -2,8 +2,10 @@
Design simplified.
++ Design simplified. +