Skip to content

feat(web): filter sidebar threads by environment - #8530

Open
saphid wants to merge 8 commits into
pingdotgg:mainfrom
saphid:web/sidebar-environment-filter
Open

feat(web): filter sidebar threads by environment#8530
saphid wants to merge 8 commits into
pingdotgg:mainfrom
saphid:web/sidebar-environment-filter

Conversation

@saphid

@saphid saphid commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Observed problem and reproduction

Connect T3 Code to more than one environment and open the web or desktop sidebar. Threads from every machine are interleaved. The project filter cannot express “show only this environment” because one logical project may span environments.

Cause

The sidebar had project scope but no environment scope. Thread rows, drafts, search results, project options, selection, and settled pagination always used the full connected-environment catalog.

Change and boundary

The sidebar now shows an icon-only environment checklist beside the project combobox only when more than one environment is connected. Selected environments use the normal high-contrast foreground; unchecked environments are slightly faded at rest and retain a theme-safe 70% accent foreground while highlighted. The last selected environment stays high contrast but has a distinct locked background, not-allowed cursor, and repository-standard tooltip explaining the at-least-one constraint. The trigger also has the same themed tooltip pattern as the adjacent icon buttons.

Disabling an environment hides its threads, drafts, and search results, narrows project options, clears multi-select, and resets settled-tail pagination. A dot marks an active filter. Project choices retain upstream’s logical group label, so selecting one environment never replaces a grouped repository with one physical clone name and never appends a redundant environment name.

State is the disabled environment set. An empty set means all environments are enabled, newly connected environments are visible by default, and the last enabled environment cannot be unchecked. Catalog pruning is derived during render, so disconnecting the last enabled environment cannot produce a transient empty sidebar before the synchronization effect runs.

This is session-only and uses the shared web sidebar, so it applies to web and desktop. React Native mobile, SwiftUI mobile, providers, server events, and wire contracts are unchanged. Settings, the command palette, and keybindings do not own this list filter. Local, direct remote, relay, and tunnel catalogs use the same client-side path.

Validation

On remote head 248f6158842b9adce725a88efd6c3b846d93eb0a, against fetched live main target 1f8ed54add4133ac39effceded8fc1fff12d8e03:

  • CI=true pnpm vp test run src/components/Sidebar.logic.test.ts from apps/web: 1 file and 124 tests passed; exit 0.
  • CI=true pnpm vp lint apps/web/src/components/Sidebar.tsx apps/web/src/components/Sidebar.logic.ts apps/web/src/components/Sidebar.logic.test.ts: exit 0.
  • CI=true pnpm vp format --check apps/web/src/components/Sidebar.tsx apps/web/src/components/Sidebar.logic.ts apps/web/src/components/Sidebar.logic.test.ts: exit 0.
  • CI=true pnpm --filter @t3tools/web typecheck: exit 0.
  • git diff --check: exit 0.
  • Current-head multi-environment pass: the control rendered with two seeded environments; selected rows computed to full foreground, unchecked rows to muted foreground, and the active-filter dot appeared after one environment was unchecked.
  • Current-head one-selected pass: the unchecked highlighted row used text-accent-foreground/70, the selected locked row remained full contrast with a distinct background and not-allowed cursor, and the project menu retained the logical project label without an environment suffix.
  • Current-head single-environment pass: after disconnecting the seeded remote, the environment control was absent and project labels remained plain logical labels.
  • Reconnect/update pass during this correction series: reconnecting the seeded remote restored the control with the new environment enabled by default; catalog pruning did not strand a stale disabled id or paint an empty sidebar. The final commits changed only row presentation, tooltip composition, and logical label presentation; the reconnect state model stayed unchanged and remains covered by the focused pruning tests.
  • GitHub reports MERGEABLE / CLEAN and all current-head checks complete: 18 successful, 8 expected skips, 1 neutral, 0 failures, 0 pending. Cursor Bugbot and Macroscope Correctness, UI Consistency, Effect Service Conventions, and Approvability completed without a current-head finding.
  • The branch is 8 commits ahead and 7 behind fetched live main, with merge base 053affbed2659f90cd1b1efaaa7a75865c4131c7. Per owner instruction, this correction used normal owned-head pushes only: no merge, rebase, force-push, or merge action.

