Files
Miguel Ángel b2fc18b2df fix(skills,lint): correct composition-contract claims the code contradicts (#3468)
The runtime absorbed a series of authoring mistakes over time and `runtime/init.ts`
says so in its own comments, but the skills kept teaching the old rules. Four of
them actively cost an agent a failing run: add `crossorigin` (lint rejects it
unconditionally), never build a timeline inside `async` (lint calls that the
documented contract), never `gsap.set` later-scene clips (two fixHints instruct
exactly that), and 12 copyable media snippets with no `id`, which render silent.

Corrected in every place each claim appeared, including `hyperframes-animation`,
three workflow scripts, the scaffolded project instructions, the CLI `docs`
command, and the public docs site: `data-track-index` is a Studio display lane
the render never reads, `class="clip"` is a layout convention rather than a
visibility requirement, timed elements may nest, the visibility window is
half-open, sub-composition host dimensions are backfilled, and the root-fill rule
applies only to the layered-composite path.

Behaviour changes, each backed by a render rather than by reading code:

- `timeline_registry_missing_init` deleted. The runtime creates the registry
  before any inline script; a composition without the guard line renders and
  animates correctly.
- `video_nested_in_timed_element` kept, message corrected. A rendered repro shows
  the nested-with-local-start case really does break, so the rule guards a real
  defect, but nothing is "FROZEN": the extractor ignores the wrapper's offset
  while visibility uses it, so the clip shows wrong frames and then vanishes.
- `mediaRenderIds` now stamps media whose source is a `<source>` child, closing a
  duplicate-id gap the old `[src]`-only selector left open.
- Stale messages fixed on `subcomposition_root_styled_by_class` and
  `deprecated_data_layer`.

`coreSkillContent.test.ts` pinned the literal sentence that made root
`data-start` look required, so it is narrowed to structure plus the regression it
genuinely catches.

Not covered, and flagged in the PR: the media global-vs-local start heuristic in
`runtime/init.ts` is the root cause behind the nested-video defect. Removing it
changes the meaning of existing compositions and needs its own deprecation.
2026-08-24 18:04:39 -04:00

71 lines
2.5 KiB
Plaintext

---
title: "Time elements with data attributes"
sidebarTitle: "Data attributes"
description: "Place clips on the HyperFrames timeline without putting timing logic in JavaScript."
---
HyperFrames keeps timing in HTML. A timed element normally needs a stable ID,
a start, a duration, and a track:
```html
<section id="headline" class="clip" data-start="0" data-duration="3" data-track-index="1">
Launch day
</section>
```
| Attribute | What it controls |
| ------------------ | ------------------------------------------------ |
| `data-start` | When the element enters the composition timeline |
| `data-duration` | How long its timeline slot lasts |
| `data-track-index` | Which Studio lane displays it (optional; the render ignores it) |
Add `class="clip"` to timed DOM and image elements. The runtime keys visibility
off `data-start` rather than the class, but the shared `.clip` rule is what gives
a scene its full-frame box. Video visibility is managed by the media runtime;
audio has no visual lifecycle.
## Tracks are not layers
Tracks are the rows Studio draws. They do not decide which element is in front,
and they do not schedule anything. Use CSS `z-index` for paint order.
Two clips on one track may overlap; the render composites both. Separate tracks
keep an intentional overlap, such as a crossfade, readable in Studio:
```html
<video
id="intro"
data-start="0"
data-duration="4"
data-track-index="0"
src="./intro.mp4"
muted
playsinline
></video>
<section id="result" class="clip" data-start="intro - 0.5" data-duration="3" data-track-index="1">
The result
</section>
```
## Start relative to another clip
A numeric `data-start` is an absolute time in seconds. A clip ID means “start
when that clip ends.” Add or subtract seconds for a gap or overlap:
```html
data-start="intro" data-start="intro + 0.5" data-start="intro - 0.5"
```
References resolve only inside the same composition. The referenced clip must
have a known duration, and reference chains cannot contain a cycle.
## Media and nested compositions
Media can also declare a source offset, playback rate, and volume. A nested
composition adds a source path and its own fixed timeline window. These are
exact contracts rather than new timing models.
Use the [HTML schema reference](/reference/html-schema) for every supported
attribute and element-specific rule. Use [Compositions](/concepts/compositions)
to decide when a scene should become a separate composition.