LISN.js

Edit on StackBlitz

"use client";
import {
  PagerComponent,
  PagerPageComponent,
  PagerSwitchComponent,
  PagerPrevSwitchComponent,
  PagerNextSwitchComponent,
} from "@lisn.js/react";
import "lisn.js/pager-carousel.css";

import styles from "./demo.module.css";

export default function Page() {
  return (
    <>
      <div className={styles.wrapper}>
        <PagerComponent
          className={styles.demo}
          config={{
            style: "carousel",
            peek: true,
            pageSize: 250,
            horizontal: true,
            parallax: true,
            useGestures: "touch,wheel",
            alignGestureDirection: true,
            preventDefault: false,
          }}
        >
          <div className={styles.arrows}>
            <PagerPrevSwitchComponent
              className={styles.arrow}
              data-switch="prev"
              aria-label="Previous"
            ></PagerPrevSwitchComponent>
            <PagerNextSwitchComponent
              className={styles.arrow}
              data-switch="next"
              aria-label="Next"
            ></PagerNextSwitchComponent>
          </div>

          <div className={styles.pages}>
            {/* Pages act as switches themselves so that the user can tap one
						to make it active */}
            <PagerPageComponent className={styles.page}>
              <PagerSwitchComponent className={styles.content}>
                <h1>L</h1>
                <h4>Lightweight.</h4>

                <ul>
                  <li>Vanilla TypeScript</li>
                  <li>Highly optimized</li>
                  <li>No layout thrashing</li>
                </ul>
              </PagerSwitchComponent>
            </PagerPageComponent>

            <PagerPageComponent className={styles.page}>
              <PagerSwitchComponent className={styles.content}>
                <h1>I</h1>
                <h4>Interactive.</h4>

                <ul>
                  <li>Powerful API</li>
                  <li>Multi gesture support</li>
                  <li>Mobile/touch ready</li>
                </ul>
              </PagerSwitchComponent>
            </PagerPageComponent>

            <PagerPageComponent className={styles.page}>
              <PagerSwitchComponent className={styles.content}>
                <h1>S</h1>
                <h4>Simple.</h4>

                <ul>
                  <li>Intuitive syntax</li>
                  <li>Consistent API</li>
                  <li>HTML-only mode</li>
                </ul>
              </PagerSwitchComponent>
            </PagerPageComponent>

            <PagerPageComponent className={styles.page}>
              <PagerSwitchComponent className={styles.content}>
                <h1>N</h1>
                <h4>No-nonsense.</h4>

                <ul>
                  <li>What says on the box</li>
                  <li>Sensible defaults</li>
                  <li>Highly customizable</li>
                </ul>
              </PagerSwitchComponent>
            </PagerPageComponent>
          </div>
        </PagerComponent>
      </div>
    </>
  );
}
/* Container */
.wrapper {
  --animate-duration: 0.4s;
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  width: 100dvw;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Pager and page container */
.demo {
  width: 100%;
  max-width: 1460px;
  margin: 0 auto;
}

/* Individual pages */
.page {
  padding: 5vh 2vmin;
  border-radius: 15px;
  background: var(--bg-color-lighter);
  box-shadow: rgba(0, 0, 0, 0.2) 4px 5px 5px 0px;
}

.page[data-lisn-page-state="current"] {
  background: var(--bg-color-lightest);
}

/* Switches (general) */
.content,
.arrow {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  outline: none;
}

/* Prev/next arrows */
.arrows {
  width: 100%;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

.demo[data-lisn-current-page-is-first-enabled="true"] [data-switch="prev"],
.demo[data-lisn-current-page-is-last-enabled="true"] [data-switch="next"] {
  cursor: default;
  pointer-events: none;
  opacity: 0.25;
}

.arrow {
  background: none;
  padding: 0;
  margin: 10px;
  width: 0;
  height: 0;
  border-style: solid;
  opacity: 0.8;
  cursor: pointer;
  border-width: 13px;
  border-color: transparent var(--text-color);
}

.arrow:hover {
  opacity: 1;
}

.arrow[data-switch="prev"] {
  border-left: none !important;
}

.arrow[data-switch="next"] {
  border-right: none !important;
}

/* Page content */
.page .content {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.demo h1 {
  margin: 0 auto;
  font-size: 75px;
  background-image: linear-gradient(
    45deg,
    var(--text-color) 42%,
    var(--text-color-lighter) 50%,
    var(--text-color) 58%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

.demo h4 {
  font-size: clamp(20px, calc(15px + 2vw), 32px);
}

.demo ul {
  padding: 0;
  list-style-type: none;
}

.demo ul li {
  margin: 8px 0;
}

.demo ul li::before {
  content: "\2726";
  display: inline-block;
  font-size: 0.4em;
  transform: translateY(-0.4em);
  margin: 0 0.6em 0 0;
}

Edit on CodePen

document.addEventListener("DOMContentLoaded", () => {
  const pager = document.getElementById("demo");
  const pages = pager.querySelectorAll(".page");
  const switches = pager.querySelectorAll(".switch");
  const prevSwitch = pager.querySelector(".prev-switch");
  const nextSwitch = pager.querySelector(".next-switch");
  new LISN.widgets.Pager(pager, {
    pages,
    switches,
    prevSwitch,
    nextSwitch,
    style: "carousel",
    peek: true,
    pageSize: 250,
    horizontal: true,
    parallax: true,
    useGestures: "touch,wheel",
    alignGestureDirection: true,
    preventDefault: false,
  });
});
<div id="demo">
  <div class="prev-next-buttons">
    <button class="prev-switch" aria-label="Previous"></button>
    <button class="next-switch" aria-label="Next"></button>
  </div>

  <div class="pages">
    <div class="page switch">
      <h1>L</h1>
      <h4>Lightweight.</h4>

      <ul>
        <li>Vanilla TypeScript</li>
        <li>Highly optimized</li>
        <li>No layout thrashing</li>
      </ul>
    </div>

    <div class="page switch">
      <h1>I</h1>
      <h4>Interactive.</h4>

      <ul>
        <li>Powerful API</li>
        <li>Multi gesture support</li>
        <li>Mobile/touch ready</li>
      </ul>
    </div>

    <div class="page switch">
      <h1>S</h1>
      <h4>Simple.</h4>

      <ul>
        <li>Intuitive syntax</li>
        <li>Consistent API</li>
        <li>HTML-only mode</li>
      </ul>
    </div>

    <div class="page switch">
      <h1>N</h1>
      <h4>No-nonsense.</h4>

      <ul>
        <li>What says on the box</li>
        <li>Sensible defaults</li>
        <li>Highly customizable</li>
      </ul>
    </div>
  </div>
</div>
/* Pager and page container */
#demo {
  width: 100%;
  max-width: 1460px;
  margin: 0 auto;
}

/* Individual pages */
#demo .page {
  padding: 5vh 2vmin;
  border-radius: 15px;
  background: var(--bg-color-lighter);
  box-shadow: rgba(0, 0, 0, 0.2) 4px 5px 5px 0px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

#demo .page[data-lisn-page-state="current"] {
  background: var(--bg-color-lightest);
}

#demo .switch {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  outline: none;
}

/* Prev/next arrows */
#demo[data-lisn-current-page-is-first-enabled="true"] .prev-switch,
#demo[data-lisn-current-page-is-last-enabled="true"] .next-switch {
  --btn-color: #777;
  cursor: default;
  pointer-events: none;
}

#demo .prev-next-buttons {
  width: 100%;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

#demo .prev-next-buttons button {
  --btn-color: #ddd;
  background: none;
  padding: 0;
  margin: 10px;
  width: 0;
  height: 0;
  border-style: solid;
  opacity: 0.8;
  cursor: pointer;
  border-width: 13px;
  border-color: transparent var(--btn-color);
}

