Add a search input to the default vendor pages for company card exports, and fix the empty search result

Open
#105,938 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@heyjennahay is already working on this.

Since Nov 5, 2026.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
67/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
frontend, payments

Research direction

Start by locating the six default vendor pages and compare the existing Rillet search with the four pages that lack one. Reuse Rillet’s search and filtering behavior, then check the selection lists’ existing empty state. Done when all six pages filter vendor names as specified, preserve selection and row order, and show “No results found” when nothing matches.

Written by the indexing model from the issue text.

Description

Improvement Weekly
Background

When an admin connects an accounting integration, they can choose a default vendor for company card expenses that don't match a vendor automatically. This opens a vendor page in the RHP, which lists every vendor synced from the integration, with a radio button on each row.

The vendor list can reach hundreds of vendors. Xero and Rillet show a search input at the top of this page as intended. DualEntry, Dynamics 365 Business Central, QuickBooks Online, and Sage Intacct don't, so an admin has to scroll and scan each row to find one vendor.

The Xero and Rillet search also has a bug. When the search text matches no vendor, we show the None row instead of No results found.

Image

This issue adds the search input to the four pages without it, and fixes the empty search result on all six pages.

Change summary
  • Add a search input at the top of the default vendor page for DualEntry, Dynamics 365 Business Central, QuickBooks Online, and Sage Intacct, matching the Rillet page.
  • Filter the list by vendor name as the admin types.
  • Show No results found on all six pages when no vendor matches, including Xero and Rillet.
  • No change to which vendors we list, how we sync them, the order of the rows, or what the default vendor does on export. This changes how admins find a vendor only.
Product and design details
Image
Where this applies
Integration Location Change
Xero Export > Default vendor Fix the empty search result
Rillet Export > Default company card vendor Fix the empty search result
DualEntry Export > Default vendor for all company cards Add the search input
Dynamics 365 Business Central Export > Default company card vendor Add the search input
Sage Intacct Export > Export company card expenses as > Default vendor Add the search input
QuickBooks Online Export > Export company card expenses as > Default vendor Add the search input

All locations are under Workspaces > Connections > the integration. We don't change any page title or supporting copy.

Search input
  • We add the search input below the supporting copy and above the first row, in the same position as the Rillet page.
  • Placeholder copy: Search.
  • The input stays pinned above the list while the list scrolls.
  • We always show the input, regardless of how many vendors are available, so the page behaves the same for every workspace.
  • We reuse the search input and filtering that the Rillet page already uses. No new component.
  • The input is focused when the page opens, as it is on the Rillet page.
Filtering
  • The list filters as the admin types, with no submit step.
  • We match on the vendor name as shown in the list, case-insensitive, anywhere in the name. For example, amazon matches Amazon Business and Amazon Web Services.
  • We filter the vendors we already loaded from the last sync. Searching doesn't send a new request to the integration.
  • Matching rows keep their current order on each page.
  • The None row follows the same rule as every other row. It shows only when its name matches the search text.
  • Clearing the input restores the full list, including the None row.
Selection while filtering
  • Selecting a row while a search is active works the same as it does without a search.
  • The currently selected vendor keeps its selected state while the search hides it. It shows as selected again when it matches or when the admin clears the input.
No results
Image
  • When no row matches the search text, we replace the list with No results found, matching our other selection lists.
  • We don't show the None row in this state. Today, Xero and Rillet show None here.
Mobile
  • The same input and behavior apply on mobile.
Dominant language
TypeScript
Stars
5k
Forks
4k
Avg merge
3d 5h
Merged PRs (30d)
594

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Expensify/App

All issues in Expensify/App

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.