fix(home): remove black flash between tab switches
All checks were successful
Deploy / deploy (push) Successful in 2m40s

- AnimatePresence mode=wait keeps the DOM empty while the outgoing tab
  finishes its exit transition (200ms) before mounting the incoming
  tab. On touch devices this shows as a brief black frame — reported
  as экран остается черным.
- Switch to mode=sync: outgoing fades out while incoming fades in,
  no gap. initial=false suppresses the enter animation on first render.
- Drop the y: 12 → -8 slide (cheap jank on hydration), keep just
  opacity. Duration 200ms → 150ms for snappier feel.
This commit is contained in:
Cosmo
2026-04-23 09:22:55 +00:00
parent 8d32e7ebb0
commit dc5c9b3673

View File

@@ -960,9 +960,9 @@ function SettingsTab({ city, onCityChange, onLogout, theme, onThemeChange }: { c
// ————— Tab animation variants —————
const tabVariants = {
enter: { opacity: 0, y: 12 },
center: { opacity: 1, y: 0 },
exit: { opacity: 0, y: -8 },
enter: { opacity: 0 },
center: { opacity: 1 },
exit: { opacity: 0 },
}
// ————— Main —————
@@ -1125,15 +1125,15 @@ function HomePageInner() {
<main style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minWidth: 0, position: 'relative', zIndex: 1 }}>
<TopBar sensors={sensors} haConnected={haConnected} />
<AnimatePresence mode="wait">
<AnimatePresence mode="sync" initial={false}>
{tab === 'home' && (
<motion.div key="home" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.2 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<motion.div key="home" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.15 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<HomeTab weather={weather} sensors={sensors} />
</motion.div>
)}
{tab === 'devices' && (
<motion.div key="devices" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.2 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<motion.div key="devices" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.15 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<RoomTabs rooms={ROOMS} active={activeRoom} onChange={setActiveRoom} />
<div style={{ flex: 1, overflowY: 'auto', WebkitOverflowScrolling: 'touch' as any, padding: '16px 24px 28px' }}>
{devicesInRoom.length === 0 ? (
@@ -1153,19 +1153,19 @@ function HomePageInner() {
)}
{tab === 'calendar' && (
<motion.div key="calendar" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.2 }} style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
<motion.div key="calendar" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.15 }} style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
<CalendarTab />
</motion.div>
)}
{tab === 'notes' && (
<motion.div key="notes" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.2 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<motion.div key="notes" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.15 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<NotesTab />
</motion.div>
)}
{tab === 'settings' && (
<motion.div key="settings" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.2 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<motion.div key="settings" variants={tabVariants} initial="enter" animate="center" exit="exit" transition={{ duration: 0.15 }} style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
<SettingsTab city={city} onCityChange={handleCityChange} onLogout={handleLogout} theme={theme} onThemeChange={setTheme} />
</motion.div>
)}