List Scroll Jump
by Christian Micle
HTML
<div id="app"></div>
CSS
:root {
scroll-behavior: smooth;
}
* {
box-sizing: border-box;
}
html,
body,
#app {
padding: 0;
margin: 0;
background-color: white;
height: 100%;
}
.list {
height: 100%;
overflow: auto;
box-sizing: border-box;
overflow-anchor: none;
}
React
function chooseColor(index) {
const v = index % 10;
if (v === 0) {
return 'purple';
}
if (v === 1) {
return 'orange';
}
if (v === 2) {
return 'green';
}
if (v === 3) {
return 'yellow';
}
if (v === 4) {
return 'magenta';
}
if (v === 5) {
return 'red';
}
if (v === 6) {
return 'black';
}
if (v === 7) {
return 'brown';
}
if (v === 8) {
return 'pink';
}
return 'cyan';
}
function List() {
const listRef = React.useRef();
const itemsRef = React.useRef();
const itemsRemoved = React.useRef(false);
const shiftInfoRef = React.useRef(null);
const [itemsMeta, setItemsMeta] = React.useState({ from: { year: 1974, month: 3 }, to: { year: 1991, month: 8 }});
const items = React.useMemo(() => {
const builder = [];
let startingMonth = itemsMeta.from.month;
let endingMonth = 12;
for (let yearCounter = itemsMeta.from.year; yearCounter <= itemsMeta.to.year; yearCounter += 1) {
if (yearCounter === itemsMeta.to.year) {
endingMonth = itemsMeta.to.month;
}
for (let monthCounter = startingMonth; monthCounter <= endingMonth; monthCounter += 1) {
startingMonth = 1;
const color = chooseColor(yearCounter);
const text = yearCounter + ':' + monthCounter;
builder.push(<div key={yearCounter * 12 + monthCounter}style={{color: 'white', fontSize: 48, margin: 20, backgroundColor: color}}>{text}</div>);
}
}
return builder;
}, [ itemsMeta ]);
const handleScroll = React.useCallback(() => {
const scrollOn = 140;
const targetChild = itemsRef.current.childNodes[scrollOn];
const item = itemsRef.current.childNodes[scrollOn + 1];
const childRect = targetChild.getBoundingClientRect();
...