What the Behaviors drawer does
The Behaviors drawer lets non-coders wire up interaction without writing JavaScript by hand. Each "behavior" is an (element, event, action) rule — "when this happens on that element, do this". The drawer serialises your list of behaviors as JSON inside a fenced block at the bottom of the playground's JS file, then regenerates a single delegated event handler for the whole list. Your hand-written JS above the fence is left untouched.
Opening it
Click the Behaviors icon in the left rail of the editor. The canvas shrinks to make room. Only one left drawer (Style, Behaviors, or AI assistant) can be open at a time.
Adding a behavior
- Click Add behavior (or tap an element in the preview while the drawer is open — the source-element field pre-fills with its selector).
- Pick the event the rule should fire on (see the list below).
- Pick an action from the action menu and fill in its fields (target element, value, etc.).
Supported events
- Click / Double-click
- Submit (form)
- Type / change value (
input) - Change
- Focus / Blur (handled via
focusin/focusoutso a single delegated handler suffices) - Hover / Hover out (
mouseover/mouseoutfor the same reason) - Key released (
keyup)
Supported actions
- Show element — sets the target's display so it becomes visible.
- Hide element — sets the target's display to
none. - Toggle CSS class — adds / removes a class on the target.
- Set text — replaces the target's text content with a literal string.
- Navigate to URL — navigates the top-level page.
- Show value from a sheet — reads a column from a Data Sheet (first row, last row, or row count) and writes that value into the target element's text. Lets non-coders surface sheet data without writing
flowfn.data.get(...)by hand. - Call a function — calls a named function you've defined in your hand-written JS above the fence. The drawer auto-detects function names in your source and lists them in the picker.
- Run custom JS — drops to a short code field for cases the structured actions don't cover. Use sparingly; for anything non-trivial, write a regular function and use Call a function.
The managed block
On save, the drawer rewrites a single fenced block at the bottom of your JS file:
// ff-behaviors:start — managed by the Behaviors drawer (don't hand-edit this block)
// ff-behaviors-data: {"behaviors":[…]}
document.addEventListener('click', function(e) { … });
// ff-behaviors:end
Don't hand-edit inside the fence — the drawer regenerates it every save and your changes will be lost. Hand-written JS belongs above the fence. The drawer reads its data exclusively from the ff-behaviors-data sidecar comment, so a roundtrip (read → edit → write) always preserves intent.
Interaction with Inspect
While the Behaviors drawer is open, the element you tap in the preview is highlighted as the active source element. Tapping a different element re-points the drawer's "Add behavior" form at it. Closing the drawer drops the highlight.
Tips
- For anything that needs to fire on more than one event or chain multiple actions, write a small function in your JS and wire it with the Call a function action.
- If a behavior stops firing after a DOM change, check that the source-element selector still matches — selectors are resolved at event time against the current DOM, so adding wrapper elements above the target is fine but renaming the target's
idisn't. - The drawer's events all delegate from
document, so adding new matching elements at runtime (e.g. viainnerHTMLor your sheet renderer) just works without rewiring.