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 { useState } from "react";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
import { wrap } from "popmotion"; import { wrap } from "popmotion";
import classnames from "classnames";
const variants = { const variants = {
enter: (direction) => { enter: (direction) => {
@ -35,7 +36,7 @@ const swipePower = (offset, velocity) => {
return Math.abs(offset) * velocity; return Math.abs(offset) * velocity;
}; };
export const Carousel = ({ items }) => { export const Carousel = ({ Component, items }) => {
const [[page, direction], setPage] = useState([0, 0]); const [[page, direction], setPage] = useState([0, 0]);
// We only have 3 items, but we paginate them absolutely (ie 1, 2, 3, 4, 5...) and // We only have 3 items, but we paginate them absolutely (ie 1, 2, 3, 4, 5...) and
@ -50,6 +51,15 @@ export const Carousel = ({ items }) => {
return ( return (
<> <>
<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>
<AnimatePresence initial={false} custom={direction}> <AnimatePresence initial={false} custom={direction}>
<motion.div <motion.div
key={page} key={page}
@ -58,10 +68,10 @@ export const Carousel = ({ items }) => {
initial="enter" initial="enter"
animate="center" animate="center"
exit="exit" exit="exit"
// transition={{ transition={{
// x: { type: "spring", stiffness: 300, damping: 30 }, x: { type: "spring", stiffness: 300, damping: 30 },
// opacity: { duration: 0.2 }, // opacity: { duration: 0.2 },
// }} }}
drag="x" drag="x"
dragConstraints={{ left: 0, right: 0 }} dragConstraints={{ left: 0, right: 0 }}
dragElastic={1} dragElastic={1}
@ -74,15 +84,28 @@ export const Carousel = ({ items }) => {
paginate(-1); paginate(-1);
} }
}} }}
className="absolute top-0 w-full"
> >
{items[itemIndex]} <Component {...items[itemIndex]} />
</motion.div> </motion.div>
</AnimatePresence> </AnimatePresence>
<div className="next" onClick={() => paginate(1)}>
{"‣"}
</div> </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> </div>
</> </>
); );

View File

@ -29,7 +29,7 @@ async function example() {
return ( return (
<div> <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-error"></div>
<div className="circle bg-warning"></div> <div className="circle bg-warning"></div>
<div className="circle bg-primary"></div> <div className="circle bg-primary"></div>

View File

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

View File

@ -1,12 +1,7 @@
import * as React from "react"; import * as React from "react";
import { GatsbyImage, getImage } from "gatsby-plugin-image"; import { GatsbyImage, getImage } from "gatsby-plugin-image";
import Layout, { import Layout, { Section, SectionTitle, SectionTitleCaption, CardWithDescription } from "../components/Layout";
Section, import { Carousel } from "../components/Carousel/Carousel";
SectionTitle,
SectionTitleCaption,
CardWithDescription,
CardCarousel,
} from "../components/Layout";
import SEO from "../components/seo"; import SEO from "../components/seo";
import { import {
ArrowRight, ArrowRight,
@ -183,7 +178,7 @@ const AboutPage = ({ ...props }) => {
</div> </div>
<div className="desktop:hidden"> <div className="desktop:hidden">
<CardCarousel CardComponent={CardWithDescription} cards={aboutCards} /> <Carousel Component={CardWithDescription} items={aboutCards} />
</div> </div>
<div className="mt-14 text-center space-y-6"> <div className="mt-14 text-center space-y-6">
@ -247,7 +242,7 @@ const AboutPage = ({ ...props }) => {
</div> </div>
<div className="desktop:hidden"> <div className="desktop:hidden">
<CardCarousel CardComponent={TeamCardPage} cards={teamCardsPaginated} fullWidth={true} /> <Carousel Component={TeamCardPage} items={teamCardsPaginated} fullWidth={true} />
</div> </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"> <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 * 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 { ExternalLink, DataSwap, Encryption, Layers, Mesh, Toolkit, DevBig } from "../components/Icons";
import CodeTerminal from "../components/CodeTerminal"; import CodeTerminal from "../components/CodeTerminal";
import SEO from "../components/seo"; import SEO from "../components/seo";
@ -130,7 +131,7 @@ const DevelopersPage = () => (
</div> </div>
<div className="desktop:hidden"> <div className="desktop:hidden">
<CardCarousel CardComponent={CardWithDescription} cards={reasonCards} /> <Carousel Component={CardWithDescription} items={reasonCards} />
</div> </div>
<div className="desktop:hidden mt-12 text-center"> <div className="desktop:hidden mt-12 text-center">

View File

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