Skip to content

Commit 3445162

Browse files
authored
🤖 Re-apply PR #382: Move Files Changed to top and remove stickiness (#402)
## Problem PR #382 was merged but was accidentally reverted by commit `00e5b179` (🤖 Restore ReviewPanel and FileTree from good state) during the Tailwind migration. This PR re-applies those changes to the current Tailwind-based codebase. ## Changes ### Layout Restructuring - **Search bar moved outside scrollable area** - Always visible at top, not part of the scrolling content - **Single scrollable container** - Created one `overflow-y-auto` div containing both file tree and hunks - **File tree on top in all viewports** - No longer side-by-side on wide screens - **No sticky behavior** - File tree scrolls away naturally with content ### Technical Implementation - Search bar: Fixed position at top with `border-b` - ScrollableContent: `flex min-h-0 flex-1 flex-col overflow-y-auto` - FileTree: First child with `flex-[0_0_auto]` (sizes to content, doesn't grow) - Hunks: Below file tree with `flex-[0_0_auto]` (sizes to content) ## Before vs After **Before (reverted state):** - File tree in sidebar (wide) or top section (narrow) - Two separate scrollable areas (tree + hunks) - File tree stayed visible when scrolling hunks **After (this PR):** - File tree always at top, full width - Single scrollable area containing both - File tree scrolls away naturally ## Related - Original PR: #382 - Reverted by: `00e5b179` (Tailwind migration cleanup) - Maintained: Common prefix extraction removal (already absent in current code) _Generated with `cmux`_
1 parent 9621063 commit 3445162

File tree

2 files changed

+76
-73
lines changed

2 files changed

+76
-73
lines changed

docs/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ This ensures transparency about AI-generated contributions.
2424

2525
## PR Management
2626

27-
**Prefer to reuse existing PRs** by force-pushing to the same branch, even if the branch name becomes irrelevant. Avoid closing and recreating PRs unnecessarily - PR spam clutters the repository history.
27+
**Prefer to reuse existing PRs** by force-pushing to the same branch, even if the branch name becomes irrelevant. Avoid closing and recreating PRs unnecessarily - PR spam clutters the repository history. **Never close PRs without explicit user instruction.** Always force-push to the existing branch instead of creating new PRs.
2828

2929
After submitting or updating PRs, **always check merge status**:
3030

src/components/RightSidebar/CodeReview/ReviewPanel.tsx

