Field Kit
The terminal claimed the click first
A custom click target sitting over a component that acts on press must claim the event at mousedown, or it always arrives after the default behavior has started.
What happened
On 2026-06-28, a directory affordance layered over a terminal emulator refused to open its menu, because the emulator started a text selection drag on mousedown before the handler bound to the later stage ever ran, and the first automated verification clicks landed too far right to trigger the affordance at all.
3 prompts, in order
- Find which stage claims the click A custom overlay or menu drawn over a terminal never opens on click.
- Claim the press on mousedown The timeline shows the underlying component acting before your handler.
- Prove it with tolerant clicks Automation clicks the fixed target and the menu still does not open.
1Find which stage claims the click
- Run it when
- A custom overlay or menu drawn over a terminal never opens on click.
- It asks you for
- The target's listeners, the exact event names bound, and the observed click sequence.
- You get back
- An ordered event timeline and the named stage where the interaction is lost.
- It refuses if
- The user cannot state which event name the current handler binds.
<stance> The click is spent before the custom handler sees it. Terminal emulators and rich text editors bind their own mousedown listener and begin a selection drag right there. A handler bound to click or mouseup runs second. Order decides this. Diagnose the order first, because a rebind is not a diagnosis. </stance> <inputs> Ask for each item and wait. Do not proceed on a missing answer. 1. The code for the custom click target, including every listener it binds. 2. The exact event name in each binding, copied from the source. 3. A generic description of the component underneath, and what it does with the mouse. 4. The observed sequence on a real click, step by step. 5. Whether text in the underlying component highlights during the failed click. </inputs> <method> 1. Build an ordered list of every listener that can see this click. Note the event name for each one. 2. Mark where the underlying component acts. A selection drag that starts on press puts that component first. 3. Compare that position with the custom handler's event name. A handler on click or mouseup runs after the drag begins. 4. Read the answer about highlighted text. Highlighting during a failed click confirms the component won the press. 5. Choose between two diagnoses. Either the handler never receives the event, or it receives it too late. 6. If no listener source is available, stop ranking guesses. Ask for the binding code instead. 7. State the stage where the interaction is lost in one sentence. Name the event that must be claimed earlier. </method> <deliver> - Event timeline, ordered, one line per listener. - The stage where the click is lost. - Which diagnosis the evidence supports, late or absent. - What remains unknown, and the exact input that would settle it. </deliver> <refuse> Do not propose a rebind before the timeline exists. Do not assume the underlying component listens on mousedown without source or observation. Do not accept "the click does not work" as evidence about ordering. If the user cannot supply the event names, stop. Say the timeline is incomplete and name the missing binding. Do not offer stopping propagation as a diagnosis. That changes behavior without explaining the order. </refuse>
2Claim the press on mousedown
- Run it when
- The timeline shows the underlying component acting before your handler.
- It asks you for
- The handler verbatim, the default behavior to stop, and nearby interactions to preserve.
- You get back
- A handler rebound to mousedown, with the cancellation it needs and nothing more.
- It refuses if
- The default behavior to be suppressed is not named exactly.
<stance> The press belongs to the underlying component today, and the repair takes it back. A component that starts selection on mousedown can only be beaten at mousedown. Blanket suppression breaks neighbouring interactions in the same region. Name the behavior you intend to stop. Then stop exactly that and nothing else. </stance> <inputs> Collect these before writing code. Wait on any that is missing. 1. The current handler, verbatim, with its binding. 2. The default behavior to prevent, named exactly, for example a text selection drag. 3. Other interactions in the same region that must keep working, such as selection by drag elsewhere. 4. Whether the custom target must also respond to keyboard activation. Treat item two as mandatory. Do not guess it from the component's reputation. </inputs> <method> 1. Rebind the target's primary action to mousedown. Keep the element's role and semantics unchanged. 2. Cancel the event's default action on the custom target only. Write one line explaining what that cancellation stops. 3. Decide whether propagation must also stop. Stop it only when the component's listener sits on an ancestor element. 4. Walk the interactions from item three. Say for each one whether the new binding leaves it intact. 5. Keep a keyboard path to the same action if item four requires it. Route both paths through one function. 6. If it is unclear whether the component listens on the element or a parent, instrument instead of guessing. Log the listener order and re-read step three. 7. Produce the change as a diff. List every behavior the diff suppresses. </method> <deliver> - The diff, minimal, with the new binding. - One line per suppressed behavior, and why it is suppressed. - Interactions checked, with pass or risk for each. - Anything the change cannot cover, stated plainly. </deliver> <refuse> Do not suppress defaults across the whole region to make one target work. Do not bind at a global or document level when the target is local. If the behavior to prevent is unnamed, stop and ask for it. If the component's listener location is unknown, say so before touching propagation. Do not claim the repair works. Verification belongs to the next step. </refuse>
3Prove it with tolerant clicks
- Run it when
- Automation clicks the fixed target and the menu still does not open.
- It asks you for
- The computed coordinate, the cell dimensions, the click API, and the success observable.
- You get back
- A candidate grid with pass or fail per point, plus a control result.
- It refuses if
- No control run against the old binding is available or attempted.
<stance> A probe that lands a cell too far right reports a working fix as broken. Computed coordinates drift from rendered ones through rounding and pixel ratio mapping. A single pixel point is a fragile contract with the renderer. Tolerance makes the probe honest. A pass still needs a control before it counts as proof. </stance> <inputs> Ask for each and wait. 1. The computed coordinate of the target, as the script derives it. 2. The cell or glyph dimensions in the rendered view. 3. The automation API used to click, and how it reports outcome. 4. The observable that proves the menu opened. 5. Whether a build with the old binding is still runnable for a control. </inputs> <method> 1. Treat the computed point as a center, not a contract. 2. Generate candidates in the immediately adjacent cells around that center. Ask for the cell size if item two is missing. 3. Click each candidate and record the observable from item four. Stop at the first point that opens the menu. 4. Report which offset succeeded. A win away from the center points at coordinate mapping, not at the handler. 5. If no candidate opens the menu, declare the repair unproven. Return to the event timeline rather than widening the search. 6. Run the same tolerant probe against the old binding. A menu that opens there means the probe is not testing the fix. 7. Confirm that no text selection appears during the successful press. Record that reading alongside the pass. </method> <deliver> - Candidate grid, with pass or fail per point. - The winning offset, stated in cells from the computed point. - Control result for the old binding. - Verdict: proven, unproven, or probe invalid. </deliver> <refuse> Do not report success from one point without the surrounding candidates. Do not expand beyond adjacent cells to force a pass. A hit several cells away indicates a mapping bug, and that needs its own report. Do not call the fix proven without the control run. If no control build exists, say the proof is partial. Name exactly what is missing. Do not infer the menu opened from the click API returning success. </refuse>
How you know it worked
Press and hold the mouse button on the affordance. The menu opens while the button is still down. No text in the terminal region highlights during that press. Rebind the handler to mouseup and the menu stays shut.