Cross-provider review was not run because the owner explicitly required no re-delegation. GPT-5.6 Sol reviewed the frozen three-file diff against the repository policy and the primary-worktree CODING_STANDARDS.md hash 144fbf46af335d8d18a95c8d4b4f2e9e0207fa2e; no actionable issue remained after the current review feedback was applied.

Evidence

Known gaps: Current-head static screenshots, GIFs, and MP4 capture are pending. The attached T3 preview’s snapshot endpoint failed, and its recording start timed out after 15 seconds. A Chrome fallback was abandoned because that browser was actively in use. The media below is historical reference from head 163236dac and is not claimed as current-head proof.

Historical visual reference — head 163236d

Before, dark

Sidebar before the environment filter, dark, cropped

After, dark

Environment checklist after the change, dark, cropped

Before and after, dark

Animated before and after comparison, dark, cropped

Interaction

Environment-filter action sequence, cropped

Play or download the MP4 interaction recording.

Light mode evidence

Sidebar before the environment filter, light, cropped

Environment checklist after the change, light, cropped

Animated before and after comparison, light, cropped

Full-window source captures and animations

Full-window sidebar before the environment filter, dark

Full-window environment checklist after the change, dark

Full-window environment-filter disabled state, dark

Full-window filtered result, dark

Full-window before and after animation, dark

Full-window sidebar before the environment filter, light

Full-window environment checklist after the change, light

Full-window environment-filter disabled state, light

Full-window filtered result, light

Full-window before and after animation, light

Full-window environment-filter action sequence

Risks and limitations

  • Relay and tunnel connections were not exercised because transport behavior is unchanged.
  • Mobile clients are separate implementations and remain unchanged.
  • Current-head semantic runtime verification is complete, but current-head media capture remains the explicit evidence gap above.

Owning issue and stack

No owning issue, discussion, or stacked PR exists. This is a direct web contribution, and maintainer edits are enabled.

Implemented and reviewed by GPT-5.6 Sol in the Codex/T3 harness.


Note

Low Risk
Client-only sidebar list filtering with guarded edge cases and unit tests; no server, auth, or persistence changes.

Overview
Adds a session-only environment filter to the web sidebar when more than one environment is connected: a server icon menu with per-environment checkboxes (and an active-filter dot) beside the existing project scope combobox.

Filter state is stored as the disabled environment set (empty = all visible; new connections stay on by default). toggleDisabledEnvironmentId and pruneDisabledEnvironmentIds in Sidebar.logic.ts handle toggles, no-op set identity for React, blocking the last enabled environment, and resetting when disconnects would hide every thread. The sidebar applies the enabled set to thread partitioning, draft rows, project picker options, multi-select clearing, settled-tail pagination reset, and empty-state copy; project scope widens to “all projects” if the scoped project would have no enabled environments.

Reviewed by Cursor Bugbot for commit 248f615. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add environment filter menu to sidebar for filtering threads and drafts

  • Adds a new environments dropdown menu to the sidebar header (visible only when more than one environment exists) with per-environment checkboxes and an "All environments" option
  • Introduces toggleDisabledEnvironmentId and pruneDisabledEnvironmentIds utilities in Sidebar.logic.ts that store disabled environment IDs as a Set, preserve reference identity for no-ops, and prevent disabling the last enabled environment
  • Applies the filter to thread visibility, draft sessions, visible thread counts, project scope, pagination reset keys, and empty-state messaging
  • Automatically prunes stale disabled IDs when environments disconnect and clears project scope if the scoped project becomes fully filtered out
  • Behavioral Change: multi-select selection state is now cleared when the environment filter changes, in addition to existing project-scope clear behavior

