feat: Scroll-to-Top Button (erscheint ab 300px Scroll)
This commit is contained in:
@@ -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() {
|
export default function App() {
|
||||||
// Öffentliche Upload-Seite – kein Login, kein Auth
|
// Öffentliche Upload-Seite – kein Login, kein Auth
|
||||||
const _uploadMatch = window.location.pathname.match(/^\/u\/(.+)$/);
|
const _uploadMatch = window.location.pathname.match(/^\/u\/(.+)$/);
|
||||||
@@ -3303,6 +3348,7 @@ export default function App() {
|
|||||||
if(!user) return <Login onLogin={u=>setUser(u)}/>;
|
if(!user) return <Login onLogin={u=>setUser(u)}/>;
|
||||||
|
|
||||||
const activeTool = TOOLS.find(t=>t.id===active);
|
const activeTool = TOOLS.find(t=>t.id===active);
|
||||||
|
const mainRef = useRef(null);
|
||||||
|
|
||||||
// Mobile padding bottom für fixed nav
|
// Mobile padding bottom für fixed nav
|
||||||
const isNachrichten = active === 'nachrichten';
|
const isNachrichten = active === 'nachrichten';
|
||||||
@@ -3331,7 +3377,7 @@ export default function App() {
|
|||||||
|
|
||||||
unreadMsgs={unreadMsgs}/>
|
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==='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}/>}
|
{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}:{})}/>}
|
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'?{nav:devToolsNav}:{})}/>}
|
||||||
@@ -3343,6 +3389,7 @@ export default function App() {
|
|||||||
|
|
||||||
unreadMsgs={unreadMsgs}/>
|
unreadMsgs={unreadMsgs}/>
|
||||||
)}
|
)}
|
||||||
|
<ScrollToTop scrollRef={mainRef}/>
|
||||||
<Toast msg={toastMsg.msg} type={toastMsg.type}/>
|
<Toast msg={toastMsg.msg} type={toastMsg.type}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user