Skip to content

feat(preprod): Fix snapshot tag filtering and make tags interactive#116330

Merged
mtopo27 merged 9 commits into
masterfrom
feat/preprod-snapshot-tag-filtering
May 28, 2026
Merged

feat(preprod): Fix snapshot tag filtering and make tags interactive#116330
mtopo27 merged 9 commits into
masterfrom
feat/preprod-snapshot-tag-filtering

Conversation

@mtopo27
Copy link
Copy Markdown
Contributor

@mtopo27 mtopo27 commented May 27, 2026

Tag filtering previously operated at the group level — if any image in a group matched a tag, the entire group (with all its images) was included. This meant filtering by a tag showed unrelated images, counts didn't update, and the sidebar table of contents was inconsistent with search behavior.

Tag filtering now narrows individual images within groups (matching how search already works), counts update dynamically, and tags in the main content area are clickable.

Image-level narrowing

narrowItemByTags replaces the old boolean itemMatchesTagFilters and returns a new SidebarItem with only matching images/pairs kept, mirroring the existing narrowItemBySearch pattern. A new tagFilteredItems memo sits between searchFilteredItems and filteredItems in the derivation chain, so status pill counts and sidebar group counts all reflect the narrowed set.

Cross-key dynamic tag counts

availableTags now recomputes with cross-key awareness: selecting theme=dark updates counts for other tag keys (like area) to reflect only images matching theme=dark, while the theme key's own values retain full counts so users can toggle between them. Tags that reach count 0 render as disabled chips.

Sidebar overflow and clickable tags

The tag filter section's content area is capped at 200px with scroll to prevent it from pushing the table of contents off-screen. Tags rendered on image cards in the main content area (CollapsibleBadgeRow) now accept an onTagClick callback, rendering as styled buttons with hover state that toggle the corresponding sidebar filter.

Tag filtering now narrows individual images within groups instead of
including/excluding entire groups, matching the behavior of search
filtering. Tag counts update dynamically with cross-key awareness, status
pill counts respect active tag filters, the tag section scrolls when it
has many entries, and tags in the main content area are clickable to
toggle filters.
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label May 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

📊 Type Coverage Diff

Metric Before After Delta
Coverage 93.59% 93.59% ±0%
Typed 133,015 133,110 🟢 +95
Untyped 9,115 9,121 🔴 +6
🔍 3 new type safety issues introduced

Non-null assertions (!) (3 new)

File Line Detail
static/app/views/preprod/snapshots/sidebar/snapshotSidebarContent.tsx 372 availableTags.get(tagKey)!
static/app/views/preprod/snapshots/snapshots.tsx 401 images[j]!
static/app/views/preprod/snapshots/snapshots.tsx 406 searchKeys[j]!

This is informational only and does not block the PR.

Fix tag filtering to use single-select per key with AND semantics across
keys. Remove cross-filter skip so same-key counts reflect the full
filter state. Thread activeTagFilters to card badges so active tags
are visually highlighted on snapshot cards.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tag filters are single-select per key since each image can only have
one value per tag key. Replace Record<string, Set<string>> with
Record<string, string> to match the actual data model, simplifying
the toggle handler, filter checks, and prop types across 7 files.

Extract imageMatchesTagFilters and narrowItemByTags into a dedicated
tagFiltering module with unit tests covering matching, partial
matches, null tags, and pair-based items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract shared TagChip to its own module and reuse it in both
the sidebar tag filter section and the collapsible badge row.
Remove redundant ActiveTagChip (replaced by TagChip with isActive).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mtopo27 mtopo27 marked this pull request as ready for review May 27, 2026 21:24
@mtopo27 mtopo27 requested a review from a team as a code owner May 27, 2026 21:24
Comment thread static/app/views/preprod/snapshots/snapshots.tsx Outdated
mtopo27 and others added 2 commits May 28, 2026 09:25
Introduce TagFilterContext to provide activeTagFilters and
onToggleTagFilter to leaf components directly. This removes ~70 lines
of pass-through prop declarations across 6 intermediate layers
(SnapshotMainContent, SnapshotListView, GroupContainer, PairCard,
ImageCard, CardHeader) that never used the values themselves.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compute availableTags from all sidebar items rather than the already-
filtered set so tag chips remain visible when search or status filters
narrow results. Tags with zero matches render as disabled chips instead
of disappearing. Also hoists the passesFilters check out of the inner
tag loop since it depends only on the image, not the individual tag.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
mtopo27 and others added 2 commits May 28, 2026 10:03
The search filter check in the availableTags memo was running once per
image, but it only depends on item-level data. Move it above the image
loop so it runs once per item.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…erSection

useTagFilters() returns nullable, so destructuring with ! would crash
with no useful message if rendered outside TagFilterProvider. Early
return null instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ec526d5. Configure here.

Comment thread static/app/views/preprod/snapshots/snapshots.tsx Outdated
availableTags was checking search at the group level via narrowItemBySearch,
then counting tags from all images in the group. searchFilteredItems narrows
groups to only individually matching images. This mismatch inflated tag chip
counts when a search partially matched a group.

Check search per-image using the pre-computed memberSearchKeys index instead.
This also replaces the narrowItemBySearch call with a direct string.includes,
which avoids allocating narrowed item copies.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
@mtopo27 mtopo27 merged commit 60b7da7 into master May 28, 2026
76 checks passed
@mtopo27 mtopo27 deleted the feat/preprod-snapshot-tag-filtering branch May 28, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants