Skip to content

Robust tab visibility and gating#428

Merged
Benjtalkshow merged 7 commits into
boundlessfi:mainfrom
legend4tech:Robust-Tab-Visibility-and-Gating
Mar 3, 2026
Merged

Robust tab visibility and gating#428
Benjtalkshow merged 7 commits into
boundlessfi:mainfrom
legend4tech:Robust-Tab-Visibility-and-Gating

Conversation

@legend4tech
Copy link
Copy Markdown
Contributor

@legend4tech legend4tech commented Mar 2, 2026

Robust Tab Visibility & Gating

Closes #403

What changed

Ensured that tabs not explicitly enabled in enabledTabs are completely hidden from every navigation surface and are entirely unreachable whether through normal navigation, direct URL entry, browser history, or stale deep links.

How it works

Navigation Filtering

  • Refactored the hackathonTabs useMemo to filter the tabs array against currentHackathon.enabledTabs before returning
  • overview is always kept as the default fallback tab
  • If enabledTabs is undefined/null (not configured), all tabs show as before , no existing behaviour broken
  • currentHackathon.enabledTabs is included in the memo's dependency array so tabs update dynamically when the configuration changes without a hard reload

Component Guards

  • Added isTabVisible() helper that checks if a tab ID exists in the filtered hackathonTabs array
  • Wrapped every tab component (HackathonResources, AnnouncementsTab, SubmissionTab, HackathonDiscussions, TeamFormationTab, WinnersTab, HackathonParticipants) in an isTabVisible() check — disabled tab components never mount at all, not even partially
  • Removed a duplicate HackathonResources render that existed in the original code

Deep Link Gating

  • Updated the URL tab useEffect to call setActiveTab('overview') and router.replace when the URL tab is not in the filtered list
  • Uses router.replace (not push) so the disabled tab URL does not persist in browser history
  • Fixed a React rules-of-hooks violation by deriving a stable tabIds string from hackathonTabs instead of passing the array directly into the useEffect dependency array

Mobile Navigation

  • HackathonNavTabs renders only what is passed via the tabs prop — no internal tab list
  • Since HackathonPageClient passes the already-filtered hackathonTabs as the prop, mobile and desktop navigation are automatically in sync with zero extra changes needed

Files changed

  • app/(landing)/hackathons/[slug]/HackathonPageClient.tsx

Summary by CodeRabbit

  • New Features

    • Tab visibility controls for hackathon pages so organizers can customize which navigation tabs appear.
    • URL handling defaults to the Overview tab and activates only tabs that are visible.
  • Bug Fixes

    • Prevents duplicate resource entries on hackathon pages.
    • Direct links to disabled/hidden tabs now silently redirect to Overview.
    • Tab selection and routing/query-parameter updates are more reliable.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 2, 2026

@legend4tech is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Filters hackathon tabs against currentHackathon.enabledTabs, maps UI tab ids to backend keys, prevents rendering of disabled tab components, redirects URL-requested disabled tabs to overview via router.replace, and adds a devDependency for @eslint/js.

Changes

Cohort / File(s) Summary
Tab Visibility Gating
app/(landing)/hackathons/[slug]/HackathonPageClient.tsx
Implements filtering of available tabs by currentHackathon.enabledTabs with a UI→backend key map, adds isTabVisible(tabId) guards around each tab's render, updates URL-handling to default/replace to overview when a requested tab is not visible, and adds router to effect deps.
Development Dependency
package.json
Adds devDependency @eslint/js@^9.39.3.

Sequence Diagram(s)

sequenceDiagram
  participant Browser as Browser
  participant Router as Router
  participant HackClient as HackathonPageClient
  participant Tabs as TabComponents

  Browser->>Router: Navigate with ?tab=someTab
  Router->>HackClient: provide query param
  HackClient->>HackClient: compute filteredTabs = tabs ∩ enabledTabs
  alt requested tab in filteredTabs
    HackClient->>Tabs: render requested tab component
  else requested tab NOT in filteredTabs
    HackClient->>Router: router.replace(?tab=overview)
    HackClient->>Tabs: render overview tab component
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • 0xdevcollins

Poem

