[RFC] PowerSearch: suggest complete filters from the main input
- Dominant language
- TypeScript
- Stars
- 13.1k
- Forks
- 1.1k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 687
Description
## Problem Statement
PowerSearch builds a filter in three parts:
1. **Field:** what to search, such as Author or Status.
2. **Operator:** how to compare it, such as is, is not, or contains.
3. **Value:** what to search for, such as a person, a status, or some text.
Astryx can suggest fields and operators in the main input. It can also build some complete filters from free text and static enum values. However, it does not search an operator's value source from the main input.
For example, if Author has a people search source, typing a person's name does not suggest a complete filter such as:
```text
Author is Alex Smith
```
The user must first find Author, choose an operator, and then search for the person in a second menu. This is harder for users who know the value they want but do not know which field contains it.
The desired experience is one main search that can suggest:
- a field;
- a field with an operator;
- a complete field, operator, and value filter.
Empty-input browsing should stay simple: show every available field, with optional field groups. Blended value search should start only after the user types.
## Evidence of Demand
A mature production predecessor in this component family already blends field, operator, and value results in the main input. Existing users can type a value and select a complete filter in one step. Replacing that component with Astryx should not remove this workflow.
Common examples include:
- typing a person's name and getting `Author is [person]`;
- typing a status value and getting `Status is [status]`;
- typing `title bug` and getting `Title contains "bug"`;
- typing a field name and getting both the field and its matching field/operator choices.
The current public PowerSearch story demonstrates the staged Astryx behavior: search-backed values are available only after choosing a field and operator.
https://facebook.github.io/astryx/storybook/?path=/story/core-powersearch--full-featured
This is a general filter-building pattern. It is not tied to one product or one kind of value source.
## Why Existing Components Don't Cover This
An operator can already provide a `searchSource`. PowerSearch uses it in the value picker after the field and operator are selected.
There is no supported way to include that same source in the main PowerSearch results. A consumer would have to build a second search system outside PowerSearch and duplicate:
- query parsing;
- field and operator matching;
- result ranking;
- duplicate removal;
- keyboard navigation;
- active-option state;
- screen-reader announcements;
- filter creation.
A custom search source can control one operator's values, but it cannot add complete filter suggestions to the main input by composition alone.
## Rough Approaches Considered
These are starting points for the specification work. They are not final API decisions.
### A. Blend eligible value sources inside PowerSearch
Extend the main search so it can combine:
- field suggestions;
- field/operator suggestions;
- local string and enum filter suggestions;
- results from eligible operator value sources;
- content-search suggestions when configured.
Each value-source result would become one complete filter suggestion. PowerSearch would combine the lists, remove duplicates, sort them, and apply the final limit.
A small per-source result budget may be needed so one field does not fill the whole list.
This is the closest match to the established behavior and keeps parsing, ranking, and accessibility inside PowerSearch.
### B. Add a public extension point for main-search sources
PowerSearch could accept extra sources that return complete filter suggestions.
This is more flexible, but it makes every consumer responsible for result shape, ranking, duplicate handling, and interaction with built-in sources. It may be useful later, but it does not provide parity by itself.
### C. Keep value search only in the second menu
This keeps the current implementation small, but it keeps the migration gap and makes value-first searches take more steps.
### Behavior to settle in the specification
- Which value sources are eligible for main-input search?
- When may a value match without a field-name match?
- How are fields, field/operator suggestions, and complete filters ranked together?
- How many results may one field/operator source contribute?
- How do we cancel stale async searches when the query changes?
- Should each field or operator be able to opt out of value matching?
- How should the typed-result limit apply to the final blended list?
The final public prop names should be decided after the behavior is agreed. This RFC does not propose a rename.
## API Naming Research
The parity work also changes what the two result limits mean. We should include the rename in the same specification so it is not lost.
Current problems:
- `maxOperatorMenuItems` does not limit the operator menu. It limits search-backed value suggestions. In blinded name tests, readers repeatedly assumed it meant the operator menu.
- The established predecessor also has a separate enum-list limit. Usage evidence shows that separate override is rare and is mainly used to escape a hidden 100-option cap.
- The main typed-result list will contain fields, field/operator suggestions, and complete filters after this RFC. A field-only name would become too narrow.
We ran two rounds of naming research:
1. An open-ended round described the field, operator, and value stages without giving candidate names.
2. A fresh blind round tested the names that emerged.
The value-side names converged on `maxValueOptions` or `valueOptionsLimit`. The main-list name did not converge. Leading ideas included `maxRankedMatches`, `fieldSearchLimit`, and `maxFilterSuggestions`. Each has a tradeoff: `ranked` is jargon, `field` may be too narrow, and `filter suggestions` needs a clear definition.
The specification should decide:
- the final name for the typed blended-result limit;
- a clear replacement for `maxOperatorMenuItems`;
- whether one value-option limit should cover search-backed values, enums, and enum lists;
- whether source-specific limits remain the per-operator override;
- how a codemod handles old names and conflicting value limits.
No final names are proposed in this RFC yet. The naming decision should follow the agreed behavior and another blind comprehension test.
## Accessibility Considerations
The main results remain one listbox, even when results come from several sources.
- Arrow keys should move through one flat option order.
- `aria-activedescendant` should always point to the active option.
- Every complete-filter suggestion should have a clear accessible name that includes its field, operator, and value.
- Async results should not reset focus or move the active option without user input.
- Loading and result-count changes should be announced without repeating every option.
- Selecting one complete suggestion should add one filter and return focus to the main input.
- Empty-query field groups should remain accessible named groups. Typed blended results should remain flat unless grouping has a clear user benefit.
## Performance Considerations
PowerSearch should not call every value source on every keystroke.
The specification should define a clear rule for which sources to call, how long to wait after typing, and how to ignore old requests. Each source should return only a small number of suggestions. The final typed list should also keep an overall limit.
Empty-query browsing should not make network requests. It should continue to use the configured field list.
Because the rendered result list is capped, this proposal should not require virtualization. Large value domains remain the responsibility of their search sources.
## Pre-submission Checklist
- [x] I have read the [Contributing guide](https://github.com/facebook/astryx/wiki/Contributing)
- [x] I have read the [API Conventions](https://github.com/facebook/astryx/wiki/API-Conventions)
- [x] I have checked that existing Astryx components cannot compose to solve this
- [x] This is a general-purpose UI pattern (not specific to one product)
Contributor guide
Assessment
This issue has not been assessed yet.