This branch moves the branch discussion panel from an inline position within the review layout into a dedicated sidebar that slides in from the right. On desktop the sidebar uses a CSS grid column transition; on mobile it becomes a fixed overlay with a backdrop. A toggle button with a keyboard shortcut (Cmd+. on Mac, Ctrl+. elsewhere) is added to the action row, and the discussion panel gains a close button, Escape-key dismissal, and proper ARIA attributes. The Rust test file is updated to assert the presence of the new structural element IDs.
Tutorial Steps
Add CSS for the toggle button and keyboard-shortcut badge
Intent: Introduce utility classes for the new discussion toggle button and the shortcut hint pill that appears inside it.
A new .branch-review-shell element becomes the top-level grid. By default its second column is 0 wide, making the sidebar invisible. When the .discussion-open class is toggled on, the second column animates to clamp(320px, 24vw, 440px), smoothly revealing the sidebar.
The existing .review-layout loses its margin-top (now handled by the shell) and is nested inside .branch-review-content so it shares the first column with the diff section.
Style the discussion sidebar shell and its inner layout
Intent: Define the off-screen/hidden state, reveal transition, sticky positioning, and close-button styling for the sidebar discussion panel.
The sidebar shell starts fully transparent with pointer-events: none and a slight rightward translate. When .discussion-open is applied to the parent shell, opacity/transform transition to their visible values and pointer events are re-enabled.
Inside the sidebar the .discussion-panel uses position: sticky so it follows the viewport during scroll. A new .discussion-sidebar-head flex row places the existing heading beside a round Hide button (.discussion-close-btn).
Adjust the discussion messages container for flex layout
Intent: Switch the discussion message list from a fixed max-height to a flex-growing layout so it fills the sidebar height naturally.
Previously the message list was capped at 24rem. In the sidebar context it needs to fill available vertical space, so max-height is removed and both #discussion-main and .discussion-messages become flex children with flex: 1. The discussion panel itself is given explicit min-height and height values of min(76vh, 880px) to bound the sidebar height.
Add mobile responsive overrides with fixed-position overlay and backdrop
Intent: On narrow viewports, convert the sidebar from a grid column to a full-height fixed overlay with a semi-transparent backdrop.
The grid shell falls back to display: block so content stacks normally.
The sidebar becomes position: fixed anchored to the right edge, sliding in via translateX.
A .discussion-backdrop overlay (dark semi-transparent with backdrop-filter: blur) sits behind the sidebar (z-index: 30 vs the sidebar's 40) and is shown only when .discussion-open is active.
Clicking the backdrop closes the sidebar (wired in JavaScript later).
Restructure the HTML: wrap content in the shell and move discussion to an aside
Intent: Re-organise the template markup so the review content and discussion panel live as sibling grid children inside the new shell wrapper.
The template undergoes a significant structural change:
A new <div id="branch-review-shell"> wraps everything.
Inside it, <div class="branch-review-content"> contains the existing .review-layout (file list + review main), the tutorial steps, and the diff section.
The discussion panel moves out of .tutorial-column and into a sibling <aside id="discussion-sidebar"> with aria-hidden="true" by default.
A hidden <div id="discussion-backdrop"> is placed between the content and the sidebar for mobile overlay use.
The discussion panel gains a header row with a Hide close button (id="discussion-close").
Add the discussion toggle button to the action row
Intent: Give users an explicit button to open/close the discussion sidebar, complete with an ARIA-expanded attribute and shortcut badge.
A new <button> is inserted into the .action-row after the CI link. It uses aria-controls to reference the sidebar's ID and starts with aria-expanded="false". The label text (Open Discussion / Hide Discussion) and the shortcut badge text are updated dynamically by JavaScript based on state and platform detection.
Wire up toggle, close, and backdrop click handlers in JavaScript
Intent: Connect the new DOM elements to the sidebar open/close logic.
updateDiscussionToggleLabel() – syncs the button label, shortcut badge text, aria-expanded, aria-hidden, and backdrop hidden attribute with the current discussionOpen boolean.
setDiscussionOpen(nextOpen, options) – sets the boolean, toggles the .discussion-open CSS class on the shell, calls the label updater, and optionally focuses the input on the next animation frame.
toggleDiscussion(options) – convenience wrapper that flips the current state.
Platform detection (isMacLike) is computed once at load to display the correct modifier key in the shortcut badge.
Add keyboard shortcut (Cmd/Ctrl+.) and Escape to dismiss
Intent: Let users toggle the sidebar with a keyboard shortcut and dismiss it with Escape, skipping the shortcut when the user is typing in an input.
Guard against typing targets – if the active element is an <input>, <textarea>, or contentEditable, the handler returns early so the shortcut doesn't interfere with text entry.
Cmd/Ctrl + . – detected using the isMacLike flag; metaKey on Mac, ctrlKey elsewhere. Calls toggleDiscussion with focus-input behaviour.
Escape – when the sidebar is open, pressing Escape closes it.
The handler calls event.preventDefault() on the shortcut to suppress any browser-default behaviour for Cmd+. / Ctrl+..
Update Rust integration test assertions
Intent: Ensure the rendered HTML contains the new structural IDs introduced by the sidebar layout.
Three new assertions are added to the existing branch-detail rendering test in web.rs:
id="discussion-toggle" – the toggle button exists.
id="discussion-sidebar" – the sidebar aside exists.
id="branch-review-shell" – the outer grid shell exists.
These complement the pre-existing checks for discussion content and the chat artifact ID, confirming the structural rework is present in the rendered output.