Skip to content

fix(explore): improve Policy Bills tab discoverability#185

Merged
William-Hill merged 3 commits into
mainfrom
fix/policy-tab-discoverability
Apr 13, 2026
Merged

fix(explore): improve Policy Bills tab discoverability#185
William-Hill merged 3 commits into
mainfrom
fix/policy-tab-discoverability

Conversation

@William-Hill

@William-Hill William-Hill commented Apr 13, 2026

Copy link
Copy Markdown
Owner

Summary

Policy Bills was surfaced as a top-level data source tab in #184, but it landed at position 12 in a horizontally-scrolling tab row — and on macOS the default invisible scrollbar gave no affordance that more tabs existed beyond the viewport. Users had to scroll blindly to find it.

  • Reorder: Moved Policy Bills to position 2 (right after Census ACS) so it's visible in the initial viewport on all reasonable widths.
  • Scroll affordance: Added left/right chevron buttons and edge fade gradients that appear only when the tab row overflows — solves the general overflow discoverability problem, not just Policy Bills.
  • Visual elevation: Added a pulsing accent dot to the inactive Policy Bills tab to signal that it's a categorically different data type (live legislative tracking) vs. the metric tabs.

Test plan

  • Load /explore at viewport widths where tabs overflow (~1024px and below): chevrons + edge fades appear
  • Load at wide viewport where all tabs fit: no chevrons, no fades
  • Click right chevron: tab row scrolls smoothly by one step
  • Scroll to end: right chevron and right fade disappear; left chevron and left fade appear
  • Policy Bills tab shows a pulsing green dot when any other tab is active
  • Selecting Policy Bills hides the dot (active state takes over)
  • Keyboard tab order still reaches every tab button in list order

Summary by CodeRabbit

  • New Features

    • Left/right arrow buttons and gradient indicators for horizontal tab scrolling.
    • Smooth programmatic scrolling with keyboard focus preservation and responsive overflow detection for better accessibility and layout behavior.
  • Chores

    • Reordered data source menu entries and added a new highlight flag to emphasize a specific data source in the menu.

- Move Policy Bills from position 12 to position 2 in DataSourceTabs
- Add scroll chevron buttons and edge fade gradients when tabs overflow
- Add pulsing accent dot to inactive Policy Bills tab to signal it as a
  headline feature distinct from the metric data tabs

Previously Policy Bills was buried at the end of a horizontally-scrolling
tab row with invisible macOS scrollbars, making it easy to miss.
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a4e4220e-8d32-4f78-b6cf-0ef58c868483

📥 Commits

Reviewing files that changed from the base of the PR and between c24ff72 and 7896c34.

📒 Files selected for processing (1)
  • ui-nextjs/components/explore/DataSourceTabs.tsx

📝 Walkthrough

Walkthrough

Reworks DataSourceTabs to conditionally render gradient overlays and chevron scroll buttons, add smooth programmatic horizontal scrolling, overflow-state tracking (scroll events + ResizeObserver), focus preservation, and per-item highlighting; adds optional highlight?: boolean to DataSourceConfig and moves the policy entry earlier in DATA_SOURCES.

Changes

Cohort / File(s) Summary
Tabs UX & Scrolling
ui-nextjs/components/explore/DataSourceTabs.tsx
Replaced always-present overflow container with a relative wrapper that conditionally shows left/right gradient overlays and chevrons. Added scrollerRef, scrollBy(delta) with smooth scrolling, tabIndex={-1} on scroller, focus preservation when buttons unmount, and selection/visuals still driven by activeKey.
Overflow Detection & Lifecycle
ui-nextjs/components/explore/DataSourceTabs.tsx
Introduced canScrollLeft/canScrollRight state and updateOverflow logic (using scrollLeft, clientWidth, scrollWidth), attached scroll listener, added ResizeObserver to recalc on layout changes, and cleaned up listeners/observer on unmount.
Config: Highlight Flag & Ordering
ui-nextjs/lib/explore-config.ts
Extended DataSourceConfig with optional highlight?: boolean. Moved key: "policy" earlier in DATA_SOURCES and set highlight: true on that entry; no other public signatures changed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main purpose of the PR: improving discoverability of the Policy Bills tab through reordering and enhanced scroll affordances.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/policy-tab-discoverability

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Apr 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR improves the discoverability of the Policy Bills tab in the /explore data-source tab row: it moves policy to position 2 in the config array, adds left/right chevron scroll buttons with edge-fade gradients that appear only when the tab row overflows its container, and adds a pulsing accent dot to the inactive Policy Bills tab to signal it as a live-tracking data source.

Key changes:

  • explore-config.ts: The policy array entry is relocated from index 11 to index 1 — no functional changes to the config object itself.
  • DataSourceTabs.tsx: The component gains useRef + ResizeObserver + scroll-event state tracking to drive conditional rendering of chevrons and gradients; cleanup is correct. A pulsing dot is rendered via aria-hidden spans when the Policy Bills tab is inactive.

