feat: autofocus prop for the embedded chat composer - #95
Merged
Merged
Conversation
Lets a host land the user in the composer — e.g. a freshly created project that opens the tangent page and starts a session — without a click. The textarea is disabled until the socket joins and the roster arrives, so DOM autofocus would land on a disabled field; this waits for the composer to accept input and focuses once per mounted session. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Description
Adds an
autoFocusprop to the embedded chat so a host can land the user in the composer on load. The motivating flow is tangle-ui's new-project page (stack leading up to TangleML/tangle-ui#2762): it opens the tangent page, creates a session, and wants the cursor already in the box so the user can type immediately.The composer's textarea is
disableduntil the socket joins and the agent roster arrives, so a plain DOMautofocuswould land on a disabled field and do nothing. Instead the prop waits for the composer to accept input, then focuses once per mounted session — no refocus on reconnect, on a run finishing, or after the user clicks elsewhere in the host page. Focus usespreventScroll: trueso the host page never jumps.Threaded through all three layers of the contract:
<Chat autoFocus>in@tangent/embed-react, assigned as an element property beforesessionIdso the first render already knows.autoFocusproperty +auto-focusattribute on<tangent-chat>for raw-element hosts.ComposerShellowns the focus effect;ChatInput/SubagentTabViewpass it through, so it also works whenagentIdtargets a sub-agent thread rather than being silently ignored.No server change was needed for the "start a session, say nothing" half of the flow —
newSession("", bundleId)already queues an empty prompt that is never sent.Screenshots
N/A — no visual change; the only difference is where focus sits on load.
How to test
pnpm devautoFocus, behaviour is unchanged (nothing takes focus).Notes
@tangent/embed-reactto get the typed prop (currently0.1.1— happy to bump in this PR or a follow-up). Not strictly required: a host can setelement.autoFocus = true/ theauto-focusattribute and pick up the behaviour from the runtime bundle alone.pnpm validate+build:embed+ the wrapper's.d.ts. This repo has no embed harness page (onlypublic/bundle-ui-harness, which is for bundle UI), so the focus path has not been exercised in a browser here — it will be on the tangle-ui side.focusComposer()method: refocusing after mount is more annoying than useful. Easy to add later if a host surface needs it.🤖 Generated with Claude Code