feat(core): declarative variable bindings — data-var-src, data-var-text, css custom props#2054
Open
Conversation
This was referenced Jul 8, 2026
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Jul 8, 2026
…xt, css custom props
Eighth PR of the template-variables stack: the no-script consumption
channel, so binding a variable to an element needs zero composition code.
- runtime resolves at init (values are fixed per page load — seek-safe,
deterministic, identical in preview and render):
- data-var-src="id" → sets the element's src from the variable value
(URL string or image {url}); authored src stays as the fallback
- data-var-text="id" → sets text content from a scalar value
- every scalar variable (and a font value's family name) is applied as
a --{id} CSS custom property on its composition root, so plain
var(--id) CSS bindings respond to render/preview overrides instead of
only the persisted default
- bindings resolve against the element's owning composition (same scope
chain as the color-grading runtime: __hfVariablesByComp for inlined
sub-comps, then the top-level merge)
- sdk: getVariableUsage counts data-var-* bindings as usage
- docs: "Declarative Bindings (No Script Required)" section in
concepts/variables.mdx
This is the foundation for the Studio "select an element → make this
property dynamic" gesture (next PR).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5751d71 to
e8b75b7
Compare
605efea to
a6b9835
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What
Eighth PR of the template-variables stack: declarative bindings — the no-script consumption channel, so connecting a variable to an element needs zero composition code.
The runtime resolves these at init and re-applies after the composition loader inlines external/template sub-compositions (their DOM and per-instance scoped values don't exist at init; the pass is idempotent):
data-var-src="id"— sets the element'ssrcfrom the variable value (URL string or image{url}); the authored src stays as the fallbackdata-var-text="id"— sets the element's own text; element children (nested clips, animated spans) are preserved via setOwnText semantics — a text binding never deletes animation targets--{id}CSS custom property on its composition root — the root is resolved with the same chain the SDK'sfindRootuses, so a persisted inline default can never shadow a runtime overrideAlso in this PR (from the post-feature review round):
runtime/variableScope.ts— the element→values scope resolver, shared with the color-grading runtime (was duplicated)unknown_variable_bindingwarning (binding id not declared — a typo'd binding silently keeps the fallback), andmedia_missing_srcdowngrades tomedia_variable_src_no_fallback(warning) for variable-bound media, explaining the audio-extraction caveatdata-var-*bindings; sharedisScalarVariableValueguard so SDK/runtime/Studio can't disagree on what "scalar" meansdocs/concepts/variables.mdx,docs/reference/html-schema.mdx(which previously claimed values "must be read and applied manually"),docs/concepts/data-attributes.mdx, and thehyperframes-coreskill referencesWhy
Variables were consumable only via
getVariables()script calls — "make this image replaceable" required glue code. This is the foundation for the Studio's select-an-element → make-it-dynamic gesture (#2055), and the right altitude: agents hand-authoring compositions get the same one-attribute binding.Known follow-ups (deliberately not in this PR)
srcattrs are rebased; a bound default likeimg.pngfrom a sub-comp can 404 after bundling)src, not the variable value — binding media with audio can produce an A/V content mismatch; the new lint warning calls this outTest plan
{url}sources, fallback preservation, own-text child preservation, idempotent re-apply, scalar + font-name CSS props, sub-composition scoping)🤖 Generated with Claude Code