#demo .prev-next-buttons button:hover {
  --btn-color: #fff;
}

#demo .prev-switch {
  border-left: none !important;
}

#demo .next-switch {
  border-right: none !important;
}

/* Page content */
#demo h1 {
  margin: 0 auto;
  font-size: 75px;
  background-image: linear-gradient(
    45deg,
    var(--text-color) 42%,
    var(--text-color-lighter) 50%,
    var(--text-color) 58%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

#demo h4 {
  font-size: clamp(20px, calc(15px + 2vw), 32px);
}

#demo ul {
  padding: 0;
  list-style-type: none;
}

#demo ul li {
  margin: 8px 0;
}

#demo ul li::before {
  content: "\2726";
  display: inline-block;
  font-size: 0.4em;
  transform: translateY(-0.4em);
  margin: 0 0.6em 0 0;
}

Edit on CodePen

<div
  id="demo"
  data-lisn-pager="style=carousel
                 | peek
                 | page-size=250
                 | horizontal
                 | parallax
                 | use-gestures=touch,wheel
                 | align-gesture-direction=true
                 | prevent-default=false"
>
  <div class="prev-next-buttons">
    <button data-lisn-pager-prev-switch aria-label="Previous"></button>
    <button data-lisn-pager-next-switch aria-label="Next"></button>
  </div>

  <div class="pages">
    <div data-lisn-pager-page data-lisn-pager-switch>
      <h1>L</h1>
      <h4>Lightweight.</h4>

      <ul>
        <li>Vanilla TypeScript</li>
        <li>Highly optimized</li>
        <li>No layout thrashing</li>
      </ul>
    </div>

    <div data-lisn-pager-page data-lisn-pager-switch>
      <h1>I</h1>
      <h4>Interactive.</h4>

      <ul>
        <li>Powerful API</li>
        <li>Multi gesture support</li>
        <li>Mobile/touch ready</li>
      </ul>
    </div>

    <div data-lisn-pager-page data-lisn-pager-switch>
      <h1>S</h1>
      <h4>Simple.</h4>

      <ul>
        <li>Intuitive syntax</li>
        <li>Consistent API</li>
        <li>HTML-only mode</li>
      </ul>
    </div>

    <div data-lisn-pager-page data-lisn-pager-switch>
      <h1>N</h1>
      <h4>No-nonsense.</h4>

      <ul>
        <li>What says on the box</li>
        <li>Sensible defaults</li>
        <li>Highly customizable</li>
      </ul>
    </div>
  </div>
