use swipable carousel

This commit is contained in:
Karol Wypchlo 2021-03-31 18:12:18 +02:00
parent 2ee5cd3095
commit 13d1cade63
6 changed files with 68 additions and 49 deletions

View File

@ -2,6 +2,7 @@ import * as React from "react";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { wrap } from "popmotion";
import classnames from "classnames";
const variants = {
enter: (direction) => {
@ -35,7 +36,7 @@ const swipePower = (offset, velocity) => {
return Math.abs(offset) * velocity;
};
export const Carousel = ({ items }) => {
export const Carousel = ({ Component, items }) => {
const [[page, direction], setPage] = useState([0, 0]);
// We only have 3 items, but we paginate them absolutely (ie 1, 2, 3, 4, 5...) and
@ -50,39 +51,61 @@ export const Carousel = ({ items }) => {
return (
<>
<AnimatePresence initial={false} custom={direction}>
<motion.div
key={page}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
// transition={{
// x: { type: "spring", stiffness: 300, damping: 30 },
// opacity: { duration: 0.2 },
// }}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
onDragEnd={(e, { offset, velocity }) => {
const swipe = swipePower(offset.x, velocity.x);
<div className="relative overflow-hidden">
<div className="opacity-0 flex flex-row">
{items.map((item, index) => (
<div className="flex-shrink-0 w-screen">
<Component key={index} {...item} />
</div>
))}
</div>
if (swipe < -swipeConfidenceThreshold) {
paginate(1);
} else if (swipe > swipeConfidenceThreshold) {
paginate(-1);
}
}}
>
{items[itemIndex]}
</motion.div>
</AnimatePresence>
<div className="next" onClick={() => paginate(1)}>
{"‣"}
<AnimatePresence initial={false} custom={direction}>
<motion.div
key={page}
custom={direction}
variants={variants}
initial="enter"
animate="center"
exit="exit"
transition={{
x: { type: "spring", stiffness: 300, damping: 30 },
// opacity: { duration: 0.2 },
}}
drag="x"
dragConstraints={{ left: 0, right: 0 }}
dragElastic={1}
onDragEnd={(e, { offset, velocity }) => {
const swipe = swipePower(offset.x, velocity.x);
if (swipe < -swipeConfidenceThreshold) {
paginate(1);
} else if (swipe > swipeConfidenceThreshold) {
paginate(-1);
}
}}
className="absolute top-0 w-full"
>
<Component {...items[itemIndex]} />
</motion.div>
</AnimatePresence>
</div>
<div className="prev" onClick={() => paginate(-1)}>
{"‣"}
<div className="flex justify-center mt-8">
{items.map((item, index) => (
<button
key={index}
type="button"
className="p-3 flex"
onClick={() => setPage([index, index > itemIndex ? 1 : -1])}
>
<span
className={classnames("circle transition-colors", {
"bg-primary border-2 border-primary": itemIndex === index,
"bg-white border-2 border-palette-600": itemIndex !== index,
})}
></span>
</button>
))}
</div>
</>
);

View File

@ -29,7 +29,7 @@ async function example() {
return (
<div>
<div className="bg-palette-400 rounded-t space-x-2 px-2" style={{ width: "540px" }}>
<div className="bg-palette-400 rounded-t space-x-2 px-2">
<div className="circle bg-error"></div>
<div className="circle bg-warning"></div>
<div className="circle bg-primary"></div>

View File

@ -5,7 +5,7 @@ export default function Link({
children,
to,
activeClassName,
partiallyActive,
partiallyActive = to !== "/",
target = "_blank",
rel = "noopener noreferrer",
...params

View File

@ -1,12 +1,7 @@
import * as React from "react";
import { GatsbyImage, getImage } from "gatsby-plugin-image";
import Layout, {
Section,
SectionTitle,
SectionTitleCaption,
CardWithDescription,
CardCarousel,
} from "../components/Layout";
import Layout, { Section, SectionTitle, SectionTitleCaption, CardWithDescription } from "../components/Layout";
import { Carousel } from "../components/Carousel/Carousel";
import SEO from "../components/seo";
import {
ArrowRight,
@ -183,7 +178,7 @@ const AboutPage = ({ ...props }) => {
</div>
<div className="desktop:hidden">
<CardCarousel CardComponent={CardWithDescription} cards={aboutCards} />
<Carousel Component={CardWithDescription} items={aboutCards} />
</div>
<div className="mt-14 text-center space-y-6">
@ -247,7 +242,7 @@ const AboutPage = ({ ...props }) => {
</div>
<div className="desktop:hidden">
<CardCarousel CardComponent={TeamCardPage} cards={teamCardsPaginated} fullWidth={true} />
<Carousel Component={TeamCardPage} items={teamCardsPaginated} fullWidth={true} />
</div>
<div className="desktop:col-span-2 flex flex-col desktop:flex-row items-center desktop:space-x-8 space-y-8 desktop:space-y-0">

View File

@ -1,5 +1,6 @@
import * as React from "react";
import Layout, { Section, SectionTitle, CardWithDescription, CardCarousel } from "../components/Layout";
import Layout, { Section, SectionTitle, CardWithDescription } from "../components/Layout";
import { Carousel } from "../components/Carousel/Carousel";
import { ExternalLink, DataSwap, Encryption, Layers, Mesh, Toolkit, DevBig } from "../components/Icons";
import CodeTerminal from "../components/CodeTerminal";
import SEO from "../components/seo";
@ -130,7 +131,7 @@ const DevelopersPage = () => (
</div>
<div className="desktop:hidden">
<CardCarousel CardComponent={CardWithDescription} cards={reasonCards} />
<Carousel Component={CardWithDescription} items={reasonCards} />
</div>
<div className="desktop:hidden mt-12 text-center">

View File

@ -1,6 +1,6 @@
import * as React from "react";
// import { StaticImage } from "gatsby-plugin-image";
import Layout, { Section, SectionTitle, CardWithDescription, CardWithTitle, CardCarousel } from "../components/Layout";
import Layout, { Section, SectionTitle, CardWithDescription, CardWithTitle } from "../components/Layout";
import { Carousel } from "../components/Carousel/Carousel";
import SEO from "../components/seo";
import CommunitySection from "../components/CommunitySection";
import Uploader from "../components/Uploader";
@ -102,7 +102,7 @@ const IndexPage = () => {
</div>
<div className="desktop:hidden">
<CardCarousel CardComponent={CardWithTitle} cards={etosCards} />
<Carousel Component={CardWithTitle} items={etosCards} />
</div>
<div className="flex flex-col items-center mt-16">
@ -141,7 +141,7 @@ const IndexPage = () => {
</div>
<div className="desktop:hidden">
<CardCarousel CardComponent={CardWithDescription} cards={ecosystemCards} />
<Carousel Component={CardWithDescription} items={ecosystemCards} />
</div>
<div className="desktop:hidden mt-12 text-center">