feat: Scroll-to-Top Button (erscheint ab 300px Scroll)

This commit is contained in:
2026-06-13 18:07:17 +02:00
parent 65707617dd
commit 7758487c9f

View File

@@ -3215,6 +3215,51 @@ function PublicUpload({ token }) {
);
}
// ── Scroll-to-Top Button ──────────────────────────────────────────────────
function ScrollToTop({ scrollRef }) {
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = scrollRef?.current;
if (!el) return;
const onScroll = () => setVisible(el.scrollTop > 300);
el.addEventListener('scroll', onScroll, { passive: true });
return () => el.removeEventListener('scroll', onScroll);
}, [scrollRef]);
if (!visible) return null;
return (
<button
onClick={() => scrollRef.current?.scrollTo({ top: 0, behavior: 'smooth' })}
style={{
position: 'fixed',
bottom: 'calc(70px + env(safe-area-inset-bottom, 0px))',
right: 20,
zIndex: 900,
width: 40,
height: 40,
borderRadius: '50%',
background: 'rgba(255,255,255,0.08)',
border: '1px solid rgba(255,255,255,0.15)',
backdropFilter: 'blur(8px)',
color: 'rgba(255,255,255,0.7)',
fontSize: 16,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow: '0 4px 16px rgba(0,0,0,0.4)',
transition: 'opacity 0.2s',
}}
title="Nach oben"
>
</button>
);
}
export default function App() {
// Öffentliche Upload-Seite kein Login, kein Auth
const _uploadMatch = window.location.pathname.match(/^\/u\/(.+)$/);
@@ -3303,6 +3348,7 @@ export default function App() {
if(!user) return <Login onLogin={u=>setUser(u)}/>;
const activeTool = TOOLS.find(t=>t.id===active);
const mainRef = useRef(null);
// Mobile padding bottom für fixed nav
const isNachrichten = active === 'nachrichten';
@@ -3331,7 +3377,7 @@ export default function App() {
unreadMsgs={unreadMsgs}/>
)}
<main style={mainStyle}>
<main ref={mainRef} style={mainStyle}>
{active==='dashboard' && <Dashboard toast={toast} mobile={mobile} setActive={setActive} setDevToolsNav={setDevToolsNav} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} user={user}/>}
{active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user} nav={devToolsNav}/>}
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'?{nav:devToolsNav}:{})}/>}
@@ -3343,6 +3389,7 @@ export default function App() {
unreadMsgs={unreadMsgs}/>
)}
<ScrollToTop scrollRef={mainRef}/>
<Toast msg={toastMsg.msg} type={toastMsg.type}/>
</>
);