Repository navigation
feat(sdk): a Data App's structure, read from its markup, in the inspect panel - #31
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces element bindings to the Anfra SDK, allowing queries and controls to be bound to DOM elements via CSS selectors. It also implements a 'locate' feature that enables the host to request the frame to scroll to and highlight these bound elements. The UI has been updated with 'Locate' buttons in the inspect panel, and comprehensive tests have been added. The review feedback highlights two important improvements in 'elements.ts': ensuring the 'unbind' method trims input selectors to match 'bind' and avoid silent failures, and replacing the unsafe '(element as HTMLElement).offsetWidth' cast with 'element.getBoundingClientRect()' to safely trigger reflows on both HTML and SVG elements.
c2f50fe to
e143d74
Compare
…te it A definition marks its semantic parts on its own elements: data-anfra-container and data-anfra-block (ids, unique per kind, with an optional data-anfra-label), and data-anfra-query / data-anfra-control on the elements an entity draws into, as "name" or "app/name". The app runtime reads them into a tree of nodes, with problems (an unknown name, a duplicate id, a block inside a block) reported on the node and never thrown, and posts it in the inspect snapshot beside the apps, with where each entity is drawn. Only while a host inspects: then a mutation observer limited to elements and the five attributes keeps it current, and nothing runs otherwise. The host asks the frame to highlight a node, locate one (or an entity wherever it is drawn), and to start or stop pick mode; the frame draws one overlay (a tinted box and a label) over the marked element, and in pick mode reports the node under a click without letting the click through. `query.locate()` and `control.locate()` find their marked elements the same way, for a button of the app's own. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The panel becomes a devtool with two tabs. Structure shows the page's marked parts as a tree: hovering a node highlights it on the page, clicking scrolls to it and opens a detail pane (id, label, problems, and the entity's card for a query or control), Pick chooses a node from the page, and Copy handle puts `[Label](data-anfra-block="id")` on the clipboard for an agent. Data holds the cards, each saying in how many places and which blocks its entity is drawn, with a Locate button. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
e143d74 to
8fb3ec1
Compare
The label read as one run of text joined by dots. It is now parts the eye can tell apart, as a browser's element inspector does: the kind muted, the id or name bold, the author's label beside it, a note such as "1 of 3", and the size at the right. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The problems the tree reports, the cards' "drawn" line, the pick hint and the empty state now say what is wrong or what to do in one plain sentence each, instead of a clause joined to a rule. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
d9a19a8 to
5e40369
Compare
Choosing a node in the tree ends pick mode, as a click on the page does, and a pick clears the overlay it left: the overlay shows only while the reader hovers the tree. The Structure tab's toolbar (Pick, Copy handle) is its own row between the tab header and the tree, outside what scrolls. The handle row in the detail pane has a copy button of its own, shown on hover. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
5e40369 to
8745c5f
Compare
A dynamic app declares queries and controls while the page runs. A host inspecting it saw the new entity only on the next change, usually its first run, and a node marked with its name was flagged as unknown until then. Declaring, and mapping, now notify like any other change; a render subscribed to the app runs once more, which it handles already for an entity with no result. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A Data App can mark its parts in its own HTML. The inspect panel in
anfra servethen shows them as a tree, like a browser's element inspector: hover a node to see it on the page, click to scroll to it, pick one from the page, and copy a handle for an agent.Markup
Five attributes.
data-anfra-container="id"anddata-anfra-block="id"name the parts, with an optionaldata-anfra-label.data-anfra-queryanddata-anfra-controlgo on the elements an entity draws into, asnameorapp/name. Ids are unique per kind. A block holds no container or block, and a control lives in a block the way a query does.The markup is optional. A wrong name, a duplicate id or a block inside a block shows up as a sentence on that node in the tree. Nothing throws.
SDK
While a host inspects, the app runtime reads the attributes into a tree and posts it with the snapshot, along with how many places draw each entity and in which blocks. A mutation observer keeps the tree current; it watches elements coming and going and the five attributes, and nothing else. A frame nobody inspects does no work.
Declaring a query, control or mapping now notifies subscribers, so an app that adds charts while it runs shows them in the panel right away instead of after their first run.
The host sends three new messages,
anfra:highlight,anfra:locateandanfra:pick-watch, and the frame sendsanfra:pickedback.MountedDataAppgainshighlight,locate,setPickingand anonPickcallback.The frame draws one overlay over the marked element: a tinted box and a label with the kind, the id or name in bold, the author's label, a note such as "1 of 3" when the entity is drawn in several places, and the size.
query.locate()andcontrol.locate()find their marked elements and flash the same overlay. Hidden elements get the overlay whenever they have a box, which is what devtools does.appserve
The inspect panel has two tabs. Structure has a toolbar with Pick and Copy handle, the tree under it, and a detail pane for the selected node with its handle and a copy button on that row. Pick ends on a click on the page, on Escape, or on a click in the tree, and clears the overlay. Copy handle gives something like
[Revenue over time](data-anfra-block="trend"). Data has the cards from before; each one says in how many places and which blocks its entity is drawn, and has a Locate button.Checks
make checkandmake testpass. New SDK tests cover parsing, the tree and its problems, usage, the overlay, pick mode and declaring. I tried it by hand in appserve on three Data Apps: hover, locate, pick, copy, the Data tab, elements added after load, and an app's own locate button.Left for later: reading the structure from the file without running it, exposing it to author code, and doing anything special for hidden content.
🤖 Generated with Claude Code