Lines changed: 75 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -555,68 +555,85 @@ export const ReviewPanel: React.FC<ReviewPanelProps> = ({
555555
Loading diff...
556556
</div>
557557
) : (
558-
<div className="flex min-h-0 flex-1 flex-row overflow-hidden @[800px]:flex-col">
559-
<div className="order-1 flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
560-
{truncationWarning && (
561-
<div className="bg-warning/10 border-warning/30 text-warning mx-3 my-3 flex items-center gap-1.5 rounded border px-3 py-1.5 text-[10px] leading-[1.3] before:text-xs before:content-['⚠️']">
562-
{truncationWarning}
563-
</div>
564-
)}
558+
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
559+
{truncationWarning && (
560+
<div className="bg-warning/10 border-warning/30 text-warning mx-3 my-3 flex items-center gap-1.5 rounded border px-3 py-1.5 text-[10px] leading-[1.3] before:text-xs before:content-['⚠️']">
561+
{truncationWarning}
562+
</div>
563+
)}
564+
565+
{/* Search bar - always visible at top, not sticky */}
566+
<div className="border-border-light bg-separator border-b px-3 py-2">
567+
<div className="border-border-light bg-dark hover:border-border-gray focus-within:border-accent focus-within:hover:border-accent flex items-stretch overflow-hidden rounded border transition-[border-color] duration-150">
568+
<input
569+
ref={searchInputRef}
570+
type="text"
571+
placeholder={`Search in files and hunks... (${formatKeybind(KEYBINDS.FOCUS_REVIEW_SEARCH)})`}
572+
value={searchState.input}
573+
onChange={(e) => setSearchState({ ...searchState, input: e.target.value })}
574+
className="text-foreground placeholder:text-dim focus:bg-separator flex h-full flex-1 items-center border-none bg-transparent px-2.5 py-1.5 font-sans text-xs leading-[1.4] outline-none"
575+
/>
576+
<TooltipWrapper inline>
577+
<button
578+
className={cn(
579+
"py-1.5 px-2.5 border-none border-l border-light text-[11px] font-monospace font-semibold leading-[1.4] cursor-pointer outline-none transition-all duration-150 whitespace-nowrap flex items-center h-full",
580+
searchState.useRegex
581+
? "bg-review-bg-blue text-accent-light shadow-[inset_0_0_0_1px_rgba(77,184,255,0.4)] hover:bg-review-bg-info hover:text-accent-light"
582+
: "bg-transparent text-subtle hover:bg-separator hover:text-foreground",
583+
"active:translate-y-px"
584+
)}
585+
onClick={() =>
586+
setSearchState({ ...searchState, useRegex: !searchState.useRegex })
587+
}
588+
>
589+
.*
590+
</button>
591+
<Tooltip position="bottom">
592+
{searchState.useRegex ? "Using regex search" : "Using substring search"}
593+
</Tooltip>
594+
</TooltipWrapper>
595+
<TooltipWrapper inline>
596+
<button
597+
className={cn(
598+
"py-1.5 px-2.5 border-none border-l border-light text-[11px] font-monospace font-semibold leading-[1.4] cursor-pointer outline-none transition-all duration-150 whitespace-nowrap flex items-center h-full",
599+
searchState.matchCase
600+
? "bg-review-bg-blue text-accent-light shadow-[inset_0_0_0_1px_rgba(77,184,255,0.4)] hover:bg-review-bg-info hover:text-accent-light"
601+
: "bg-transparent text-subtle hover:bg-separator hover:text-foreground",
602+
"active:translate-y-px"
603+
)}
604+
onClick={() =>
605+
setSearchState({ ...searchState, matchCase: !searchState.matchCase })
606+
}
607+
>
608+
Aa
609+
</button>
610+
<Tooltip position="bottom">
611+
{searchState.matchCase
612+
? "Match case (case-sensitive)"
613+
: "Ignore case (case-insensitive)"}
614+
</Tooltip>
615+
</TooltipWrapper>
616+
</div>
617+
</div>
565618

566-
<div className="border-border-light bg-separator border-b px-3 py-2">
567-
<div className="border-border-light bg-dark hover:border-border-gray focus-within:border-accent focus-within:hover:border-accent flex items-stretch overflow-hidden rounded border transition-[border-color] duration-150">
568-
<input
569-
ref={searchInputRef}
570-
type="text"
571-
placeholder={`Search in files and hunks... (${formatKeybind(KEYBINDS.FOCUS_REVIEW_SEARCH)})`}
572-
value={searchState.input}
573-
onChange={(e) => setSearchState({ ...searchState, input: e.target.value })}
574-
className="text-foreground placeholder:text-dim focus:bg-separator flex h-full flex-1 items-center border-none bg-transparent px-2.5 py-1.5 font-sans text-xs leading-[1.4] outline-none"
619+
{/* Single scrollable area containing both file tree and hunks */}
620+
<div className="flex min-h-0 flex-1 flex-col overflow-y-auto">
621+
{/* FileTree at the top */}
622+
{(fileTree ?? isLoadingTree) && (
623+
<div className="border-border-light flex w-full flex-[0_0_auto] flex-col overflow-hidden border-b">
624+
<FileTree
625+
root={fileTree}
626+
selectedPath={selectedFilePath}
627+
onSelectFile={setSelectedFilePath}
628+
isLoading={isLoadingTree}
629+
getFileReadStatus={getFileReadStatus}
630+
workspaceId={workspaceId}
575631
/>
576-
<TooltipWrapper inline>
577-
<button
578-
className={cn(
579-
"py-1.5 px-2.5 border-none border-l border-light text-[11px] font-monospace font-semibold leading-[1.4] cursor-pointer outline-none transition-all duration-150 whitespace-nowrap flex items-center h-full",
580-
searchState.useRegex
581-
? "bg-review-bg-blue text-accent-light shadow-[inset_0_0_0_1px_rgba(77,184,255,0.4)] hover:bg-review-bg-info hover:text-accent-light"
582-
: "bg-transparent text-subtle hover:bg-separator hover:text-foreground",
583-
"active:translate-y-px"
584-
)}
585-
onClick={() =>
586-
setSearchState({ ...searchState, useRegex: !searchState.useRegex })
587-
}
588-
>
589-
.*
590-
</button>
591-
<Tooltip position="bottom">
592-
{searchState.useRegex ? "Using regex search" : "Using substring search"}
593-
</Tooltip>
594-
</TooltipWrapper>
595-
<TooltipWrapper inline>
596-
<button
597-
className={cn(
598-
"py-1.5 px-2.5 border-none border-l border-light text-[11px] font-monospace font-semibold leading-[1.4] cursor-pointer outline-none transition-all duration-150 whitespace-nowrap flex items-center h-full",
599-
searchState.matchCase
600-
? "bg-review-bg-blue text-accent-light shadow-[inset_0_0_0_1px_rgba(77,184,255,0.4)] hover:bg-review-bg-info hover:text-accent-light"
601-
: "bg-transparent text-subtle hover:bg-separator hover:text-foreground",
602-
"active:translate-y-px"
603-
)}
604-
onClick={() =>
605-
setSearchState({ ...searchState, matchCase: !searchState.matchCase })
606-
}
607-
>
608-
Aa
609-
</button>
610-
<Tooltip position="bottom">
611-
{searchState.matchCase
612-
? "Match case (case-sensitive)"
613-
: "Ignore case (case-insensitive)"}
614-
</Tooltip>
615-
</TooltipWrapper>
616632
</div>
617-
</div>
633+
)}
618634

619-
<div className="min-h-0 flex-1 overflow-y-auto p-3">
635+
{/* Hunks below the file tree */}
636+
<div className="flex flex-[0_0_auto] flex-col p-3">
620637
{hunks.length === 0 ? (
621638
<div className="text-muted flex flex-col items-center justify-start gap-3 px-6 pt-12 pb-6 text-center">
622639
<div className="text-foreground text-base font-medium">No changes found</div>
@@ -691,20 +708,6 @@ export const ReviewPanel: React.FC<ReviewPanelProps> = ({
691708
)}
692709
</div>
693710
</div>
694-
695-
{/* FileTree positioning handled by CSS order property */}
696-
{(fileTree ?? isLoadingTree) && (
697-
<div className="border-border-light @[800px]:border-border-light order-2 flex min-h-0 w-80 shrink-0 flex-col overflow-hidden border-l @[800px]:order-0 @[800px]:h-auto @[800px]:w-full @[800px]:flex-[0_0_auto] @[800px]:border-b @[800px]:border-l-0">
698-
<FileTree
699-
root={fileTree}
700-
selectedPath={selectedFilePath}
701-
onSelectFile={setSelectedFilePath}
702-
isLoading={isLoadingTree}
703-
getFileReadStatus={getFileReadStatus}
704-
workspaceId={workspaceId}
705-
/>
706-
</div>
707-
)}
708711
</div>
709712
)}
710713
</div>

0 commit comments

Comments
 (0)