upgrade
This commit is contained in:
77
frontend/src/main.tsx
Normal file
77
frontend/src/main.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
// Lightweight scroll-reveal setup for elements with `.section` or `[data-reveal]`.
|
||||
// Respects prefers-reduced-motion and observes dynamically added nodes.
|
||||
function setupReveal() {
|
||||
const w = window as unknown as { __revealSetupDone?: boolean }
|
||||
if (w.__revealSetupDone) return
|
||||
w.__revealSetupDone = true
|
||||
|
||||
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
const selector = '.section, [data-reveal]'
|
||||
|
||||
// If reduced motion is preferred, mark everything visible and skip observers
|
||||
if (prefersReduced) {
|
||||
document.querySelectorAll(selector).forEach((el) => el.classList.add('reveal-visible'))
|
||||
return
|
||||
}
|
||||
|
||||
const seen = new WeakSet<Element>()
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('reveal-visible')
|
||||
io.unobserve(entry.target)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ threshold: 0.12, rootMargin: '0px 0px -10% 0px' },
|
||||
)
|
||||
|
||||
const observeExisting = () => {
|
||||
document.querySelectorAll(selector).forEach((el) => {
|
||||
if (!seen.has(el)) {
|
||||
seen.add(el)
|
||||
io.observe(el)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Observe current DOM
|
||||
observeExisting()
|
||||
|
||||
// Observe future DOM mutations (e.g., route changes render new sections)
|
||||
const mo = new MutationObserver((mutations) => {
|
||||
let needsScan = false
|
||||
for (const m of mutations) {
|
||||
if (m.type === 'childList' && (m.addedNodes?.length ?? 0) > 0) {
|
||||
needsScan = true
|
||||
}
|
||||
if (needsScan) break
|
||||
}
|
||||
if (needsScan) observeExisting()
|
||||
})
|
||||
mo.observe(document.documentElement, { childList: true, subtree: true })
|
||||
|
||||
// Cleanup on HMR disposal (Vite dev) to avoid duplicate observers
|
||||
if (import.meta && import.meta.hot) {
|
||||
import.meta.hot.dispose(() => {
|
||||
io.disconnect()
|
||||
mo.disconnect()
|
||||
w.__revealSetupDone = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize after first render tick
|
||||
queueMicrotask(setupReveal)
|
||||
Reference in New Issue
Block a user