You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Route suggestion chips, Spotlight, trending prompts, Mac recommendations, and prompt history through one prompt-seeding path.
Reveal and focus the composer after seeding, place the caret at the end, and never auto-submit.
Preserve history-trigger focus restoration when the popover is dismissed without a selection.
Why
ENG-612 / #638: under the active evolve-prompt-suggestions multivariate feature flag, the trending variant can leave the composer off-screen while suggestion rows remain clickable. Previously those clicks only updated Zustand state, so they could look inert. Mac recommendations and prompt history also bypassed the shared helper.
This supersedes closed draft #641. The filesystem “edit with prompt” action navigates from another screen and is intentionally outside this in-place suggestion flow.
bun -F native test:unit — 347 tests passed across 51 files
bunx tsc --noEmit -p apps/native/tsconfig.json
bunx oxlint on all four changed files — 0 warnings/errors
bunx oxfmt --check on all four changed files
bun -F native build
Real WKWebView smoke: an off-screen Mac recommendation revealed and focused the composer with the caret at the end and no submit; history selection retained composer focus; Escape restored trigger focus
Storybook reports the same five existing Evolve snapshot deltas as fix(promptinput): remove dead trending browse CTA #660; its check passes. No baselines were accepted because this change does not alter those stories.
These stories' HTML snapshots changed. I've added screenshots + links to the changed stories below. Review them carefully then accept the changes to regenerate baselines and include them in this PR:
Alternatively, you can run bun run test:update-snapshots locally to re-generate the baselines and then push the changes to this PR.
What does this do?
The screenshots above show UI changes detected by the Storybook
snapshot tests run on this PR. Each image is the rendered output of
a Storybook story from the code in this PR branch; the snapshot
test compared it against the committed baseline in __snapshots__/ and flagged the difference.
Checking the box tells the darkmatter[bot] to regenerate the
baselines from this PR's current code and commit them directly to
this branch. The new baselines become the source of truth for
future runs — only accept after confirming the visual changes are
intentional.
Comparison baseline: the committed __snapshots__/ files on this
PR branch (carried forward from develop). Accept updates them in
place on this branch.
Prompt suggestions reveal and focus the composer before user submits
Product decisions in this change
1. All prompt suggestion surfaces share one seeding path, so the composer always reveals, receives focus, and positions the caret after any suggestion is selected.
Before this change, each surface called the global state action directly and stopped there. This meant a suggestion click on an off-screen composer updated state silently, with no visible feedback. A shared path ensures the user always knows their selection was received. The pattern is also correct for long-term maintenance: when seeding behavior needs to change again, one function controls all surfaces.
2. Selecting a suggestion seeds the composer but never submits the evolution, so users can review or edit before the agent starts.
In this product, an evolution edits system configuration. Auto-submit would start that process the moment a user taps a chip. The cost of an accidental evolution is high enough (time, build cycle, possible rollback) that requiring an explicit submit step is clearly right. The seeded text is a starting point, not a confirmed command.
3. After seeding, the caret lands at the end of the seeded text, not at the start.
Suggestions in this product are complete prompt sentences, not prefixes. A user who wants to refine the prompt is more likely to append context ("... but only for my user account") than to insert at the beginning. End placement also signals that the text is ready to submit as-is. This would need revisiting if the product adds partial-phrase chips designed to be completed.
4. The history popover returns focus to its trigger button when the user dismisses without selecting, and moves focus to the composer when the user does select.
This is the standard ARIA pattern for popovers. Focus returning to the element that opened the popover on Escape is what keyboard users expect. Redirecting focus to the composer after selection is correct because the next intended action is to review or submit the seeded text, not to interact with the history button again. The ref-based gate that distinguishes the two cases is the right mechanism.
5. Smooth scroll is replaced with instant scroll when the user's OS reports a preference for reduced motion.
This is a required accessibility behavior. The implementation reads the media query at call time inside the rAF callback, which means it picks up the live preference rather than a stale capture at component mount. The test that stubs matchMedia confirms the branch is exercised.
6. MacRecommendationChip and PromptHistoryBadge no longer own their seeding behavior and receive it as a callback from the parent composer.
These chips previously called a global action directly. That made seeding behavior impossible to extend from the parent and harder to test. Accepting a callback makes the parent the single source of truth for what "select a suggestion" means. The components remain simple presenters. The only cost is that they cannot be dropped into a new context without a parent that provides the callback, but that is not a realistic concern here since they are prompt-input-specific UI.
7. The "edit with prompt" filesystem action is intentionally excluded from this seeding unification.
The PR description gives a clear reason: that action navigates from another screen rather than operating in-place. The mechanics are genuinely different. However, users do not see those mechanics. A user who selects a filesystem file and picks "edit with prompt" has the same mental model as a user who picks a chip: they want the composer to be ready with their intent. If the filesystem path delivers a different focus or reveal experience, it will feel inconsistent. The current exclusion is defensible as a scoping decision, but the gap should be closed in a follow-up.
Open questions
Does the "edit with prompt" filesystem action currently reveal and focus the composer after navigating? If not, does the team plan to align it with the behavior introduced here?
Are there any suggestion surfaces not visible in this diff (for example, the Spotlight variant or the trending variant) that still call the global state action directly and bypass the shared seeding path?
When the composer is disabled because processing is already active, suggestion surfaces are presumably not shown. Is that suppression consistent across all surfaces, or can a user reach a chip while processing is running?
Recommendation
Ship it
Every decision in the PR is sound and consistent with good UX practice. The change fixes a real gap where suggestion clicks could appear inert, adds tests that cover the new behavior across every affected surface, and respects accessibility preferences. The one concern (filesystem action exclusion) is a known gap the team has already scoped out, not a regression introduced here.
Thanks — I checked each open question against the current branch:
Filesystem action: “Edit with a prompt” stores the seed and closes the Filesystem view. It does not use the shared seedPrompt path, focus the textarea, or scroll it into view. That remains a separate cross-screen path outside ENG-612; this PR covers the in-place suggestion controls.
Suggestion coverage: Spotlight, Trending (row selection and “Use”), starter chips, Mac recommendations, and prompt history all call the shared seedPrompt. The filesystem transition is the only production non-empty prompt writer outside PromptInput.
Processing state: During normal evolve, the overlay covers the controls and the textarea and history control are disabled. Rebuild also uses a full-content overlay. Some apply actions run from Begin, but the composer remains enabled, so suggestion seeding still reveals and focuses it normally. There is a brief cancellation wind-down where suggestions can be selected while the textarea remains disabled; on the cancellation path, the selected text is retained when processing clears and is not auto-submitted.
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
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.
Summary
Why
ENG-612 / #638: under the active
evolve-prompt-suggestionsmultivariate feature flag, thetrendingvariant can leave the composer off-screen while suggestion rows remain clickable. Previously those clicks only updated Zustand state, so they could look inert. Mac recommendations and prompt history also bypassed the shared helper.This supersedes closed draft #641. The filesystem “edit with prompt” action navigates from another screen and is intentionally outside this in-place suggestion flow.
Fixes #638
Test Plan
bun -F native test:unit— 347 tests passed across 51 filesbunx tsc --noEmit -p apps/native/tsconfig.jsonbunx oxlinton all four changed files — 0 warnings/errorsbunx oxfmt --checkon all four changed filesbun -F native buildgit diff --checkKnown repository baselines
.agent/skills/nixmac-dsMarkdown files, as it does on fix(promptinput): remove dead trending browse CTA #660. This PR's dedicated Treefmt check passes.Docs