One concrete accessibility concern: the chevron buttons are conditionally mounted/unmounted and, when keyboard focus sits on a chevron that then disappears (scroll reaches a boundary), focus reverts to document.body rather than staying in the tab row. The hardcoded 'policy' key string in the component also creates a silent coupling to the config that would be easy to break on a rename.

Confidence Score: 4/5

Safe to merge; the scroll-affordance implementation is solid and the config reorder is risk-free — one P1 keyboard focus-loss edge case should be addressed before or shortly after landing.

The core logic (ResizeObserver pattern, scroll-state tracking, cleanup, conditional rendering) is correct and well-structured. The config change is a pure reorder with no behavioral impact. The only P1 is a focus-loss scenario that only affects keyboard users who have focus on a chevron at the exact moment it unmounts — real but narrow. The P2 hardcoded-key issue is a maintenance concern, not a runtime bug.

ui-nextjs/components/explore/DataSourceTabs.tsx — focus management in scrollBy and the hardcoded 'policy' key

Important Files Changed

Filename Overview
ui-nextjs/components/explore/DataSourceTabs.tsx Adds scroll-affordance chevrons, edge-fade gradients, and a pulsing Policy Bills indicator; ResizeObserver + scroll-listener pattern is well-implemented with proper cleanup, but keyboard focus is lost when a chevron unmounts and the pulsing-dot logic hardcodes 'policy'.
ui-nextjs/lib/explore-config.ts Reorders the policy entry to position 2 (right after Census ACS) so it is visible in the initial viewport; no logic changes, comment preserved.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[DataSourceTabs mounts] --> B[useEffect: updateOverflow]
    B --> C{scrollWidth > clientWidth?}
    C -- Yes --> D[canScrollRight = true\nShow right chevron + fade]
    C -- No --> E[canScrollRight = false\nHide right chevron]

    D --> F[User clicks right chevron]
    F --> G[scrollBy +240px smooth]
    G --> H[scroll event fires]
    H --> I[updateOverflow re-runs]
    I --> J{At right boundary?}
    J -- Yes --> K[canScrollRight = false\nChevron unmounts\n⚠ focus lost if focused]
    J -- No --> D

    L[ResizeObserver] -- viewport resize --> I

    M[User clicks left chevron] --> N[scrollBy -240px smooth]
    N --> H
Loading

Reviews (1): Last reviewed commit: "fix(explore): improve Policy Bills tab d..." | Re-trigger Greptile

Comment thread ui-nextjs/components/explore/DataSourceTabs.tsx
Comment thread ui-nextjs/components/explore/DataSourceTabs.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui-nextjs/components/explore/DataSourceTabs.tsx`:
- Around line 76-93: The tab buttons are only visually indicating selection;
update the button element used in DataSourceTabs to expose the active state to
assistive tech by adding semantic ARIA attributes: give the button role="tab"
and set aria-selected={isActive} (and aria-controls if a matching panel id
exists), ensuring the existing isActive logic is used to drive the attribute;
keep the onClick handler (onSelect) and key (src.key) unchanged so behaviour and
identity remain the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e673cc52-5c70-480f-9855-e7a00dbda63e

📥 Commits

Reviewing files that changed from the base of the PR and between 911d966 and 51bddab.

📒 Files selected for processing (2)
  • ui-nextjs/components/explore/DataSourceTabs.tsx
  • ui-nextjs/lib/explore-config.ts

Comment thread ui-nextjs/components/explore/DataSourceTabs.tsx
- Preserve keyboard focus when chevron unmounts after scrolling to the
  edge by redirecting focus to the scroller (which is now programmatically
  focusable via tabIndex=-1)
- Replace hardcoded 'policy' key check with a declarative 'highlight'
  field on DataSourceConfig, so future sources can opt into the same
  visual elevation without editing the component
- Add aria-pressed to tab buttons so assistive tech announces the
  currently-selected data source

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui-nextjs/components/explore/DataSourceTabs.tsx`:
- Around line 76-79: The scroller element currently uses tabIndex={-1} and
removes focus outline via className="... outline-none", which leaves no visible
focus when programmatic focus lands there (e.g., after chevron unmount); restore
a subtle focus style by replacing or augmenting the outline-none with a small
accessible focus indicator (e.g., add a focus-visible class or ring) on the
element referenced by scrollerRef so keyboard users see focus before it moves to
a tab button, while keeping the element out of normal tab order.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 78061084-d640-41b3-bb14-1e923235ef09

📥 Commits

Reviewing files that changed from the base of the PR and between 51bddab and c24ff72.

📒 Files selected for processing (2)
  • ui-nextjs/components/explore/DataSourceTabs.tsx
  • ui-nextjs/lib/explore-config.ts

Comment thread ui-nextjs/components/explore/DataSourceTabs.tsx Outdated
@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • ui-nextjs/components/explore/DataSourceTabs.tsx

Commit: 7896c34d67cd4172a13841e005ed7247d296b991

The changes have been pushed to the fix/policy-tab-discoverability branch.

Time taken: 5m 10s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@William-Hill William-Hill merged commit e9db892 into main Apr 13, 2026
4 checks passed
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.

1 participant