Skip to content

refactor(landing): share the search submit and suggestion logic between ServiceSearch and the homepage hero (#3686) - #3715

Merged
TaigaTi merged 2 commits into
mainfrom
refactor/landing-service-search-hook-3686
Nov 13, 2026
Merged

TaigaTi merged 2 commits into
mainfrom
refactor/landing-service-search-hook-3686

Conversation

@TaigaTi

@TaigaTi TaigaTi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Closes #3686

The homepage hero repeated ServiceSearch's search logic almost line for line, so there were two copies of the search-submit and search-suggestion-select payloads that could drift. Both now use one hook, useServiceSearch, in apps/landing/src/components/. It works out the suggestions, sends both events and navigates. The one real difference stays an option on the hook: the homepage passes emptyTo: '/services', so an empty search there still goes to the services list, and ServiceSearch's still goes to the results page.

The hook takes one options object rather than the (source, viewer, overlay, { emptyTo }) shape suggested in review. Each component keeps its own field text and passes it in (text, setText, suggesting), because the hero's text is shared with the Ask field and its suggestions only show in Search mode. Moving that state into the hook would have pulled Ask mode in with it. Both components' field markup is unchanged.

How it was checked

  • No behaviour change: HomeHero.test.tsx and ServiceSearch.test.tsx pass unchanged, and between them they cover both empty-search destinations and the full payload of both events for home, services and results. To make sure they'd catch a slip in the hook, I briefly broke the empty-search option and the suggestion position: four tests failed, two in each file. No separate hook tests, since they'd only repeat these.
  • Landing: full test suite (843 tests), typecheck and lint pass.

Not in this PR

Tracking the hero's Popular searches links is #3683, which can now use the hook's submit.

🤖 Generated with Claude Code

…eServiceSearch (#3686)

The homepage hero repeated ServiceSearch's search-submit and
search-suggestion-select tracking almost line for line, so the two
payloads could drift. Both now use one hook. The hero's empty search
still goes to /services, as an option on the hook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amazon-inspector-n-virginia

Copy link
Copy Markdown

⏳ I'm reviewing this pull request for security vulnerabilities and code quality issues. I'll provide an update when I'm done

@amazon-inspector-n-virginia

Copy link
Copy Markdown

✅ I finished the code review, and didn't find any security or code quality issues.

@github-actions

github-actions Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Amplify PR previews

App Status URL
forms ⏭ Not affected —
landing ✅ Ready https://refactor-landing-service-search-hook-3686.d3kbl8o0ovutw4.amplifyapp.com
chat ⏭ Not affected —
form-builder ⏭ Not affected —
analytics ⏭ Not affected —

Commit: 59f98a1 · Branches auto-delete when this PR closes.

ℹ️ feature-flagging uses a single shared preview slot at a fixed URL (preview.feature-flagging.sandbox.alpha.gov.bb) — GitHub login works, but only one FF preview exists at a time (the most recent FF PR build wins). It reads/writes sandbox flag data.

@IsaiahSama IsaiahSama left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. I found nothing that blocks this.

I checked the hook against both removed copies:

  • submit: search-submit sends { query, source } with the trimmed query. An empty search goes to /services only when emptyTo is set, which only HomeHero passes. ServiceSearch still sends an empty search to /search-results?q=, as it did at base.
  • onSuggestionSelect: query is read from the typed text before setText(hit.title), which matches both originals. position is index + 1, then it calls submit(hit.title). hits is worked out in the same render as before, so the index lines up with the suggestions the user sees.
  • HomeHero still gets suggestions only in Search mode after typing (suggesting: mode === 'search' && hasTyped). SOURCE is still 'home'.

On #3686: there is now one copy of both payloads, the homepage passes emptyTo: '/services', and the hook sits next to ServiceSearch. The options object differs from the signature the issue suggested. The description explains why: the text state stays with each component because the hero shares it with Ask mode. That holds. Neither test file is changed in the diff.

CI: all checks pass, including Build, Type Check, Lint and Test. The PR is mergeable.

Non-blocking nit, take it or leave it: ServiceSearch now writes 'services' | 'results' out in its props, while the hook has its own SearchSource union. If the hook exported SearchSource, ServiceSearch could use Exclude<SearchSource, 'home'> and the list of sources would live in one place.

@TaigaTi
TaigaTi requested a review from IsaiahSama November 13, 2026 15:50
…ce (#3686)

Export SearchSource from useServiceSearch and type ServiceSearch's source
prop as Exclude<SearchSource, 'home'>, so the list of sources lives in one
place. Type-only, no behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TaigaTi

TaigaTi commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

Done in 59f98a1. The hook now exports SearchSource, and ServiceSearch's source prop is Exclude<SearchSource, 'home'>, so the list of sources lives in one place. It's a type-only change.

@TaigaTi
TaigaTi merged commit 7b5b526 into main Nov 13, 2026
28 checks passed
@TaigaTi
TaigaTi deleted the refactor/landing-service-search-hook-3686 branch November 13, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Landing: share the search submit and suggestion logic between ServiceSearch and the homepage hero

2 participants