mirror of
https://github.com/nexu-io/open-design.git
synced 2026-07-03 12:27:55 +08:00
feat(web): add product-wide UI animations (#3294)
* feat(web): add product-wide UI animations Add motion library (Framer Motion) for modal/toast/popover exit animations via AnimatePresence, and a comprehensive CSS entrance animation system (entrance.css) for all other UI surfaces. Motion is limited to low-frequency mount/unmount components (modals, toasts, popovers) to avoid re-render overhead. All high-frequency components (grids, lists, nav, inputs) use pure CSS @keyframes with staggered nth-child delays — zero JS cost. Covers: home hero sequence, card grids, design kanban, marketplace, settings, memory panels, MCP picker, inspector/comment slide-in, chat history, file viewer, connector drawer, error banners, agent cards, automation history, skill rows, breadcrumbs, workspace tabs, staged attachments, code viewer, and button press feedback. Respects prefers-reduced-motion system preference. * fix(web): prevent thumbnail flash on tab switch Replace individual card/row stagger animations (opacity 0→1 per child) with container-level fades. The child animations replayed on every React remount when switching tabs, causing all preview thumbnails to flash from invisible. Now only containers animate (fast fade-in), individual items inside grids/lists stay fully visible immediately. * fix: remove fade animations from tab-switchable content to prevent flash on remount Grids, tab panels, entry sections, viewer panels, and other content that remounts on tab switch no longer start from opacity:0. Only true one-time mounts (page load, home hero), overlays/popovers, slide-in panels, and error banners retain entrance animations. * fix: keep tab content mounted with display:none to prevent thumbnail reload on tab switch Projects, Tasks, Plugins, and Design Systems tabs now stay mounted in the DOM when inactive, hidden via display:none. This preserves loaded images and prevents the visible flash caused by thumbnails re-fetching on every tab switch. Home and Integrations tabs keep conditional rendering since they have no persistent media to preserve. * fix: keep HomeView mounted to preserve recent project thumbnails on tab switch * perf: use content-visibility:hidden for inactive tabs + add card press feedback Replace display:none with content-visibility:hidden so the browser skips rendering computation for hidden tabs while preserving the full DOM tree. Add :active scale(0.98) press feedback to design-card, plugins-home__card, and recent-projects__card for tactile click response. * fix: pin dependency versions to exact (no caret ranges) * chore: update lockfile for pinned dependency versions * fix: replace PreviewModal motion with CSS animation, add motion test mock - PreviewModal no longer uses motion/react — prevents test failures from AnimatePresence exit animations never completing in test env - Add CSS animations for .ds-modal-backdrop (fade-in) and .ds-modal (scale-in) - Add vitest alias to mock motion/react so AnimatePresence in other components (UpdaterPopup, ExamplesTab) completes synchronously in tests * chore(nix): refresh pnpm deps hash * test(e2e): scope visual-home locators to their entry view The redesigned entry shell keeps every view mounted (only the active one is visible) so tab switches don't reload thumbnails. That makes testids like `plugins-home-section` and text like "Launchpad dashboard" exist in more than one view at once, breaking Playwright strict-mode locators. Tag each view container with `data-testid="entry-view-<name>"` and scope the affected visual specs to the relevant view so the locators stay unambiguous. * test(e2e): scope entry-chrome home starters locators to their view The redesigned entry shell keeps every view mounted (only the active one is visible), so `plugins-home-section` and its children render in both the home and plugins views at once, breaking Playwright strict-mode locators. Scope the home starters assertions in entry-chrome-flows to the `entry-view-home` container so the locators stay unambiguous, matching the existing visual-home spec fix. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) * fix(web): close a11y/reduced-motion/exit gaps in animation layer Address three review findings on the product-wide animation PR: - EntryShell kept every tab view mounted via content-visibility:hidden, but that only skips paint — inactive Home/Projects/Plugins subtrees stayed in the tab order and accessibility tree. Mark inactive view wrappers inert + aria-hidden so keyboard users and screen readers only see the active view while the cached DOM survives. - The motion/react variants animated unconditionally; the CSS prefers-reduced-motion block did not cover them. Wrap the app root in MotionConfig reducedMotion="user" so dialogs/toasts/popovers honor the OS preference, and add a focused regression test for the wiring. - NewProjectModal short-circuited with `if (!open) return null`, so its exit variants never ran. Render the body inside AnimatePresence gated on `open` so the close animation plays before unmount. Generated-By: looper 0.8.1 (runner=fixer, agent=claude-code) --------- Co-authored-by: qiongyu1999 <2694684348@qq.com> Co-authored-by: open-design-bot[bot] <282769551+open-design-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -10,5 +10,5 @@
|
||||
# 2. Run the relevant nix build/flake check
|
||||
# 3. Copy the expected hash printed by Nix into the matching field below
|
||||
daemonHash = "sha256-I2NzPscFPwgyocWyCUKfruqEAojzB6SuI4U/klrfdCI=";
|
||||
webHash = "sha256-FeCqszNQooPNx9zbKeJc30CYxfUanZ6pAO2FwnUI/Lk=";
|
||||
webHash = "sha256-HJElsw92u9Q0L22m8susnyRVtUnw/yfgnV98+NltmPg=";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user