docs(registry,skills): surface code-highlight 0-based indexing and opacity-reveal sweep guidance (#2418)

* docs(registry,skills): surface code-highlight 0-based indexing and opacity-reveal sweep guidance

From the 2026-07-14 CLI feedback digest (skills-owner action): a user
building code teaching videos hit two authoring gaps.

1. code-highlight's `line` is intentionally zero-based (`line: 1` =
   second displayed line) but the warning lived only in pr-to-video's
   code-vocabulary reference — nowhere an author actually touches the
   value. Call it out at the block-use sites: the `__BLOCK` declaration
   itself, the registry-item description, and the motion-graphics
   catalog map.

2. Opacity-only code-typing tripped `sweep_static` for that user, who
   worked around it with a slow host y-drift. The sweep fingerprint
   does include per-element opacity, so document the actual trap (a
   reveal that settles before the sampled window, then holds a static
   frame) and the idiomatic fixes (spread the reveal / keep a blinking
   caret alive) in the check reference — and pin the fingerprint's
   opacity sensitivity with a regression test covering both the
   visibility-floor crossing and a mid-fade value change.


* docs(catalog): regenerate code-highlight page from updated registry-item description

Only the code-highlight page is committed: a full generate-catalog-pages
run also surfaces ~34 blocks missing from the git-tracked catalog index
(pre-existing drift on main), which belongs in its own chore PR.
This commit is contained in:
WaterrrForever
2026-07-16 00:27:18 +08:00
committed by GitHub
parent e038cc93c6
commit c8d13af9b2
7 changed files with 65 additions and 19 deletions
+2 -2
View File
@@ -1,11 +1,11 @@
---
title: "Code Highlight Sweep"
description: "A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line."
description: "A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line. `line` is 0-based: `line: 1` targets the second displayed line (unlike code-scroll, whose target is 1-based)."
---
# Code Highlight Sweep
A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line.
A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line. `line` is 0-based: `line: 1` targets the second displayed line (unlike code-scroll, whose target is 1-based).
`code` `code-animation` `highlight` `developer`
@@ -63,6 +63,49 @@ describe("layout-audit.browser", () => {
expect(after).not.toBe(before);
});
// Opacity-reveal fixture (CLI feedback digest 2026-07-14): code-typing style
// scenes reveal pre-laid-out characters via opacity only — no geometry ever
// moves. The sweep fingerprint must treat that as motion, both while a glyph
// fades (opacity value changes) and when it crosses the 0.2 visibility floor
// (element enters the signature); otherwise `check` misfires `sweep_static`
// and authors reach for geometry hacks (a slow host y-drift) to pass.
it("changes the sweep fingerprint when text reveals via opacity alone", () => {
document.body.innerHTML = `
<div id="root" data-composition-id="main" data-width="640" data-height="360">
<div id="code"><span id="char">c</span></div>
</div>
`;
let charOpacity = "0";
installGeometry(
{
root: rect({ left: 0, top: 0, width: 640, height: 360 }),
code: rect({ left: 40, top: 40, width: 560, height: 48 }),
char: rect({ left: 40, top: 40, width: 18, height: 48 }),
},
{
char: {
get opacity() {
return charOpacity;
},
} as Partial<CSSStyleDeclaration>,
},
);
installAuditScript();
const collect = (window as unknown as { __hyperframesLayoutGeometry: () => string })
.__hyperframesLayoutGeometry;
const hidden = collect(); // below the 0.2 visibility floor — not in the signature
charOpacity = "0.5";
const fading = collect(); // mid-fade — present, opacity part of the signature
charOpacity = "1";
const revealed = collect(); // settled
expect(fading).not.toBe(hidden);
expect(revealed).not.toBe(fading);
});
it("uses authored canvas dimensions when the root bounding rect is degenerate", () => {
document.body.innerHTML = `
<div id="root" data-composition-id="main" data-width="640" data-height="360">
+3
View File
@@ -536,6 +536,9 @@
id: "code-highlight",
effect: "highlight",
seq: "feature",
// `line` is ZERO-BASED: line: 1 highlights the SECOND displayed line
// (gutter 2). Note code-scroll's target is 1-based — don't carry a
// value between the two blocks without re-checking it.
line: 1,
duration: 5,
};
@@ -3,7 +3,7 @@
"name": "code-highlight",
"type": "hyperframes:block",
"title": "Code Highlight Sweep",
"description": "A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line.",
"description": "A highlight band sweeps across a target line while the surrounding context dims — draws the eye to one line. `line` is 0-based: `line: 1` targets the second displayed line (unlike code-scroll, whose target is 1-based).",
"dimensions": {
"width": 1920,
"height": 1080
+2 -2
View File
@@ -26,7 +26,7 @@
"files": 102
},
"hyperframes-cli": {
"hash": "bc0feefa2255c5e1",
"hash": "1065ea34fecfda50",
"files": 11
},
"hyperframes-core": {
@@ -50,7 +50,7 @@
"files": 133
},
"motion-graphics": {
"hash": "1aee662a16dedc08",
"hash": "cc93e3d220a0ebf5",
"files": 23
},
"music-to-video": {
@@ -56,7 +56,7 @@ One command, one Chrome boot. `check` runs the linter first and skips the browse
Every finding carries a selector, the element's `data-*` identity, the composition source file, a bbox, and the sample time: jump straight from the JSON to the HTML you must edit and re-run.
**Severity is persistence-aware.** A dynamic issue observed at a single grid sample (an entrance/exit transient) demotes to info and never gates. Issues held across samples gate the exit code, a held `content_overlap` is an error, and a held, partially-visible `canvas_overflow` breaching ≥5% of the canvas promotes to warning. Coordinate-frame findings (`escaped_container`, `panel_out_of_canvas`, `connector_detached`) flag geometry computed in one frame but rendered in another — an element far outside its offset parent, a painted panel stuck across the canvas edge, a connector line detached from every node. If a 3s+ composition shows zero geometry change across every sample, `check` fails with `sweep_static`: a frozen timeline makes every green verdict unreliable, so it refuses to pass.
**Severity is persistence-aware.** A dynamic issue observed at a single grid sample (an entrance/exit transient) demotes to info and never gates. Issues held across samples gate the exit code, a held `content_overlap` is an error, and a held, partially-visible `canvas_overflow` breaching ≥5% of the canvas promotes to warning. Coordinate-frame findings (`escaped_container`, `panel_out_of_canvas`, `connector_detached`) flag geometry computed in one frame but rendered in another — an element far outside its offset parent, a painted panel stuck across the canvas edge, a connector line detached from every node. If a 3s+ composition shows zero geometry change across every sample, `check` fails with `sweep_static`: a frozen timeline makes every green verdict unreliable, so it refuses to pass. The fingerprint includes per-element opacity, so opacity-only reveals (code typing, staggered fades) count as motion — but only while they're still in flight at the sampled times. The classic trap is a reveal that completes early and then holds a static frame for the rest of the duration: every sample lands on the settled state and the run fails. Spread the reveal across the timeline or keep one continuously animated element alive (a blinking caret is idiomatic for code typing) — don't bolt on a slow position drift just to appease the check.
**Escape hatches** (mark intent in the HTML, then re-run):
+13 -13
View File
@@ -10,19 +10,19 @@ After classifying intent → category, the **Director names the block(s) + what
## Category → block(s)
| Category | Borrow from catalog | Customize | Gaps → hand-author |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| **kinetic-typo** | one of **18 `caption-*`** (kinetic-slam, editorial-emphasis, clip-wipe, gradient-fill, neon-glow, glitch-rgb, matrix-decode, particle-burst, weight-shift, pill-karaoke, highlight, blend-difference…) | words; `emphasis_words``word--emphasis`; palette; font; timing | a motif none of the 18 cover |
| **charts** | `data-chart` (bar+line, staggered, value labels) | edit the data array + headline/subtitle; `--bg`/`--text` | pie/donut, bar-chart-race, ring/% |
| **stat** | `apple-money-count` (finance: $ counter + burst + SFX) **or** our generic `stat-motion` (any %/number + ring) | target, prefix/suffix, label, palette | — |
| maps/geo | **vector lane**: `us-map` (+bubble/hex/flow), `world-map`, `spain-map` + **hand-author** `geo-highlight`/`geo-flow`/`flag-borders`/`pin-rollout` (NOT in registry — build per `categories/maps/module.md`). **basemap lane** (real satellite/dark / zoom-to-place): bake via `categories/maps/bake-basemap.mjs``<video>` + geo-aligned SVG overlay (border draw-on + colour-block fills) | regions/data, palette, callouts/connectors, basemap style | (basemap lane now covers real imagery + zoom-to-address — was the gap) |
| diagram | `flowchart` (SVG connectors + nodes) | nodes, edges, labels | — |
| **code / code-reveal** | one of the **9 Code Animations** blocks: `code-typing` (live typing), `code-diff` (a change), `code-morph` (a refactor), `code-highlight` (spotlight a line), `code-scroll` (walk a file), `code-snippet-flight` (assemble); GPU hero reveals `code-3d-extrude` / `code-shader-dissolve` / `code-particle-assemble` for a title-card moment; for a static themed code/terminal window use a `code-snippet-*` block | the baked code string / diff / theme | a code motion none cover |
| **brand reveal** | `logo-outro` (piece assembly + glow + tagline + URL pill) | logo asset, tagline, URL, palette | — |
| transitions | 15+ shader transitions (domain-warp, whip-pan, sdf-iris, glitch…) | direction, timing | — |
| social overlay | ig / tiktok / yt / x / reddit / spotify / macos cards | handle, metrics, avatar | — |
| polish | grain-overlay, vignette, shimmer-sweep, texture-mask-text | intensity | — |
| **asset-fusion (RWA)** | **annotation kit from `north-korea-locked-down`** — scribble-circle draw-on, pop-up pill + pointer, red-wash, scanline, corners, camera push; + `us-map-bubble` callouts/connectors | asset, annotation position (`element_positions`), label, palette **eyedropper'd from the asset** | **NET-NEW (not in catalog): the affordance binding — asset geometry _becomes_ the chart axis (straw → gauge)** |
| Category | Borrow from catalog | Customize | Gaps → hand-author |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
| **kinetic-typo** | one of **18 `caption-*`** (kinetic-slam, editorial-emphasis, clip-wipe, gradient-fill, neon-glow, glitch-rgb, matrix-decode, particle-burst, weight-shift, pill-karaoke, highlight, blend-difference…) | words; `emphasis_words``word--emphasis`; palette; font; timing | a motif none of the 18 cover |
| **charts** | `data-chart` (bar+line, staggered, value labels) | edit the data array + headline/subtitle; `--bg`/`--text` | pie/donut, bar-chart-race, ring/% |
| **stat** | `apple-money-count` (finance: $ counter + burst + SFX) **or** our generic `stat-motion` (any %/number + ring) | target, prefix/suffix, label, palette | — |
| maps/geo | **vector lane**: `us-map` (+bubble/hex/flow), `world-map`, `spain-map` + **hand-author** `geo-highlight`/`geo-flow`/`flag-borders`/`pin-rollout` (NOT in registry — build per `categories/maps/module.md`). **basemap lane** (real satellite/dark / zoom-to-place): bake via `categories/maps/bake-basemap.mjs``<video>` + geo-aligned SVG overlay (border draw-on + colour-block fills) | regions/data, palette, callouts/connectors, basemap style | (basemap lane now covers real imagery + zoom-to-address — was the gap) |
| diagram | `flowchart` (SVG connectors + nodes) | nodes, edges, labels | — |
| **code / code-reveal** | one of the **9 Code Animations** blocks: `code-typing` (live typing), `code-diff` (a change), `code-morph` (a refactor), `code-highlight` (spotlight a line; `line` is 0-based), `code-scroll` (walk a file), `code-snippet-flight` (assemble); GPU hero reveals `code-3d-extrude` / `code-shader-dissolve` / `code-particle-assemble` for a title-card moment; for a static themed code/terminal window use a `code-snippet-*` block | the baked code string / diff / theme | a code motion none cover |
| **brand reveal** | `logo-outro` (piece assembly + glow + tagline + URL pill) | logo asset, tagline, URL, palette | — |
| transitions | 15+ shader transitions (domain-warp, whip-pan, sdf-iris, glitch…) | direction, timing | — |
| social overlay | ig / tiktok / yt / x / reddit / spotify / macos cards | handle, metrics, avatar | — |
| polish | grain-overlay, vignette, shimmer-sweep, texture-mask-text | intensity | — |
| **asset-fusion (RWA)** | **annotation kit from `north-korea-locked-down`** — scribble-circle draw-on, pop-up pill + pointer, red-wash, scanline, corners, camera push; + `us-map-bubble` callouts/connectors | asset, annotation position (`element_positions`), label, palette **eyedropper'd from the asset** | **NET-NEW (not in catalog): the affordance binding — asset geometry _becomes_ the chart axis (straw → gauge)** |
## Reuse mechanics