</div>
/* Pager and page container */
#demo {
  width: 100%;
  max-width: 1460px;
  margin: 0 auto;
}

/* Individual pages */
#demo [data-lisn-pager-page] {
  padding: 5vh 2vmin;
  border-radius: 15px;
  background: var(--bg-color-lighter);
  box-shadow: rgba(0, 0, 0, 0.2) 4px 5px 5px 0px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

#demo [data-lisn-pager-page][data-lisn-page-state="current"] {
  background: var(--bg-color-lightest);
}

#demo [data-lisn-pager-switch] {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  outline: none;
}

/* Prev/next arrows */
#demo[data-lisn-current-page-is-first-enabled="true"]
  [data-lisn-pager-prev-switch],
#demo[data-lisn-current-page-is-last-enabled="true"]
  [data-lisn-pager-next-switch] {
  --btn-color: #777;
  cursor: default;
  pointer-events: none;
}

#demo .prev-next-buttons {
  width: 100%;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  gap: 10px;
}

#demo .prev-next-buttons button {
  --btn-color: #ddd;
  background: none;
  padding: 0;
  margin: 10px;
  width: 0;
  height: 0;
  border-style: solid;
  opacity: 0.8;
  cursor: pointer;
  border-width: 13px;
  border-color: transparent var(--btn-color);
}

#demo .prev-next-buttons button:hover {
  --btn-color: #fff;
}

#demo [data-lisn-pager-prev-switch] {
  border-left: none !important;
}

#demo [data-lisn-pager-next-switch] {
  border-right: none !important;
}

/* Page content */
#demo h1 {
  margin: 0 auto;
  font-size: 75px;
  background-image: linear-gradient(
    45deg,
    var(--text-color) 42%,
    var(--text-color-lighter) 50%,
    var(--text-color) 58%
  );
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

#demo h4 {
  font-size: clamp(20px, calc(15px + 2vw), 32px);
}

#demo ul {
  padding: 0;
  list-style-type: none;
}

#demo ul li {
  margin: 8px 0;
}

#demo ul li::before {
  content: "\2726";
  display: inline-block;
  font-size: 0.4em;
  transform: translateY(-0.4em);
  margin: 0 0.6em 0 0;
}

L

Lightweight.

  • Vanilla TypeScript
  • Highly optimized
  • No layout thrashing

I

Interactive.

  • Powerful API
  • Multi gesture support
  • Mobile/touch ready

S

Simple.

  • Intuitive syntax
  • Consistent API
  • HTML-only mode

N

No-nonsense.

  • What says on the box
  • Sensible defaults
  • Highly customizable