mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-21 02:06:00 +00:00
feat(app): review panel reactivity improvements (#37089)
This commit is contained in:
@@ -551,7 +551,7 @@ export function SessionSidePanel(props: {
|
||||
>
|
||||
<Show when={props.reviewSidebarToggle}>
|
||||
{(toggle) => (
|
||||
<div class="h-full shrink-0 flex items-center justify-center">
|
||||
<div class="session-review-v2-sidebar-toggle-slot h-full shrink-0 sticky left-0 z-10 flex items-center justify-center bg-v2-background-bg-base">
|
||||
{toggle()(activeTab() === SESSION_OPEN_FILE_TAB)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -263,7 +263,9 @@ export function SessionReviewFilePreviewV2(props: SessionReviewFilePreviewV2Prop
|
||||
<span data-slot="session-review-v2-file-path">{getDirectory(props.file)}</span>
|
||||
</Show>
|
||||
</div>
|
||||
<DiffChanges changes={view()} />
|
||||
<div data-slot="session-review-v2-file-diff">
|
||||
<DiffChanges changes={view()} />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
ref={(el) => {
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
padding: 10px 12px;
|
||||
padding-left: 8px;
|
||||
flex-shrink: 0;
|
||||
border-bottom: 1px solid var(--border-weaker-base, var(--v2-border-border-weak));
|
||||
@@ -273,9 +273,37 @@
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
[data-component="session-review-v2"] [data-slot="session-review-v2-file-header"] [data-component="diff-changes"] {
|
||||
[data-component="session-review-v2"] [data-slot="session-review-v2-file-diff"] {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
background-color: var(--v2-background-bg-base);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
bottom: -8px;
|
||||
right: 100%;
|
||||
width: 16px;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(90deg, transparent, var(--v2-background-bg-base));
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -8px -16px -8px 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
background-color: var(--v2-background-bg-base);
|
||||
}
|
||||
|
||||
[data-component="diff-changes"] {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-review-v2"] [data-slot="session-review-v2-file-status"] {
|
||||
|
||||
@@ -139,6 +139,7 @@ export function SessionReviewV2Sidebar(props: SessionReviewV2SidebarProps) {
|
||||
min={minWidth()}
|
||||
max={maxWidth()}
|
||||
onResize={(next) => props.onWidthChange?.(next)}
|
||||
onDblClick={() => props.onWidthChange?.(SESSION_REVIEW_V2_SIDEBAR_WIDTH_DEFAULT)}
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
@@ -8,6 +8,8 @@ export interface ResizeHandleProps extends Omit<JSX.HTMLAttributes<HTMLDivElemen
|
||||
max: number
|
||||
onResize: (size: number) => void
|
||||
onCollapse?: () => void
|
||||
/** Called while dragging when size crosses `collapseThreshold`. */
|
||||
onCollapseChange?: (collapsed: boolean) => void
|
||||
collapseThreshold?: number
|
||||
}
|
||||
|
||||
@@ -20,17 +22,26 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
||||
"max",
|
||||
"onResize",
|
||||
"onCollapse",
|
||||
"onCollapseChange",
|
||||
"collapseThreshold",
|
||||
"class",
|
||||
"classList",
|
||||
])
|
||||
|
||||
const handleMouseDown = (e: MouseEvent) => {
|
||||
if (e.detail > 1) return
|
||||
e.preventDefault()
|
||||
const edge = local.edge ?? (local.direction === "vertical" ? "start" : "end")
|
||||
const start = local.direction === "horizontal" ? e.clientX : e.clientY
|
||||
const startSize = local.size
|
||||
const min = local.min
|
||||
const max = local.max
|
||||
const threshold = local.collapseThreshold ?? 0
|
||||
const onResize = local.onResize
|
||||
const onCollapse = local.onCollapse
|
||||
const onCollapseChange = local.onCollapseChange
|
||||
let current = startSize
|
||||
let collapsed = false
|
||||
|
||||
document.body.style.userSelect = "none"
|
||||
document.body.style.overflow = "hidden"
|
||||
@@ -46,8 +57,12 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
||||
? start - pos
|
||||
: pos - start
|
||||
current = startSize + delta
|
||||
const clamped = Math.min(local.max, Math.max(local.min, current))
|
||||
local.onResize(clamped)
|
||||
const nextCollapsed = threshold > 0 && current < threshold
|
||||
if (nextCollapsed !== collapsed) {
|
||||
collapsed = nextCollapsed
|
||||
onCollapseChange?.(collapsed)
|
||||
}
|
||||
onResize(Math.min(max, Math.max(min, current)))
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
@@ -56,10 +71,11 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
||||
document.removeEventListener("mousemove", onMouseMove)
|
||||
document.removeEventListener("mouseup", onMouseUp)
|
||||
|
||||
const threshold = local.collapseThreshold ?? 0
|
||||
if (local.onCollapse && threshold > 0 && current < threshold) {
|
||||
local.onCollapse()
|
||||
if (collapsed) {
|
||||
onCollapse?.()
|
||||
return
|
||||
}
|
||||
onCollapseChange?.(false)
|
||||
}
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove)
|
||||
|
||||
@@ -793,6 +793,62 @@ body[data-new-layout]
|
||||
[data-slot="tabs-list"]
|
||||
> .sticky {
|
||||
padding-right: 0;
|
||||
|
||||
[data-component="icon-button-v2"] {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 20px;
|
||||
height: 28px;
|
||||
background-color: var(--v2-background-bg-base);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body[data-new-layout]
|
||||
#review-panel
|
||||
[data-component="tabs"]
|
||||
.session-review-v2-tabs-bar
|
||||
[data-slot="tabs-list"]
|
||||
> .session-review-v2-sidebar-toggle-slot.sticky {
|
||||
padding-right: 0;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
right: 100%;
|
||||
transform: translateY(-50%);
|
||||
width: 12px;
|
||||
height: 28px;
|
||||
background-color: var(--v2-background-bg-base);
|
||||
background-image: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 100%;
|
||||
transform: translateY(-50%);
|
||||
width: 8px;
|
||||
height: 28px;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(90deg, var(--v2-background-bg-base), transparent);
|
||||
}
|
||||
|
||||
[data-component="icon-button-v2"]::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
body[data-new-layout] #review-panel [data-component="tabs"] .session-review-v2-open-in-app-slot {
|
||||
|
||||
Reference in New Issue
Block a user