Skip to content

feat: flatten workspace chrome and consolidate settings - #29

Merged
donovan-yohan merged 2 commits into
mainfrom
feat/flat-settings
Aug 8, 2026
Merged

donovan-yohan merged 2 commits into
mainfrom
feat/flat-settings

Conversation

@donovan-yohan

@donovan-yohan donovan-yohan commented Aug 8, 2026 •

Copy link
Copy Markdown
Owner

Closes #28

What changed

  • replaces the persistent theme, MCP connection, and self-rename controls with one right-aligned Settings surface
  • keeps display name, agent connection, and appearance state with their existing owners instead of adding a parallel state model
  • removes product-owned drop shadows and adopts flat borders, outlines, and intentional selection strokes
  • makes the settings and connection surfaces keyboard accessible, focus-contained, and independent from source/activity flyouts
  • strengthens workspace browser coverage for settings, themes, MCP status, canvas focus, flat styling, responsive containment, and 44 px touch targets

Architecture

This slice reuses the existing ThemeProvider, Awareness identity, and agent-connection flow. Settings is presentation/composition only: it does not add Yjs state, protocol fields, or a second source of truth. Diagram renaming remains tab-scoped, and source/activity flyout ownership remains unchanged.

Verification

  • shared build
  • 139 unit tests
  • recursive typecheck, lint, and production build
  • sequence E2E with owned services
  • collaboration E2E with owned services
  • workspace UX E2E: 18 passed
  • adversarial review followed by one focused fix/re-review; no remaining P0/P1/P2 findings
  • git diff --check

Known follow-up

At the late populated mobile state, the nominal 320 px screenshot is still 339 px wide because the footer/presence region can overflow. Settings itself remains contained and usable. The exact reproduction and acceptance gate are tracked in #18 rather than being misreported as fixed here.

Summary by CodeRabbit

  • New Features

    • Added workspace settings for editing display names, selecting themes, and managing agent connections.
    • Added connection status details, agent counts, and responsive settings dialogs.
    • Improved keyboard navigation, focus handling, Escape-key support, and outside-click dismissal.
  • Style

    • Refined the interface with flatter visual styling, reduced shadows, and outlined selection indicators.
    • Improved responsive dialog, connection-status, and theme-option presentation.
  • Tests

    • Expanded automated coverage for settings behavior, focus management, themes, agent presence, persistence, and responsive layouts.

@vercel

vercel Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
arielcharts Ready Ready Preview Aug 8, 2026 3:38pm

@coderabbitai

coderabbitai Bot commented Aug 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@donovan-yohan, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: faf42ed4-0779-475b-814a-ab3c71ecbc5f

📥 Commits

Reviewing files that changed from the base of the PR and between 341f53d and 91856c1.

📒 Files selected for processing (8)
  • apps/web/src/app/globals.css
  • apps/web/src/components/session-workspace.tsx
  • apps/web/src/components/workspace-settings.tsx
  • apps/web/src/lib/connection-state.ts
  • apps/web/src/lib/focusable.ts
  • apps/web/src/lib/session.test.ts
  • apps/web/src/lib/session.ts
  • e2e-workspace-ux-validate.ts
📝 Walkthrough

Walkthrough

The PR consolidates identity, agent connection, and theme controls into WorkspaceSettings. It adds accessible dialog behavior, responsive styling, flat visual treatments, and expanded unit and end-to-end validation.

Changes

Workspace UX consolidation

Layer / File(s) Summary
Workspace settings surface
apps/web/src/components/workspace-settings.tsx, apps/web/src/app/globals.css, apps/web/src/components/workspace-settings.test.ts
Adds display-name editing, agent connection actions, appearance radios, dialog focus handling, outside-pointer dismissal, responsive layout, and helper tests.
Workspace integration and modal flow
apps/web/src/components/session-workspace.tsx, apps/web/src/lib/session.test.ts
Replaces inline controls with WorkspaceSettings, updates awareness and local storage on name save, and adds connection status, agent counts, focus trapping, and focus restoration.
Flat visual treatments
apps/web/src/app/globals.css, apps/web/src/components/diagram-canvas.tsx
Removes product shadows and glow effects. Selected, focused, and active states use outlines, strokes, and underline indicators.
Browser and helper validation
e2e-workspace-ux-validate.ts, e2e/support/workspace.ts
Adds settings helpers and validates themes, agent presence, modal behavior, focus handling, responsive layout, overlay coexistence, camera stability, and flat chrome.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  actor WorkspaceUser
  participant WorkspaceSettings
  participant SessionWorkspace
  participant ConnectionModal
  WorkspaceUser->>WorkspaceSettings: Open settings
  WorkspaceUser->>WorkspaceSettings: Save name or select theme
  WorkspaceSettings->>SessionWorkspace: Submit workspace changes
  WorkspaceUser->>WorkspaceSettings: Connect agent
  WorkspaceSettings->>SessionWorkspace: Start connection flow
  SessionWorkspace->>ConnectionModal: Display status and agent count
Loading

Possibly related PRs