🐰
I hopped through tabs both near and wide,
Hidden ones now vanish, nowhere to hide.
A stale link nudges me back to the shore,
Overview welcomes — I bound once more.
🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: implementing robust tab visibility and gating logic to control which tabs are shown based on enabled status.
Linked Issues check ✅ Passed The implementation successfully addresses all core objectives from issue #403: filters visible tabs via useMemo with dynamic dependencies, guards tab component rendering, handles deep link gating with overview fallback, maintains mobile/desktop consistency, and includes necessary helper functions.
Out of Scope Changes check ✅ Passed The package.json change adding @eslint/js is a minor dev dependency update unrelated to the main tab gating feature but reasonable for code quality.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@app/`(landing)/hackathons/[slug]/HackathonPageClient.tsx:
- Around line 170-185: The filtering currently skips when enabledTabs is an
empty array and compares tab.id to enabledTabs entries which are actually tab
keys; update the logic in the currentHackathon.enabledTabs branch so that you
run the filter whenever enabledTabs is not null/undefined (i.e., check
currentHackathon?.enabledTabs !== undefined rather than length>0), and inside
tabs.filter use the actual tab key property (e.g., tab.key or whichever field
holds values like "joinATeamTab"/"winnersTab") instead of tab.id, casting to
EnabledTab as needed so an empty array will hide all non-overview tabs and
enabledTabs entries correctly match tab identifiers.

In `@package.json`:
- Line 150: package.json currently lists "eslint" at 9.39.2 which conflicts with
the new "@eslint/js@10.0.1" peer requirement; update the "eslint" dependency in
package.json to a v10 range (e.g. "eslint": "^10.0.0") so it satisfies
`@eslint/js`'s peer dependency, then run npm/yarn install and verify
eslint.config.mjs imports work as expected; reference the "eslint" entry in
package.json and the "@eslint/js" dependency when making the change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 04c46d6 and c478086.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • app/(landing)/hackathons/[slug]/HackathonPageClient.tsx
  • package.json

Comment thread app/(landing)/hackathons/[slug]/HackathonPageClient.tsx Outdated
Comment thread package.json Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 `@app/`(landing)/hackathons/[slug]/HackathonPageClient.tsx:
- Around line 300-314: The useEffect handling searchParams currently ignores the
case when there is no 'tab' param, which can leave activeTab stale; update the
effect in HackathonPageClient (the useEffect that reads searchParams and uses
hackathonTabs) to setActiveTab('overview') when tabFromUrl is null or empty, and
ensure the URL is synchronized by creating a URLSearchParams copy, setting
tab=overview and calling router.replace(`?${queryParams.toString()}`, { scroll:
false }); keep the existing branch that validates tabFromUrl against
hackathonTabs and the fallback for unrecognised/disabled tabs.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c7f906a and 173c317.

📒 Files selected for processing (1)
  • app/(landing)/hackathons/[slug]/HackathonPageClient.tsx

Comment thread app/(landing)/hackathons/[slug]/HackathonPageClient.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 `@app/`(landing)/hackathons/[slug]/HackathonPageClient.tsx:
- Around line 174-177: The tabIdToEnabledKey mapping is incomplete and must
include UI ids that differ from backend keys; update the tabIdToEnabledKey
Record used in HackathonPageClient.tsx (currently containing 'team-formation'
and 'winners') to also map 'resources' -> 'resourcesTab', 'participants' ->
'participantsTab', 'announcements' -> 'announcementsTab', 'submission' ->
'submissionTab', and 'discussions' -> 'discussionTab' so the fallback logic
(around the existing enabledTabs lookup) correctly finds the backend enabledTabs
keys.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 173c317 and 7ce95b1.

📒 Files selected for processing (1)
  • app/(landing)/hackathons/[slug]/HackathonPageClient.tsx

Comment thread app/(landing)/hackathons/[slug]/HackathonPageClient.tsx
Comment thread package.json Outdated
Copy link
Copy Markdown
Collaborator

@Benjtalkshow Benjtalkshow left a comment

Choose a reason for hiding this comment

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

Remove the pnpm-lock.yaml. The codebase uses npm

@legend4tech
Copy link
Copy Markdown
Contributor Author

Remove the pnpm-lock.yaml. The codebase uses npm

GM GM
removed, also the eslint i added all good now

Copy link
Copy Markdown
Collaborator

@Benjtalkshow Benjtalkshow left a comment

Choose a reason for hiding this comment

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

LGTM!

@Benjtalkshow Benjtalkshow merged commit 8d53df8 into boundlessfi:main Mar 3, 2026
7 of 8 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Mar 13, 2026
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.

Robust Tab Visibility & Gating

2 participants