Skip to content

Commit 305e4bd

Browse files
committed
fix: stabilize extras action rail alignment across environments
1 parent 67c9a95 commit 305e4bd

1 file changed

Lines changed: 64 additions & 16 deletions

File tree

web/sidebar_tabs/rookieui_extras_pane.js

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,37 @@ export function buildExtrasPane(parent, bootstrapState, formRegistry, context) {
186186
createField(optionsGrid, "Face Restoration", elements.faceRestoration);
187187
createField(optionsGrid, "CodeFormer Weight", elements.codeformerWeight);
188188

189-
const actionRail = document.createElement("div");
190-
actionRail.className = "rookieui-shell__action-rail rookieui-shell__action-rail--extras";
191-
rightColumn.appendChild(actionRail);
189+
const actionRail = document.createElement("div");
190+
actionRail.className = "rookieui-shell__action-rail rookieui-shell__action-rail--extras";
191+
rightColumn.appendChild(actionRail);
192+
193+
let extrasRailAlignRafToken = null;
194+
const resolveActiveExtrasPane = () => (state.mode === "batch_process" ? batchPane : singlePane);
195+
const syncExtrasActionRailAlignment = () => {
196+
const ownerPane = section.closest(".rookieui-shell__pane");
197+
if (ownerPane?.hidden) {
198+
return;
199+
}
200+
const activePaneRect = resolveActiveExtrasPane().getBoundingClientRect();
201+
const actionRailRect = actionRail.getBoundingClientRect();
202+
const currentMarginTop = Number.parseFloat(globalThis.getComputedStyle?.(actionRail)?.marginTop ?? "0") || 0;
203+
const marginTop = Math.max(0, Math.round(currentMarginTop + (activePaneRect.top - actionRailRect.top)));
204+
// CRITICAL: keep Extras rail alignment dynamic; fixed offsets drift across Linux/Windows font metrics and cause flaky E2E top-delta checks.
205+
actionRail.style.marginTop = `${marginTop}px`;
206+
};
207+
const queueExtrasActionRailAlignment = () => {
208+
if (extrasRailAlignRafToken !== null && typeof globalThis.cancelAnimationFrame === "function") {
209+
globalThis.cancelAnimationFrame(extrasRailAlignRafToken);
210+
}
211+
if (typeof globalThis.requestAnimationFrame === "function") {
212+
extrasRailAlignRafToken = globalThis.requestAnimationFrame(() => {
213+
extrasRailAlignRafToken = null;
214+
syncExtrasActionRailAlignment();
215+
});
216+
return;
217+
}
218+
syncExtrasActionRailAlignment();
219+
};
192220

193221
const submitButton = document.createElement("button");
194222
submitButton.id = "rookieui-extras-submit";
@@ -349,15 +377,31 @@ export function buildExtrasPane(parent, bootstrapState, formRegistry, context) {
349377
}
350378
});
351379

352-
singleButton.addEventListener("click", () => {
353-
state.mode = "single_image";
354-
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
355-
});
356-
batchButton.addEventListener("click", () => {
357-
state.mode = "batch_process";
358-
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
359-
});
360-
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
380+
singleButton.addEventListener("click", () => {
381+
state.mode = "single_image";
382+
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
383+
syncExtrasActionRailAlignment();
384+
queueExtrasActionRailAlignment();
385+
});
386+
batchButton.addEventListener("click", () => {
387+
state.mode = "batch_process";
388+
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
389+
syncExtrasActionRailAlignment();
390+
queueExtrasActionRailAlignment();
391+
});
392+
syncExtrasMode([singleButton, batchButton], [singlePane, batchPane], state.mode);
393+
queueExtrasActionRailAlignment();
394+
395+
if (typeof ResizeObserver === "function") {
396+
const extrasAlignObserver = new ResizeObserver(() => {
397+
queueExtrasActionRailAlignment();
398+
});
399+
extrasAlignObserver.observe(modeTabs);
400+
extrasAlignObserver.observe(singlePane);
401+
extrasAlignObserver.observe(batchPane);
402+
section.__extrasAlignObserver = extrasAlignObserver;
403+
}
404+
globalThis.addEventListener?.("resize", queueExtrasActionRailAlignment);
361405

362406
let extrasModeSnapshot = state.mode;
363407
const extrasStateLock = installPaneStateLock(formRegistry, "extras", elements, () => {
@@ -379,8 +423,12 @@ export function buildExtrasPane(parent, bootstrapState, formRegistry, context) {
379423
captureExtrasState();
380424
});
381425

382-
return {
383-
onActivate: restoreExtrasState,
384-
onDeactivate: captureExtrasState,
385-
};
426+
return {
427+
onActivate: () => {
428+
restoreExtrasState();
429+
syncExtrasActionRailAlignment();
430+
queueExtrasActionRailAlignment();
431+
},
432+
onDeactivate: captureExtrasState,
433+
};
386434
}

0 commit comments

Comments
 (0)