🐛 fix(electron): align TabBar left padding with NavPanel width on initial load (#13981)

🐛 fix(electron): align TabBar left padding with NavPanel width on initial load

Defer DraggablePanel mount in NavPanelDraggable until `isStatusInit` flips true
so defaultSize captures the hydrated `leftPanelWidth` instead of the pre-hydration
default. Before hydration, render a placeholder div matching the store's current
width so NavigationBar's live-read width stays aligned with the DOM. Also adds
a small paddingRight to NavigationBar for visual balance.

Without this, the TabBar's left edge drifted away from the NavPanel's right edge
whenever the user's persisted panel width differed from the 320px default.
This commit is contained in:
Innei 2026-04-20 01:46:05 +08:00 committed by GitHub
parent 730169e6b6
commit 3bd7f1f146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 13 additions and 9 deletions

View file

@ -87,6 +87,7 @@ const NavigationBar = memo(() => {
data-width={leftPanelWidth}
justify="end"
style={{
paddingRight: 8,
width: isLeftPanelVisible ? `${leftPanelWidth - 12}px` : '150px',
transition: !isLeftPanelVisible ? 'width 0.2s' : 'none',
}}

View file

@ -106,24 +106,20 @@ const classNames = {
};
export const NavPanelDraggable = memo<NavPanelDraggableProps>(({ activeContent }) => {
const [expand, togglePanel] = useGlobalStore((s) => [
const [expand, togglePanel, isStatusInit] = useGlobalStore((s) => [
systemStatusSelectors.showLeftPanel(s),
s.toggleLeftPanel,
systemStatusSelectors.isStatusInit(s),
]);
const handleSizeChange = useNavPanelSizeChangeHandler();
// Defer DraggablePanel mount until system status hydrates; otherwise defaultSize
// captures the pre-hydration default and the DOM drifts off NavigationBar's live width.
const defaultWidthRef = useRef(0);
if (defaultWidthRef.current === 0) {
if (defaultWidthRef.current === 0 && isStatusInit) {
defaultWidthRef.current = systemStatusSelectors.leftPanelWidth(useGlobalStore.getState());
}
const defaultSize = useMemo(
() => ({
height: '100%',
width: defaultWidthRef.current,
}),
[],
);
const styles = useMemo(
() => ({
background: isDesktop && isMacOS() ? 'transparent' : cssVar.colorBgLayout,
@ -132,6 +128,13 @@ export const NavPanelDraggable = memo<NavPanelDraggableProps>(({ activeContent }
[],
);
if (defaultWidthRef.current === 0) {
const pendingWidth = systemStatusSelectors.leftPanelWidth(useGlobalStore.getState());
return <div aria-hidden style={{ flexShrink: 0, height: '100%', width: pendingWidth }} />;
}
const defaultSize = { height: '100%', width: defaultWidthRef.current };
return (
<DraggablePanel
className={draggableStyles.panel}