🚥 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 clearly summarizes the primary changes: flattening workspace chrome and consolidating settings.
Linked Issues check ✅ Passed The changes implement the WorkspaceSettings consolidation, flat styling, accessibility, responsive behavior, state reuse, and coverage required by [#28].
Out of Scope Changes check ✅ Passed The modified components, styles, tests, and E2E coverage directly support the linked issue objectives, with no unrelated changes identified.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/flat-settings

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (7)
apps/web/src/components/workspace-settings.tsx (2)

206-219: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider labelling the dialog with its heading.

The dialog sets aria-label="Workspace settings" while it also renders <h2>Settings</h2>. Screen reader users hear two different names for the same surface. Give the heading an id and use aria-labelledby to keep one name.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/workspace-settings.tsx` around lines 206 - 219,
Update the dialog in the isOpen render block to remove the conflicting
aria-label, assign a unique id to the Settings h2, and reference that id through
aria-labelledby on the element with role="dialog".

8-8: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider importing the shared ConnectionState type.

session-workspace.tsx already defines a ConnectionState union and passes it to this component. A local duplicate can drift if a new state is added. Import the shared type instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/workspace-settings.tsx` at line 8, Replace the local
ConnectionState union in workspace-settings.tsx with an import of the shared
ConnectionState type defined by session-workspace.tsx, and update the component
references to use that imported type.
e2e-workspace-ux-validate.ts (2)

154-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Await the provider connection and reuse the app's endpoint derivation.

connectAgentPresence builds the WebSocket URL by rewriting the MCP URL protocol and forcing pathname = '/ws'. This duplicates the app's own endpoint logic. If the server path changes, the helper connects to a dead endpoint and the only symptom is the 15-second waitForFunction timeout at line 536.

Wait for the provider status event to report connected before returning, so a bad endpoint fails with a clear message.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e-workspace-ux-validate.ts` around lines 154 - 173, Update
connectAgentPresence to derive the WebSocket endpoint using the app’s existing
endpoint-resolution logic instead of manually rewriting the MCP URL and forcing
/ws. Make the helper await the WebsocketProvider status event until it reports
connected before returning, and surface a clear failure if the connection cannot
be established.

692-692: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use locator-based waits for the selection checks.

Line 692 and 716 pass captured ElementHandles after .hover() / .click() that can replace the React Flow elements. Use the existing locators with expect(...).toHaveClass(...), or poll a selector string inside waitForFunction, to avoid stale-handle failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e-workspace-ux-validate.ts` at line 692, Update the selection checks around
the visible node interactions to use the existing locator rather than an
ElementHandle captured from visibleNode.elementHandle(). Replace the
waitForFunction calls after hover/click with locator-based
expect(...).toHaveClass(...) assertions or selector polling, preserving the
is-selected requirement while avoiding stale React Flow element handles.
apps/web/src/components/session-workspace.tsx (1)

65-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider sharing one focusable-element selector.

workspace-settings.tsx defines FOCUSABLE_SELECTOR with radio and hidden-input handling. This file defines a second, less strict selector for the same purpose. Extract one constant into a shared module so both focus traps stay consistent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/session-workspace.tsx` at line 65, Extract the
focusable-element selector into a shared module, using the stricter selector
from workspace-settings.tsx that includes radio and hidden-input handling.
Update MODAL_FOCUSABLE_SELECTOR in session-workspace.tsx and FOCUSABLE_SELECTOR
in workspace-settings.tsx to import and reuse that shared constant so both focus
traps remain consistent.
e2e/support/workspace.ts (1)

112-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse this exported helper instead of duplicating it.

e2e-workspace-ux-validate.ts defines its own openWorkspaceSettings at lines 129-137 with the same body. That file already imports selectWorkspaceTheme from this module, and selectWorkspaceTheme calls this exported helper. Two implementations of the same interaction can drift apart.

Import this helper in e2e-workspace-ux-validate.ts and delete the local copy. Consider exporting closeWorkspaceSettings here as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/support/workspace.ts` around lines 112 - 120, Reuse the exported
openWorkspaceSettings helper from workspace.ts in e2e-workspace-ux-validate.ts:
add it to the existing import, remove that file’s local duplicate
implementation, and preserve all current call sites. Export
closeWorkspaceSettings from workspace.ts as well if the validation flow
currently needs the same shared interaction.
apps/web/src/app/globals.css (1)

1044-1046: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the React Flow v12 CSS variable variants and drop the unused Controls variable.

React Flow v12 uses the -default variants (--xy-controls-box-shadow-default, --xy-node-boxshadow-hover-default, --xy-node-boxshadow-selected-default), so var(--xy-*) does resolve to a value. diagram-canvas.tsx does not render React Flow <Controls>, so remove the Controls override to avoid dead CSS.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/app/globals.css` around lines 1044 - 1046, Update the React Flow
CSS variable declarations by removing the unused --xy-controls-box-shadow
override and renaming the hover and selected node variables to their v12
-default variants: --xy-node-boxshadow-hover-default and
--xy-node-boxshadow-selected-default.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/app/globals.css`:
- Around line 487-497: Update the max-width 720px media query so
.workspace-settings-close, .workspace-settings-actions button, and
.workspace-settings-connect receive a 44px minimum height on phone viewports,
matching the existing .workspace-settings-trigger touch-target sizing while
preserving their other styles.

In `@apps/web/src/components/session-workspace.tsx`:
- Around line 959-971: In apps/web/src/components/session-workspace.tsx:959-971,
add display-name state, update it in saveDisplayName and in the collaboration
effect that assigns currentIdentityRef.current, and pass that state to
WorkspaceSettings instead of reading the ref during render. In
apps/web/src/components/workspace-settings.tsx:130-137, separate the
isOpen-driven draft initialization and autofocus effect from the
keydown/pointerdown listener effect, keeping the listeners dependent on [close,
isOpen] so display-name changes do not reset drafts or steal focus.

In `@e2e-workspace-ux-validate.ts`:
- Around line 147-152: Update selectThemePreference so the system preference
resolves the expected theme from the page’s emulated color scheme, while
explicit dark and light preferences retain their direct mappings. Use the
resolved value when waiting for the html[data-theme] locator, ensuring system
mode works under dark emulation.
- Around line 546-549: Fix the cleanup wait in the finally block by ensuring it
observes a mounted agent-status element: reopen the settings dialog before
waitForFunction, or switch the predicate to the persistent presence-bar status
element. Preserve the requirement that the wait resolves only after “MCP agent
working” is no longer present.

---

Nitpick comments:
In `@apps/web/src/app/globals.css`:
- Around line 1044-1046: Update the React Flow CSS variable declarations by
removing the unused --xy-controls-box-shadow override and renaming the hover and
selected node variables to their v12 -default variants:
--xy-node-boxshadow-hover-default and --xy-node-boxshadow-selected-default.

In `@apps/web/src/components/session-workspace.tsx`:
- Line 65: Extract the focusable-element selector into a shared module, using
the stricter selector from workspace-settings.tsx that includes radio and
hidden-input handling. Update MODAL_FOCUSABLE_SELECTOR in session-workspace.tsx
and FOCUSABLE_SELECTOR in workspace-settings.tsx to import and reuse that shared
constant so both focus traps remain consistent.

In `@apps/web/src/components/workspace-settings.tsx`:
- Around line 206-219: Update the dialog in the isOpen render block to remove
the conflicting aria-label, assign a unique id to the Settings h2, and reference
that id through aria-labelledby on the element with role="dialog".
- Line 8: Replace the local ConnectionState union in workspace-settings.tsx with
an import of the shared ConnectionState type defined by session-workspace.tsx,
and update the component references to use that imported type.

In `@e2e-workspace-ux-validate.ts`:
- Around line 154-173: Update connectAgentPresence to derive the WebSocket
endpoint using the app’s existing endpoint-resolution logic instead of manually
rewriting the MCP URL and forcing /ws. Make the helper await the
WebsocketProvider status event until it reports connected before returning, and
surface a clear failure if the connection cannot be established.
- Line 692: Update the selection checks around the visible node interactions to
use the existing locator rather than an ElementHandle captured from
visibleNode.elementHandle(). Replace the waitForFunction calls after hover/click
with locator-based expect(...).toHaveClass(...) assertions or selector polling,
preserving the is-selected requirement while avoiding stale React Flow element
handles.

In `@e2e/support/workspace.ts`:
- Around line 112-120: Reuse the exported openWorkspaceSettings helper from
workspace.ts in e2e-workspace-ux-validate.ts: add it to the existing import,
remove that file’s local duplicate implementation, and preserve all current call
sites. Export closeWorkspaceSettings from workspace.ts as well if the validation
flow currently needs the same shared interaction.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dc57721e-fab5-4521-ac86-ed049eed83dd

📥 Commits

Reviewing files that changed from the base of the PR and between d70ebf9 and 341f53d.

📒 Files selected for processing (9)
  • apps/web/src/app/globals.css
  • apps/web/src/components/diagram-canvas.tsx
  • apps/web/src/components/session-workspace.tsx
  • apps/web/src/components/theme-control.tsx
  • apps/web/src/components/workspace-settings.test.ts
  • apps/web/src/components/workspace-settings.tsx
  • apps/web/src/lib/session.test.ts
  • e2e-workspace-ux-validate.ts
  • e2e/support/workspace.ts
💤 Files with no reviewable changes (1)
  • apps/web/src/components/theme-control.tsx

Comment thread apps/web/src/app/globals.css
Comment thread apps/web/src/components/session-workspace.tsx
Comment thread e2e-workspace-ux-validate.ts
Comment thread e2e-workspace-ux-validate.ts
@donovan-yohan
donovan-yohan merged commit 6a1e78d into main Aug 8, 2026
5 checks passed
@donovan-yohan
donovan-yohan deleted the feat/flat-settings branch August 8, 2026 15:39

This branch was successfully deployed

1 active deployment
Preview — 91856c14 Deployed Aug 8, 2026 by vercel[bot]
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.

Flatten app chrome and consolidate personal settings

1 participant