Skip to content

feat(keywords): add search intent filter to Keyword Research#76

Merged
bensenescu merged 1 commit into
every-app:mainfrom
mariazuheros:issue-67-intent-filter
Jul 13, 2026
Merged

feat(keywords): add search intent filter to Keyword Research#76
bensenescu merged 1 commit into
every-app:mainfrom
mariazuheros:issue-67-intent-filter

Conversation

@mariazuheros

@mariazuheros mariazuheros commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes #67.

What

Adds a multi-select intent filter (Informational, Commercial, Transactional, Navigational, Unknown) to the Keyword Research table, so users can isolate e.g. transactional terms instead of scanning the intent badges by hand.

Coverage (per the acceptance criteria)

  • Filter by one or more intents, including Transactional.
  • Intent participates in the active-filter count, persistence, and clear-all.
  • Sorting, pagination, save, and export use the filtered row set.
  • A clear empty state shows when no rows match (existing EmptyFilterResults, shared by both layouts).
  • Tests cover single and multiple intent selections.
  • Multi-select present on both the desktop and mobile layouts. Intent classification and URL params are unchanged.

Design

  • Selected intents are stored as a comma-separated string in a new intents field on KeywordFilterValues. This deliberately fits the existing all-strings filter shape: active-filter counting (Object.values(...).filter(v => v.trim() !== "")), the z.string() persistence schema, and clear-all all work with no special-casing. Reads/writes go through parseIntentFilter / toggleIntentFilter, which keep a canonical order and de-duplicate.
  • Because sorting, pagination, save, and export already derive from filteredRows, they respect the intent filter automatically — no changes needed there.
  • The persistence schema defaults intents to "", so filter blobs saved before this change still load instead of being discarded.

Tests

  • useKeywordFiltering.test.ts: single-intent, multiple-intent, intent + other filters (AND), invalid-token handling, and the parseIntentFilter / toggleIntentFilter helpers.
  • useLocalKeywordFilters.test.ts: persistence migration (a legacy blob with no intents key loads with intents: "" and keeps the user's other filters).

pnpm ci:check and the full pnpm test suite pass.

Notes

  • The intent labels are reused from IntentBadge (INTENT_LABELS) so the table and the filter stay in sync.
  • Renamed keywordResearchDesktopFilters.tsxkeywordResearchFilters.tsx, since the shared filter components (including the new one) are now imported by the mobile layout too.
  • I wasn't able to exercise the live UI end-to-end locally (Keyword Research needs a DataForSEO key), so the verification here is typecheck + unit tests. Happy to tweak the visual details (e.g. matching chip colors to the intent badge palette) if you'd prefer.

Greptile Summary

This PR adds a multi-select search intent filter to Keyword Research. The main changes are:

  • Shared intent labels between IntentBadge and the new filter UI.
  • New intents filter state with canonical parsing and toggling helpers.
  • Intent filtering applied to the existing filtered row set used by sorting, pagination, save, and export.
  • Persistence support for the new filter field with migration for older saved filter blobs.
  • Desktop and mobile filter UI updates plus unit tests for filtering and persistence.

Confidence Score: 5/5

Safe to merge with low risk.

The changes are focused on client-side filter state and UI, reuse the existing string-based filter model, and include tests for filtering and persistence migration.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex ran the requested verification and completed the contract validation, but local artifact references were not uploaded.

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
src/client/features/keywords/keywordResearchTypes.ts Adds intents to keyword filter state plus canonical parsing and toggling helpers for intent multi-select serialization.
src/client/features/keywords/hooks/useKeywordFiltering.ts Applies parsed intent selections during row filtering before existing numeric filters and sorting.
src/client/features/keywords/hooks/useLocalKeywordFilters.ts Extends persisted filter validation and reset handling to include the new intents string field.
src/client/features/keywords/page/keywordResearchFilters.tsx Renames the desktop filter module to shared filters and adds an accessible multi-select intent button group.
src/client/features/keywords/page/KeywordResearchDesktopResults.tsx Imports the shared filter components and adds the intent selector to the desktop filter panel.
src/client/features/keywords/page/KeywordResearchMobileResults.tsx Adds the shared intent selector to the mobile filter panel while retaining filtered export and pagination flows.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant FilterUI as Desktop/Mobile FilterIntentSelect
participant Form as filtersForm.values.intents
participant Parser as parseIntentFilter/toggleIntentFilter
participant Filtering as useKeywordFiltering
participant Results as Table/Pagination/Save/Export

User->>FilterUI: Click intent button
FilterUI->>Parser: toggleIntentFilter(current, intent)
Parser-->>Form: Canonical comma-separated intents
Form->>Filtering: Updated KeywordFilterValues
Filtering->>Parser: parseIntentFilter(intents)
Filtering-->>Results: filteredRows matching selected intents
Results-->>User: Updated rows, counts, pagination, save/export set
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant FilterUI as Desktop/Mobile FilterIntentSelect
participant Form as filtersForm.values.intents
participant Parser as parseIntentFilter/toggleIntentFilter
participant Filtering as useKeywordFiltering
participant Results as Table/Pagination/Save/Export

User->>FilterUI: Click intent button
FilterUI->>Parser: toggleIntentFilter(current, intent)
Parser-->>Form: Canonical comma-separated intents
Form->>Filtering: Updated KeywordFilterValues
Filtering->>Parser: parseIntentFilter(intents)
Filtering-->>Results: filteredRows matching selected intents
Results-->>User: Updated rows, counts, pagination, save/export set
Loading

Reviews (1): Last reviewed commit: "feat(keywords): add search intent filter..." | Re-trigger Greptile

Add a multi-select intent filter (Informational, Commercial,
Transactional, Navigational, Unknown) to the Keyword Research table on
both the desktop and mobile layouts (closes every-app#67).

Selected intents are stored as a comma-separated string in a new
`intents` filter field, so they fit the existing all-strings filter
shape and get active-filter counting, persistence, and clear-all for
free. Sorting, pagination, save, and export already derive from the
filtered row set, so they respect the intent filter automatically. The
persistence schema defaults `intents` to "" so filter blobs saved before
this change still load. Intent classification and URL params are
untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bensenescu

Copy link
Copy Markdown
Contributor

@greptileai

@bensenescu bensenescu merged commit 927e931 into every-app:main Jul 13, 2026
3 checks passed
@bensenescu

Copy link
Copy Markdown
Contributor

Hey maria, thanks for this!

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.

Add search intent filter to Keyword Research

2 participants