feat(search): editable filter pills#2455
Conversation
🦋 Changeset detectedLatest commit: 3467cf2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🟡 Tier 3 — StandardIntroduces new logic, modifies core functionality, or touches areas with non-trivial risk. Why this tier:
Review process: Full human review — logic, architecture, edge cases. Stats
|
Greptile SummaryThis PR adds in-place editing to active filter pills: clicking an included or excluded pill opens a Mantine
Confidence Score: 5/5This PR is safe to merge. Changes are well-scoped UI additions with no mutations to query execution paths beyond the new single-emission replaceFilterValue helper. All three mutation paths (polarity flip, value replace, one-click remove) route through well-tested hook methods. The new replaceFilterValue correctly performs a single Immer produce call so onFilterChange fires exactly once. The valueChartConfig stripping of where/filters is sound and directly tested. The chartConfig prop is required and the only real caller (DBSearchPage) was updated. Twenty-two unit tests plus hook-level tests cover the new behavior comprehensively. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant U as User
participant FP as FilterPill
participant AFP as ActiveFilterPills
participant SF as useSearchPageFilterState
participant GKV as useGetKeyValues
U->>FP: click pill (included/excluded)
FP->>FP: setOpened(true)
FP->>GKV: "fetch values (enabled=true, where='', filters=[])"
GKV-->>FP: valueOptions[]
alt Copy value
U->>FP: click Copy
FP->>FP: copyTextToClipboard(pill.value)
else Flip polarity
U->>FP: click Include / Exclude
FP->>AFP: onTogglePolarity()
AFP->>SF: "setFilterValue(field, rawValue, 'include'|'exclude')"
SF-->>AFP: filters updated
FP->>FP: setOpened(false)
else Replace value
U->>FP: select new value from Select
FP->>AFP: onReplaceValue(newValue)
AFP->>SF: replaceFilterValue(field, oldRaw, newValue, polarity)
SF-->>AFP: filters updated (single onFilterChange emission)
FP->>FP: setOpened(false)
else Remove (x button)
U->>FP: click x (stopPropagation)
FP->>AFP: onRemove()
AFP->>SF: setFilterValue / clearFilter
SF-->>AFP: filters updated
end
Reviews (3): Last reviewed commit: "chore: replace pre-existing em-dashes in..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 198 passed • 3 skipped • 1352s
Tests ran across 4 shards in parallel. |
Make the active filter pills under the search bar editable in place, reusing existing search primitives. Clicking an included or excluded pill opens a small action menu (the EventTag popover pattern) with: - Copy the value. - Flip the filter polarity (include vs exclude) in place via setFilterValue, with no remove and re-add. - Switch to a different value of the same field via a searchable value picker. Values come from the shared useGetKeyValues hook, fetched only while the menu is open and scoped to the field with where/filters cleared so the full value list shows. The swap goes through a new replaceFilterValue helper on useSearchPageFilterState so the query runs once and the polarity is preserved. The one-click remove (x) on each pill is unchanged. Range and not-applied pills keep their remove-only behavior. DBSearchPage passes the active source's filtersChartConfig to the pills for the value query. Implements HDX-4326. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
prose-lint flags these on any change to the file; converting to commas.
0993367 to
3467cf2
Compare
Make the active filter pills under the search bar editable in place. Clicking an included or excluded pill opens a small action menu to copy the value, flip the filter's polarity (include vs exclude), or switch to a different value of the same field, reusing the
EventTagpopover pattern and the actionsuseSearchPageFilterStatealready exposes.Implements HDX-4326. This is the full feature in one PR. It previously spanned this PR and #2457; I folded #2457 in here and closed it, since the pill menu and the value picker share the same component and hook and do not stand alone.
Summary
Popovermenu with three actions: copy the value, flip polarity (Excludeon an included pill,Includeon an excluded one), and a searchable value picker to switch the filter to another value of the same field.setFilterValue(field, value, 'include' | 'exclude'), so a value moves between included and excluded without a remove and re-add.replaceFilterValuehelper onuseSearchPageFilterState, which does it in one state update so the search query runs once. TwosetFilterValuecalls would each emitonFilterChangeand run the query twice for one action. Polarity is preserved across the swap.useGetKeyValueshook, fetched only while the menu is open (enabled: opened) and scoped to the field withwhere/filterscleared, so it lists all of the field's values (like the sidebar facet's "Show all values") rather than only the currently matching one.xon each pill) is unchanged. Range and not-applied pills keep their remove-only behavior.DBSearchPagepasses the active source'sfiltersChartConfigto the pills for the value query.Why
Today the only thing you can do to an active pill is remove it. Adjusting a filter, say flipping
ServiceName = checkouttoServiceName != checkoutor changing its value, means deleting the pill and rebuilding it from the sidebar. The menu reuses primitives that already ship in search, so it adds the affordance with no new state and no new design.Test plan
make ci-lint(eslint + tsc) on@hyperdx/appmake ci-unit:ActiveFilterPills.test.tsx+searchFilters.test.ts(80 tests) cover open-on-click, both polarity flips, copy, the value picker populating fromuseGetKeyValuesand selecting a value callingreplaceFilterValuewith the right args and polarity, the one-click remove not opening the menu, range pills not opening a menu, andreplaceFilterValueemittingonFilterChangeexactly once=and!=, copy, open the value picker and switch values) in light and dark themesNote
This lands as one
review/tier-3PR. It is one cohesive feature (the menu and the value picker shareActiveFilterPills.tsxanduseSearchPageFilterState), so I kept it together rather than as a stacked tier-2 pair. A separate commit also replaces six pre-existing em-dashes insearchFilters.tsxcomments with commas; that is unrelated to the feature but sits in a file this PR edits.