Macroscope summarized 248f615.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ed595e2f-27b7-40f6-bd25-6aaef96209b9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 28, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial session-only environment-filter workflow that changes how sidebar threads, drafts, search results, project choices, selection, and pagination are presented. The unresolved disabled-state affordance issue also merits review before relying on the new interaction.

You can add or adjust custom eligibility rules. Learn more.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 28, 2026
@saphid
saphid force-pushed the web/sidebar-environment-filter branch from 258c853 to 8983e13 Compare August 28, 2026 21:35
@macroscopeapp
macroscopeapp Bot dismissed their stale review August 28, 2026 21:35

Dismissing prior approval to re-evaluate 8983e13

@macroscopeapp macroscopeapp 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.

One consistency finding on the new environment-filter trigger: it is the only icon SidebarMenuButton in this header row without the coarse-pointer hit-target overlay its neighbors use. Everything else (Menu/MenuPopup/MenuCheckboxItem composition, width-class contract on MenuPopup, active-filter dot matching PullRequestListFilters) matches the shared component system.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Sidebar.tsx Outdated
Comment thread apps/web/src/components/Sidebar.tsx Outdated
@saphid
saphid force-pushed the web/sidebar-environment-filter branch from 8983e13 to 14ed67b Compare August 28, 2026 22:45
saphid and others added 2 commits August 29, 2026 13:47
Add an icon button next to the sidebar's project scope menu (visible only
when more than one environment is connected) that opens a checklist to
enable and disable which environments' threads the list shows. The filter
composes with the project scope, draft rows, search, and the settled-tail
pagination reset; the project menu narrows to projects with a presence in
an enabled environment.

State is the disabled set, so newly connected environments are visible by
default. The last enabled environment cannot be unchecked, and a catalog
change that would leave nothing enabled resets the filter instead of
hiding every thread behind a control that no longer renders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@saphid
saphid force-pushed the web/sidebar-environment-filter branch from 14ed67b to 72c948d Compare August 29, 2026 03:48

@macroscopeapp macroscopeapp 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.

Two consistency findings on the new environment filter control in apps/web/src/components/Sidebar.tsx. Everything else (dot indicator matching PullRequestListFilters, MenuPopup width contract, SidebarMenuButton icon-color indirection) lines up with the existing system.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Sidebar.tsx Outdated
Comment on lines +3809 to +3812
className={cn(
"[&>span:last-child]:min-w-0",
isEnabled
? "text-foreground data-disabled:opacity-100"

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.

data-disabled:opacity-100 cancels the only visible disabled affordance MenuCheckboxItem has. The primitive's disabled state is pointer-events-none + cursor-not-allowed + opacity-64; with pointer events off there is no hover highlight and no not-allowed cursor either, so the last enabled environment renders identically to an interactive checked item that silently does nothing on click — the outcome the adjacent comment says the disabled prop is there to avoid.

Consider keeping the primitive's dimming so the at-least-one constraint is actually visible:

Suggested change
className={cn(
"[&>span:last-child]:min-w-0",
isEnabled
? "text-foreground data-disabled:opacity-100"
? "text-foreground"

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Sidebar.tsx Outdated

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort 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 d80e30b. Configure here.

Comment thread apps/web/src/components/Sidebar.logic.ts Outdated

@macroscopeapp macroscopeapp 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.

One finding on the new commit: the locked environment row explains its constraint with a native title attribute instead of the shared Tooltip primitive. Details inline.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Sidebar.tsx Outdated

@macroscopeapp macroscopeapp 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.

One finding on the newest commit: the environment checkbox rows now pin data-highlighted text colors, which overrides MenuCheckboxItem's accent-surface foreground contract.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Sidebar.tsx Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant