Thanks to visit codestin.com
Credit goes to github.com

Skip to content

app/ui: skip sidebar transition animation on initial page load#14515

Open
umutkeltek wants to merge 1 commit intoollama:mainfrom
umutkeltek:fix/sidebar-animation-on-load
Open

app/ui: skip sidebar transition animation on initial page load#14515
umutkeltek wants to merge 1 commit intoollama:mainfrom
umutkeltek:fix/sidebar-animation-on-load

Conversation

@umutkeltek
Copy link

Problem

When the app loads with sidebarOpen persisted as true in settings, CSS transition classes cause the sidebar to visibly animate from closed → open. This happens because:

  1. useSettings() uses useQuery, so sidebarOpen initially defaults to false while the async settings fetch is in-flight
  2. When the query resolves with sidebarOpen: true, the sidebar width changes from w-0w-64
  3. All five transition classes (transition-[width], transition-[left], transition-opacity, transition-all) are applied unconditionally, so the browser animates this state change

The result is a slide-open animation every time the app loads — the sidebar should appear instantly in its saved state.

Solution

Defer CSS transition classes until after the first paint using a hasMounted state flag:

const [hasMounted, setHasMounted] = useState(false);

useEffect(() => {
  requestAnimationFrame(() => {
    setHasMounted(true);
  });
}, []);

All five transition class locations are conditionally applied:

className={`... ${hasMounted ? "transition-[width] duration-300" : ""} ...`}
  • Before mount: No transition classes → sidebar renders at its correct width instantly
  • After mount: Transition classes applied → sidebar toggle animates smoothly as before

Using requestAnimationFrame (instead of bare useEffect) ensures the transition suppression survives the full browser paint cycle, preventing any flash of animation even on slower renders.

Changes

  • app/ui/app/src/components/layout/layout.tsx — 1 file, +15/-5 lines
    • Added hasMounted state with useEffect + requestAnimationFrame
    • Conditionally applied all 5 transition classes only when hasMounted === true

Testing

  • TypeScript: tsc -b — zero errors
  • Vitest: 27/27 tests passing, zero regressions
  • Vite build: builds successfully
  • ESLint: passes
  • Prettier: passes

Behavior

Scenario Before After
App loads with sidebar open Sidebar animates open (slide from left) Sidebar appears instantly
User toggles sidebar after load Smooth animation Smooth animation (unchanged)
App loads with sidebar closed No animation (already closed) No animation (unchanged)

Fixes #12954

When the app loads with sidebarOpen persisted as true, CSS transitions
cause the sidebar to visibly animate from closed to open. This happens
because transition classes are applied unconditionally while settings
are still loading asynchronously via useQuery.

Defer transition classes until after the first frame via a hasMounted
state flag with requestAnimationFrame, so the sidebar renders in its
correct state instantly on load. Subsequent sidebar toggles still
animate smoothly.

Fixes ollama#12954
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app: sidebar animates opening on load instead of appearing open

1 participant