use swipable carousel
This commit is contained in:
parent
2ee5cd3095
commit
13d1cade63
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -5,7 +5,7 @@ export default function Link({
|
|||
children,
|
||||
to,
|
||||
activeClassName,
|
||||
partiallyActive,
|
||||
partiallyActive = to !== "/",
|
||||
target = "_blank",
|
||||
rel = "noopener noreferrer",
|
||||
...params
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
Reference in New Issue