Component Refs
Component Refs
Developer Agent Kit — documentation written for AI agents, readable by humans.
Refs provide access to DOM elements declared as interactive in the contract. They are the second parameter of the interactive constructor.
Single Refs
A ref maps to one DOM element:
# Contract
- tag: addToCart
type: interactive
elementType: HTMLButtonElement
// Component
.withInteractive(function MyComp(props, refs) {
refs.addToCart.onClick(() => {
// handle click
});
})
Ref Methods
Refs provide type-safe access to the DOM element:
refs.submitButton.onClick(() => {
/* ... */
});
// exec$ gives direct access to the element and current ViewState.
// Only use exec$ inside event handlers — never at top-level component
// creation or in effects, because elements don't exist yet at that point.
refs.submitButton.onclick(() => {
refs.submitButton.exec$((element, viewState) => {
element.disabled = viewState.isSubmitting;
});
});
Collection Refs
When an interactive tag is inside a repeated sub-contract, the ref becomes a collection. In jay-html, collection refs use the $ suffix:
<div forEach="items" trackBy="id">
<button ref="itemButton$">Click</button>
</div>
The $ is stripped from the name in the contract and component code:
# Contract
- tag: items
type: sub-contract
repeated: true
trackBy: id
tags:
- tag: id
type: data
dataType: string
- tag: itemButton
type: interactive
elementType: HTMLButtonElement
Collection Ref Methods
// Map over all items in the collection
const labels = refs.itemButton.map((proxy, viewState, coordinate) => {
return viewState.name;
});
// Find a specific item
const target = refs.itemButton.find((viewState) => viewState.id === 'target-id');
// Find by coordinate
const target = refs.itemButton.find((viewState, coordinate) =>
sameCoordinate(coordinate, ['item-2', 'itemButton']),
);
Element Types
Common element types for interactive tags:
| Element Type | Use For |
|---|---|
HTMLButtonElement |
Buttons, clickable |
HTMLAnchorElement |
Links |
HTMLInputElement |
Text inputs, checkbox |
HTMLSelectElement |
Dropdowns |
HTMLTextAreaElement |
Multi-line text |
HTMLFormElement |
Forms |
HTMLDivElement |
Generic containers |
Multiple element types (when the same ref may bind to different elements):
- tag: trigger
type: interactive
elementType: HTMLButtonElement | HTMLAnchorElement
Data + Interactive
A tag can be both data and interactive:
- tag: quantityInput
type: [data, interactive]
dataType: number
elementType: HTMLInputElement
This generates both a ViewState field and a ref.
DOM access rules (Jay Stack pages)
Refs are the only supported path from TypeScript to elements Jay renders. Direct document access bypasses the framework and can break rendering, updates, and performance.
Do
- Declare elements in jay-html with
ref="...". - Drive overlays, lists, and visibility with ViewState (
if,forEach, signal-backed bindings). - Attach handlers with ref APIs:
refs.myRef.onclick,oninput,onkeydown, etc. - Use
refs.myRef.exec$((element, viewState) => …)inside handlers for focus, scroll, measure, or native APIs. - For drags:
setPointerCaptureon the ref element that receivedpointerdown, then listen on that element.
Avoid
document.querySelector/getElementByIdto find template elementsdocument.createElement+appendChildfor UI that belongs in jay-htmldocument.addEventListener('mousemove'|'mouseup')for drags (use pointer capture instead)
Rare document exceptions
Use only when no ref can exist, with an inline comment:
| Case | Example |
|---|---|
| Offscreen processing | document.createElement('canvas') for image export |
| Coordinate hit-testing | document.elementFromPoint during cross-overlay drag |
| Tests | document.dispatchEvent in Vitest |
Global shortcuts or paste: prefer a root shell ref (ref="appRoot") with capture listeners.
See also: .cursor/skills/jay-dom-refs/SKILL.md in the jay monorepo.
About this document
This page is part of the Jay Stack Agent Kit — documentation generated from the framework source and written primarily for AI agents. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation. Learn more about the Agent Kit →