fix(app): suppress review sidebar hydration motion (#36847)
This commit is contained in:
@@ -9,7 +9,7 @@ import { createStore } from "solid-js/store"
|
|||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
|
|
||||||
export function createReviewPanelV2State() {
|
export function createReviewPanelV2State() {
|
||||||
const [store, setStore] = persisted(
|
const [store, setStore, , ready] = persisted(
|
||||||
Persist.global("review-panel-v2"),
|
Persist.global("review-panel-v2"),
|
||||||
createStore({
|
createStore({
|
||||||
sidebarOpened: true,
|
sidebarOpened: true,
|
||||||
@@ -24,6 +24,7 @@ export function createReviewPanelV2State() {
|
|||||||
return {
|
return {
|
||||||
sidebarOpened: () => store.sidebarOpened,
|
sidebarOpened: () => store.sidebarOpened,
|
||||||
sidebarWidth: () => store.sidebarWidth,
|
sidebarWidth: () => store.sidebarWidth,
|
||||||
|
sidebarTransition: ready,
|
||||||
filter,
|
filter,
|
||||||
setFilter,
|
setFilter,
|
||||||
expandMode: () => store.expandMode,
|
expandMode: () => store.expandMode,
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ function ReviewPanelV2Sidebar(props: {
|
|||||||
return (
|
return (
|
||||||
<SessionReviewV2Sidebar
|
<SessionReviewV2Sidebar
|
||||||
open={props.state.sidebarOpened()}
|
open={props.state.sidebarOpened()}
|
||||||
|
transition={props.state.sidebarTransition()}
|
||||||
title={props.title}
|
title={props.title}
|
||||||
stats={<DiffChanges changes={props.diffs()} />}
|
stats={<DiffChanges changes={props.diffs()} />}
|
||||||
filter={props.state.filter()}
|
filter={props.state.filter()}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const emptyFiles: string[] = []
|
|||||||
export type SessionFileBrowserState = {
|
export type SessionFileBrowserState = {
|
||||||
sidebarOpened: () => boolean
|
sidebarOpened: () => boolean
|
||||||
sidebarWidth: () => number
|
sidebarWidth: () => number
|
||||||
|
sidebarTransition: () => boolean
|
||||||
resizeSidebar: (width: number) => void
|
resizeSidebar: (width: number) => void
|
||||||
toggleSidebar: () => void
|
toggleSidebar: () => void
|
||||||
}
|
}
|
||||||
@@ -96,6 +97,7 @@ export function SessionFileBrowserTab(props: {
|
|||||||
sidebar={
|
sidebar={
|
||||||
<SessionReviewV2Sidebar
|
<SessionReviewV2Sidebar
|
||||||
open={sidebarOpened()}
|
open={sidebarOpened()}
|
||||||
|
transition={props.state.sidebarTransition()}
|
||||||
title={<span class="truncate">{title()}</span>}
|
title={<span class="truncate">{title()}</span>}
|
||||||
filter={filter()}
|
filter={filter()}
|
||||||
onFilterChange={setFilter}
|
onFilterChange={setFilter}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import { beforeAll, expect, mock, test } from "bun:test"
|
||||||
|
import type { AsyncStorage } from "@solid-primitives/storage"
|
||||||
|
import { createEffect, createRoot } from "solid-js"
|
||||||
|
|
||||||
|
let createReviewPanelV2State: typeof import("@/pages/session/v2/review-panel-v2-state").createReviewPanelV2State
|
||||||
|
let read: ((value: string | null) => void) | undefined
|
||||||
|
|
||||||
|
const storage: AsyncStorage = {
|
||||||
|
getItem: () => new Promise((resolve) => (read = resolve)),
|
||||||
|
setItem: async () => undefined,
|
||||||
|
removeItem: async () => undefined,
|
||||||
|
clear: async () => undefined,
|
||||||
|
key: async () => null,
|
||||||
|
getLength: async () => 0,
|
||||||
|
length: Promise.resolve(0),
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
mock.module("@opencode-ai/session-ui/v2/session-review-v2", () => ({
|
||||||
|
SESSION_REVIEW_V2_SIDEBAR_WIDTH_DEFAULT: 240,
|
||||||
|
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MIN: 200,
|
||||||
|
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MAX: 480,
|
||||||
|
}))
|
||||||
|
mock.module("@/context/platform", () => ({
|
||||||
|
usePlatform: () => ({ platform: "desktop", storage: () => storage }),
|
||||||
|
}))
|
||||||
|
|
||||||
|
createReviewPanelV2State = (await import("@/pages/session/v2/review-panel-v2-state")).createReviewPanelV2State
|
||||||
|
})
|
||||||
|
|
||||||
|
test("enables sidebar motion only after custom width hydration", async () => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
createRoot((dispose) => {
|
||||||
|
const state = createReviewPanelV2State()
|
||||||
|
const transition =
|
||||||
|
"sidebarTransition" in state && typeof state.sidebarTransition === "function"
|
||||||
|
? (state.sidebarTransition as () => boolean)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
expect(transition).toBeFunction()
|
||||||
|
expect(transition?.()).toBeFalse()
|
||||||
|
expect(state.sidebarWidth()).toBe(240)
|
||||||
|
} catch (error) {
|
||||||
|
dispose()
|
||||||
|
reject(error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
createEffect(() => {
|
||||||
|
if (!transition?.()) return
|
||||||
|
try {
|
||||||
|
expect(state.sidebarWidth()).toBe(360)
|
||||||
|
dispose()
|
||||||
|
resolve()
|
||||||
|
} catch (error) {
|
||||||
|
dispose()
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
read?.(JSON.stringify({ sidebarOpened: true, sidebarWidth: 360, expandMode: "collapse" }))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -38,7 +38,8 @@
|
|||||||
border-right-width: 0;
|
border-right-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar"]:not([data-resizing]) {
|
[data-component="session-review-v2-sidebar-root"]
|
||||||
|
[data-slot="session-review-v2-sidebar"][data-transition]:not([data-resizing]) {
|
||||||
transition:
|
transition:
|
||||||
width 200ms cubic-bezier(0.22, 1, 0.36, 1),
|
width 200ms cubic-bezier(0.22, 1, 0.36, 1),
|
||||||
border-right-width 200ms cubic-bezier(0.22, 1, 0.36, 1);
|
border-right-width 200ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export type SessionReviewV2Props = {
|
|||||||
|
|
||||||
export type SessionReviewV2SidebarProps = {
|
export type SessionReviewV2SidebarProps = {
|
||||||
open: boolean
|
open: boolean
|
||||||
|
transition: boolean
|
||||||
title?: JSX.Element
|
title?: JSX.Element
|
||||||
stats?: JSX.Element
|
stats?: JSX.Element
|
||||||
filter: string
|
filter: string
|
||||||
@@ -76,6 +77,7 @@ export function SessionReviewV2Sidebar(props: SessionReviewV2SidebarProps) {
|
|||||||
<Show when={props.open}>
|
<Show when={props.open}>
|
||||||
<aside
|
<aside
|
||||||
data-slot="session-review-v2-sidebar"
|
data-slot="session-review-v2-sidebar"
|
||||||
|
data-transition={props.transition ? "" : undefined}
|
||||||
data-resizing={resizing() ? "" : undefined}
|
data-resizing={resizing() ? "" : undefined}
|
||||||
style={{ width: `${width()}px` }}
|
style={{ width: `${width()}px` }}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user