News stream POC

by phloe

HTML

<header><h1>
Seneste nyt
</h1></header>
<main>
  <section>
    <ol>
      <li>A</li>
      <li>B</li>
      <li>C</li>
      <li>D</li>
      <li>E</li>
      <li>F</li>
      <li>G</li>
      <li>H</li>
      <li>I</li>
      <li>J</li>
      <li>K</li>
      <li>L</li>
      <li>M</li>
      <li>N</li>
      <li>O</li>
      <li>P</li>
      <li>Q</li>
      <li>R</li>
      <li>S</li>
    </ol>
  </section>
  <div class="content">
    <article>
      <header>A</header>
      <p>
      Vestibulum pharetra, nibh ac tincidunt porta, odio est molestie justo, non placerat metus libero vel erat. Quisque scelerisque quis ex in tincidunt. In euismod, dolor eu semper condimentum, velit mauris ultrices ex, eu luctus libero orci ac magna. In nec gravida odio. Mauris sodales ultrices nunc sit amet accumsan. Proin facilisis eu est in pellentesque. Sed et nunc sed urna placerat posuere sagittis a purus. Sed et ante at odio consectetur fringilla. Praesent vitae nisl orci. Nunc nec blandit lacus. Aliquam scelerisque leo ut arcu tristique, eu dictum mauris volutpat. Maecenas sit amet eleifend dolor, quis sollicitudin purus. Praesent lacinia enim vitae urna convallis ornare. Etiam eleifend iaculis nulla vitae feugiat. Sed dignissim augue et risus posuere finibus.
</p> <p>
Mauris tristique porttitor libero, ut interdum lectus luctus sit amet. Nam ex risus, dignissim quis nunc sit amet, imperdiet maximus purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam volutpat tristique semper. Aliquam erat volutpat. Vestibulum tempor, lacus efficitur scelerisque varius, lectus ipsum mattis odio, nec consectetur ante mauris a augue. Nullam dignissim ex tellus, non porttitor lectus blandit quis. Sed in neque dapibus, volutpat sem a, faucibus enim. Quisque eget nunc nisl. Cras eget fermentum ante. Phasellus vel cursus nibh. Quisque iaculis erat ut condimentum vehicula. Curabitur vestibulum, purus ac ultrices finibus, dolor nibh pharetra lectus, vel lacinia mauris purus eu...

CSS

html {
  
  overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scroll-behavior: smooth;
	scroll-snap-type: x mandatory;
}

body {
  margin: 0;
}

main {
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 200vw;
  
}
@media (min-width: 35rem) {
  main {
    grid-template-columns: 20rem 1fr;
    width: auto;
  }
}
ol {
  margin: 0;
  padding: 0.5rem;
}
ol li {
  list-style: none;
  color: #FFF;
  background-color: lightgrey;
  padding: 1.5rem;
  margin: 0;
  position: relative;
  width: calc(100% - 4rem);
  scroll-snap-align: start;
	scroll-snap-stop: always;
  scroll-margin: 0.5rem;
}

.selected {
  background-color: grey;
  --dot-color: red;
}

ol li::before {
  content: "";
  display: block;
  position: absolute;
  top: calc(50% - 0.25rem);
  right: -1rem;
  padding: 0.25rem;
  border-radius: 50%;
  background-color: var(--dot-color, grey);
}
ol li + li {
  margin-top: 0.5rem;
}

ol li::after {
  content: "";
  display: block;
  position: absolute;
  top: calc(50%);
  right: -0.75rem;
  width: 0.0625rem;
  transform: translateX(0.03125rem);
  height: 5rem;
  border-radius: 50%;
  background-color: grey;
  z-index: -1;
}

.content {
  padding: 0.5rem 0.5rem 0.5rem 0;
}

article {
  position: -webkit-sticky;
  position: sticky;
  top: 0.5rem;
  color: #FFF;
  background-color: grey;
  padding: 1.5rem;
  max-height: calc(100vh - 4rem);
  overflow-y: auto;
  scroll-padding: 1.5rem;
  scroll-margin: 0.5rem;
  scroll-snap-align: start;
	scroll-snap-stop: always;
}

JavaScript

let selected = null;
let article = document.querySelector("article");
let articleHeader = article.querySelector("header");
function selectItem(item) {
	if (selected !== item) {
    if (selected) {
			selected.classList.remove("selected");
      selected = null;
    }
    if (item) {
    	selected = item;
			selected.classList.add("selected");
      articleHeader.innerHTML = selected.innerHTML;
      // article.scrollIntoView();
      const { top, left } = article.getBoundingClientRect();
      console.log("scroll", left - 8);
      window.scrollTo({
        left: left - 8,
        behavior: 'smooth'
      });
     	
    } else {
      articleHeader.innerHTML = '';
    }
  }
}
[...document.querySelectorAll("li")].forEach((li) => {
	li.addEventListener("click", () => {
  	selectItem(li);
  });
});