framer-motion#useAnimation JavaScript Examples

The following examples show how to use framer-motion#useAnimation. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useAnimatedNavToggler.js    From cucoders with Apache License 2.0 6 votes vote down vote up
//Below logic is for toggling the navbar when toggleNavbar is called. It is used on mobile toggling of navbar.
export default function useAnimatedNavToggler() {
  const [showNavLinks, setShowNavLinks] = useState(false);
  const [x, cycleX] = useCycle("0%", "150%");
  const animation = useAnimation();

  const toggleNavbar = () => {
    setShowNavLinks(!showNavLinks);
    animation.start({ x: x, display: "block" });
    cycleX();
  };

  return {showNavLinks,animation, toggleNavbar }
}
Example #2
Source File: IntroScreen.js    From webappdevtest with MIT License 6 votes vote down vote up
export function IntroScreen(props) {
    const {selectedCity} = props;
    const controls = useAnimation();
    const contentControls = useAnimation();
    const close = {height: 0, transition: {ease: "easeInOut", duration: 1}}

    useEffect(()=>{
        contentControls.start({y: 0, opacity: 1, transition: {ease: 'easeInOut'}})
    },[])
    return (
        <motion.div
            className="introScreenContainer"
            animate={controls}
        >
            <motion.div
                className="introScreenContent"
                initial = {{y: 10, opacity: 0}}
                animate={contentControls}
            >
                <h1>Hey! Whats this?</h1>
                <p> Looks like points on a map!
                </p>
                <motion.button
                    className="primary_btn"
                    whileHover={{scale: 1.02}}
                    whileTap={{scale:0.9}}
                    onClick = {()=> {
                        selectedCity ? PageView(selectedCity) : PageView('Homepage')
                        controls.start(close)
                        contentControls.start({opacity: 0, transition: {duration: 0.1}})
                    }}
                >View the map
                </motion.button>
            </motion.div>
        </motion.div>
    )
}
Example #3
Source File: HomeContent.js    From ar-episode2 with MIT License 6 votes vote down vote up
HomeContent = () => {
  const animation = useAnimation()
  const [contentRef, inView] = useInView({
    triggerOnce: true,
    rootMargin: "-300px",
  })

  useEffect(() => {
    if (inView) {
      animation.start("visible")
    }
  }, [animation, inView])

  return (
    <HomeContentSection
      ref={contentRef}
      animate={animation}
      initial="hidden"
      variants={{
        visible: {
          opacity: 1,
          y: 0,
          transition: { duration: 0.8, ease: [0.6, 0.05, -0.01, 0.9] },
        },
        hidden: { opacity: 0, y: 72 },
      }}
    >
      <Container>
        <Content>
          Great stories don’t just happen— <br /> they need to be uncovered. And
          we dig deep to discover the great stories that lie just below the
          surface. Dirt under our fingernails and all.
        </Content>
      </Container>
    </HomeContentSection>
  )
}
Example #4
Source File: cookieBar.js    From gatsby-starter-portfolio-minimal with MIT License 6 votes vote down vote up
CookieBar = () => {
  const location = useLocation()
  const controls = useAnimation()
  const { isIntroDone } = useContext(Context).state

  // Display cookie bar after the splashScreen sequence is done
  useEffect(() => {
    if (isIntroDone) {
      controls.start({
        opacity: 1,
        y: 0,
        transition: { delay: 1 },
      })
    }
  }, [isIntroDone])

  if (!isIntroDone) return null

  return (
    <StyledCookieBar initial={{ opacity: 0, y: 20 }} animate={controls}>
      <CookieConsent
        cookieName="gatsby-gdpr-google-analytics"
        buttonId="confirm"
        buttonText="Accept"
        declineButtonId="decline"
        declineButtonText="Decline"
        enableDeclineButton={true}
        disableStyles={true}
        onAccept={() => initializeAndTrack(location)}
      >
        <p className="cookieMessage">This website uses cookies ? </p>
      </CookieConsent>
    </StyledCookieBar>
  )
}
Example #5
Source File: homeAbout.js    From ar-episode2 with MIT License 5 votes vote down vote up
HomeAbout = ({ onCursor }) => {
  //Default state, using number for our id. Which ever the number/id is in the state. That will be opened.
  const [expanded, setExpanded] = useState(0)
  const animation = useAnimation()
  const [aboutRef, inView] = useInView({
    triggerOnce: true,
    // Giving our scrollwheel additional 300px before executing animation
    rootMargin: "-300px",
  })

  useEffect(() => {
    if (inView) {
      animation.start("visible")
    }
  }, [animation, inView])

  return (
    <HomeAboutSection
      ref={aboutRef}
      animate={animation}
      initial="hidden"
      variants={{
        visible: {
          opacity: 1,
          y: 0,
          transition: { duration: 0.8, ease: [0.6, 0.05, -0.01, 0.9] },
        },
        hidden: { opacity: 0, y: 72 },
      }}
    >
      <Container>
        <Flex alignTop>
          <About>
            <h2>
              Furrow is an integrated, full-service creative studio offering
              video production, creative development, and post-production
              services.
            </h2>
            <p>
              Everybody’s got a story. And we don’t stop until we’ve uncovered
              what makes yours worth telling. Whether it’s working directly with
              you, an agency partner, or putting the finishing touches on
              something special, we’re ready to dig in and get our hands
              dirty—are you?
            </p>
          </About>
          <Services>
            <h3>Services</h3>
            {accordionIds.map((details, index) => (
              <Accordion
                key={index}
                details={details}
                expanded={expanded}
                setExpanded={setExpanded}
                onCursor={onCursor}
              />
            ))}
          </Services>
        </Flex>
      </Container>
    </HomeAboutSection>
  )
}
Example #6
Source File: burgerNav.js    From open-jobboard with Apache License 2.0 5 votes vote down vote up
BurgerNav = () => {
  const [open, setOpen] = useState(false)
  const [windowWidth, setWindowWidth] = useState(0)

  
  useEffect(() => {
    let handleWindowSizeChange
    // if (isSSR) is necessary to prevent error during the gatsby build
    if (!isSSR) {
      handleWindowSizeChange = () => setWindowWidth(window.innerWidth)
      // set initial innerWidth when component mounts
      setWindowWidth(window.innerWidth)
    }
    // Add event listener to update windowWidth in state
    window.addEventListener("resize", handleWindowSizeChange)
    return () => window.removeEventListener("resize", handleWindowSizeChange)
  }, [windowWidth])

  // Required for animation - start after the splashScreen sequence is done
  const controls = useAnimation()
  

  let navigation
  if (detectMobileAndTablet(windowWidth)) {
    navigation = (
      <>
        <StyledBurger
          aria-controls="sidebar"
          open={open}
          onClick={() => setOpen(!open)}
        >
          <div />
          <div />
          <div />
        </StyledBurger>
        <Sidebar id="sidebar" open={open} setOpen={setOpen} />
      </>
    )
  } else {
    navigation = <Navbar />
  }

  return (
    <StyledHeader>
      {/* add blur class to body when sidebar is opened */}
      <Helmet bodyAttributes={{ class: open ? "blur" : "" }} />
      <StyledContentWrapper>
        <Link to="/" aria-label="home">
          <Logo color="primary" size="2rem" />
        </Link>
        {navigation}
      </StyledContentWrapper>
    </StyledHeader>
  )
}
Example #7
Source File: IndexHeroFeaturedIn.jsx    From pooltogether-landing-site with MIT License 5 votes vote down vote up
IndexHeroFeaturedIn = () => {
  const controls = useAnimation()
  const [ref, inView] = useInView()

  useEffect(() => {
    if (inView) {
      controls.start('visible')
    }
  }, [controls, inView])

  const containerVariants = {
    visible: {
      transition: {
        staggerChildren: 0.12
      }
    },
    hidden: {}
  }

  return (
    <div id='featured-in' className='text-center pt-10'>
      <div className='pool-container mx-auto'>
        <h5 className='my-0 sm:mt-4 leading-tight'>Featured in:</h5>

        <motion.div
          className={classnames(
            'flex flex-col xs:flex-row xs:flex-wrap justify-start items-start',
            'mt-2 mb-4 px-4 xs:px-8 rounded-xl -mx-4 sm:-mx-12 lg:-mx-16'
          )}
          ref={ref}
          animate={controls}
          initial='hidden'
          variants={containerVariants}
        >
          <GridItemSupportedBy
            altBg
            title={'Binance Academy'}
            img={BinanceAcademySvg}
            url='https://academy.binance.com/en/articles/how-pool-together-turns-saving-money-into-a-game'
          />

          <GridItemSupportedBy
            altBg
            title={'Zapper'}
            img={ZapperFiSvg}
            url='https://learn.zapper.fi/articles/how-to-tranfer-eth-from-coinbase-to-defi'
          />

          <GridItemSupportedBy
            altBg
            title={'Ethereum.org'}
            img={EthereumPng}
            url='https://ethereum.org/en/dapps/'
          />

          <GridItemSupportedBy
            altBg
            title={'Bankless'}
            img={BanklessPng}
            url='https://shows.banklesshq.com/p/early-access-meet-the-nation-pooltogether'
          />

          <GridItemSupportedBy
            altBg
            title={'CoinDesk'}
            img={CoinDeskPng}
            url='https://www.coindesk.com/tag/pooltogether'
          />
        </motion.div>
      </div>
    </div>
  )
}
Example #8
Source File: splashScreen.js    From gatsby-starter-portfolio-minimal with MIT License 5 votes vote down vote up
SplashScreen = () => {
  const { state, setState } = useContext(Context)

  const backgroundControls = useAnimation()
  const backdropControls = useAnimation()

  useEffect(() => {
    const sequence = async () => {
      await backgroundControls.start({ opacity: 1 })
      await backdropControls.start({ height: "0%", transition: { delay: 0.8 } })
      await backgroundControls.start({ opacity: 0, transition: { delay: 0.6 } })
      setState({ ...state, isIntroDone: true })
    }
    sequence()
  }, [backgroundControls, backdropControls, setState, state])

  return (
    <StyledSplashScreen
      initial={{ opacity: 0 }}
      animate={backgroundControls}
      darkMode={state.darkMode}
    >
      {/* Add splashScreen class to body (prevents scrolling during splashScreen) */}
      <Helmet
        bodyAttributes={{ class: !state.isIntroDone ? "splashScreen" : "" }}
      />
      <div className="logo-wrapper">
        <motion.div
          className="backdrop"
          initial={{ height: "100%" }}
          animate={backdropControls}
        />
        <Logo
          size="3rem"
          color={
            state.darkMode
              ? darkTheme.colors.primary
              : lightTheme.colors.background
          }
        />
      </div>
    </StyledSplashScreen>
  )
}
Example #9
Source File: interests.js    From gatsby-starter-portfolio-minimal with MIT License 5 votes vote down vote up
Interests = ({ content }) => {
  const { exports, frontmatter } = content[0].node
  const { shownItems, interests } = exports

  const [shownInterests, setShownInterests] = useState(shownItems)

  const ref = useRef()
  const onScreen = useOnScreen(ref)

  const iControls = useAnimation()
  const bControls = useAnimation()

  useEffect(() => {
    // If mobile or tablet, show all interests initially
    // Otherwise interests.mdx will determine how many interests are shown
    // (isSSR) is used to prevent error during gatsby build
    if (!isSSR && detectMobileAndTablet(window.innerWidth)) {
      setShownInterests(interests.length)
    }
  }, [interests])

  useEffect(() => {
    const sequence = async () => {
      if (onScreen) {
        // i receives the value of the custom prop - can be used to stagger
        // the animation of each "interest" element
        await iControls.start(i => ({
          opacity: 1,
          scaleY: 1,
          transition: { delay: i * 0.1 },
        }))
        await bControls.start({ opacity: 1, scaleY: 1 })
      }
    }
    sequence()
  }, [onScreen, shownInterests, iControls, bControls])

  const showMoreItems = () => setShownInterests(shownInterests + 4)

  return (
    <StyledSection id="interests">
      <StyledContentWrapper>
        <h3 className="section-title">{frontmatter.title}</h3>
        <StyledInterests itemCount={interests.length} ref={ref}>
          {interests.slice(0, shownInterests).map(({ name, icon }, key) => (
            <motion.div
              className="interest"
              key={key}
              custom={key}
              initial={{ opacity: 0, scaleY: 0 }}
              animate={iControls}
            >
              <Img className="icon" fixed={icon.childImageSharp.fixed} /> {name}
            </motion.div>
          ))}
          {shownInterests < interests.length && (
            <motion.div initial={{ opacity: 0, scaleY: 0 }} animate={bControls}>
              <Button
                onClick={() => showMoreItems()}
                type="button"
                textAlign="left"
              >
                + Load more
              </Button>
            </motion.div>
          )}
        </StyledInterests>
      </StyledContentWrapper>
    </StyledSection>
  )
}
Example #10
Source File: hero.js    From gatsby-starter-portfolio-minimal with MIT License 5 votes vote down vote up
Hero = ({ content }) => {
  const { frontmatter, body } = content[0].node
  const { isIntroDone, darkMode } = useContext(Context).state

  // Controls to orchestrate animations of greetings, emoji, social profiles, underlining
  const gControls = useAnimation()
  const eControls = useAnimation()
  const sControls = useAnimation()
  const uControls = useAnimation()

  // Start Animations after the splashScreen sequence is done
  useEffect(() => {
    const pageLoadSequence = async () => {
      if (isIntroDone) {
        eControls.start({
          rotate: [0, -10, 12, -10, 9, 0, 0, 0, 0, 0, 0],
          transition: { duration: 2.5, loop: 3, repeatDelay: 1 },
        })
        await gControls.start({
          opacity: 1,
          y: 0,
          transition: { delay: 0.4 },
        })
        await sControls.start({
          opacity: 1,
          x: 0,
        })
        // Animate underlining to hover state
        await uControls.start({
          boxShadow: `inset 0 -2rem 0 ${
            darkMode ? darkTheme.colors.secondary : lightTheme.colors.secondary
          }`,
          transition: { delay: 0.4, ease: "circOut" },
        })
      }
    }
    pageLoadSequence()
  }, [isIntroDone, darkMode, eControls, gControls, sControls, uControls])

  return (
    <StyledSection id="hero">
      <StyledContentWrapper>
        <motion.div
          initial={{ opacity: 0, y: 20 }}
          animate={gControls}
          data-testid="animated-heading"
        >
          <h1 className="title">
            <div className="greetings">
              {frontmatter.greetings}
              <motion.div
                animate={eControls}
                style={{ originX: 0.7, originY: 0.7 }}
              >
                <Img
                  className="emoji"
                  fluid={frontmatter.icon.childImageSharp.fluid}
                />
              </motion.div>
            </div>
            {frontmatter.title}
          </h1>
          <h2 className="subtitle">
            {frontmatter.subtitlePrefix}{" "}
            <AnimatedUnderlining animate={uControls} big>
              {frontmatter.subtitle}
            </AnimatedUnderlining>
          </h2>
          <div className="description">
            <MDXRenderer>{body}</MDXRenderer>
          </div>
        </motion.div>
        <motion.div initial={{ opacity: 0, x: 20 }} animate={sControls}>
          <Social fontSize=".95rem" padding=".3rem 1.25rem" width="auto" />
        </motion.div>
      </StyledContentWrapper>
    </StyledSection>
  )
}
Example #11
Source File: about.js    From gatsby-starter-portfolio-minimal with MIT License 5 votes vote down vote up
About = ({ content }) => {
  const { frontmatter, body } = content[0].node
  const { isIntroDone } = useContext(Context).state
  const tControls = useAnimation()
  const iControls = useAnimation()

  // Required for animating the text content
  const tRef = useRef()
  const tOnScreen = useOnScreen(tRef)

  // Required for animating the image
  const iRef = useRef()
  const iOnScreen = useOnScreen(iRef)

  // Only trigger animations if the intro is done or disabled
  useEffect(() => {
    if (isIntroDone) {
      if (tOnScreen) tControls.start({ opacity: 1, y: 0 })
      if (iOnScreen) iControls.start({ opacity: 1, x: 0 })
    }
  }, [isIntroDone, tControls, iControls, tOnScreen, iOnScreen])

  return (
    <StyledSection id="about">
      <StyledContentWrapper>
        <motion.div
          className="inner-wrapper"
          ref={tRef}
          initial={{ opacity: 0, y: 20 }}
          animate={tControls}
        >
          <h3 className="section-title">{frontmatter.title}</h3>
          <div className="text-content">
            <MDXRenderer>{body}</MDXRenderer>
          </div>
        </motion.div>
        <motion.div
          className="image-content"
          ref={iRef}
          initial={{ opacity: 0, x: 20 }}
          animate={iControls}
        >
          <Img
            className="about-author"
            fluid={frontmatter.image.childImageSharp.fluid}
          />
        </motion.div>
      </StyledContentWrapper>
    </StyledSection>
  )
}
Example #12
Source File: header.js    From gatsby-starter-portfolio-minimal with MIT License 5 votes vote down vote up
Header = () => {
  const { isIntroDone } = useContext(Context).state
  const [open, setOpen] = useState(false)
  const [windowWidth, setWindowWidth] = useState(0)

  useEffect(() => {
    let handleWindowSizeChange
    // if (isSSR) is necessary to prevent error during the gatsby build
    if (!isSSR) {
      handleWindowSizeChange = () => setWindowWidth(window.innerWidth)
      // set initial innerWidth when component mounts
      setWindowWidth(window.innerWidth)
    }
    // Add event listener to update windowWidth in state
    window.addEventListener("resize", handleWindowSizeChange)
    return () => window.removeEventListener("resize", handleWindowSizeChange)
  }, [windowWidth])

  // Required for animation - start after the splashScreen sequence is done
  const controls = useAnimation()
  useEffect(() => {
    if (isIntroDone)
      controls.start({ opacity: 1, y: 0, transition: { delay: 0.2 } })
  }, [isIntroDone, controls])

  let navigation
  if (detectMobileAndTablet(windowWidth)) {
    navigation = (
      <>
        <StyledBurger
          aria-controls="sidebar"
          open={open}
          onClick={() => setOpen(!open)}
        >
          <div />
          <div />
          <div />
        </StyledBurger>
        <Sidebar id="sidebar" open={open} setOpen={setOpen} />
      </>
    )
  } else {
    navigation = <Navbar />
  }

  return (
    <StyledHeader initial={{ opacity: 0, y: -10 }} animate={controls}>
      {/* add blur class to body when sidebar is opened */}
      <Helmet bodyAttributes={{ class: open ? "blur" : "" }} />
      <StyledContentWrapper>
        <Link to="/" aria-label="home">
          <Logo color="primary" size="2rem" />
        </Link>
        {navigation}
      </StyledContentWrapper>
    </StyledHeader>
  )
}
Example #13
Source File: articles.js    From gatsby-starter-portfolio-minimal with MIT License 4 votes vote down vote up
Articles = () => {
  const MAX_ARTICLES = shownArticles

  const { isIntroDone, darkMode } = useContext(Context).state
  const [articles, setArticles] = useState()
  const articlesControls = useAnimation()

  // Load and display articles after the splashScreen sequence is done
  useEffect(() => {
    const loadArticles = async () => {
      if (isIntroDone) {
        await articlesControls.start({
          opacity: 1,
          y: 0,
          transition: { delay: 1 },
        })
        fetch(mediumRssFeed, { headers: { Accept: "application/json" } })
          // fetch(rssFeed, { headers: { Accept: "application/json" } })
          .then(res => res.json())
          // Feed also contains comments, therefore we filter for articles only
          .then(data => data.items.filter(item => item.categories.length > 0))
          // .then(data => data.items.filter(item => item.title.length > 0))
          .then(newArticles => newArticles.slice(0, MAX_ARTICLES))
          .then(articles => setArticles(articles))
          .catch(error => console.log(error))
      }
    }
    loadArticles()
  }, [isIntroDone, articlesControls, MAX_ARTICLES])

  return (
    <StyledSection
      id="articles"
      initial={{ opacity: 0, y: 20 }}
      animate={articlesControls}
    >
      <StyledContentWrapper>
        <h3 className="section-title">Latest Articles</h3>
        <div className="articles">
          {articles
            ? articles.map(item => (
                <a
                  href={item.link}
                  target="_blank"
                  rel="nofollow noopener noreferrer"
                  title={item.title}
                  aria-label={item.link}
                  key={item.link}
                >
                  <div className="card">
                    <span className="category">
                      <Underlining color="tertiary" hoverColor="secondary">
                        {item.categories[2]}
                      </Underlining>
                    </span>
                    <h4 className="title">{item.title}</h4>
                    <span className="date">{parseDate(item.pubDate)}</span>
                  </div>
                </a>
              ))
            : [...Array(MAX_ARTICLES <= 3 ? MAX_ARTICLES : 3)].map((i, key) => (
                <div className="card" key={key}>
                  <SkeletonLoader
                    height="1.5rem"
                    style={{ marginBottom: ".5rem" }}
                    background={
                      darkMode
                        ? darkTheme.colors.tertiary
                        : lightTheme.colors.tertiary
                    }
                  />
                  <SkeletonLoader
                    height="4rem"
                    background={
                      darkMode
                        ? darkTheme.colors.tertiary
                        : lightTheme.colors.tertiary
                    }
                  />
                  <SkeletonLoader
                    height=".75rem"
                    width="50%"
                    style={{ marginTop: ".5rem" }}
                    background={
                      darkMode
                        ? darkTheme.colors.tertiary
                        : lightTheme.colors.tertiary
                    }
                  />
                </div>
              ))}
        </div>
      </StyledContentWrapper>
    </StyledSection>
  )
}
Example #14
Source File: BrandAssetsPage.jsx    From pooltogether-landing-site with MIT License 4 votes vote down vote up
BrandAssetsPage = (props) =>  {
  const controls = useAnimation()
  const [ref, inView] = useInView()

  useEffect(() => {
    if (inView) {
      controls.start('visible')
    }
  }, [controls, inView])

  return <>
    <div
      className='pool-container mx-auto flex flex-col text-base h-full z-10 relative mb-20'
    >
      <h4
        className='my-0'
      >
        Brand Assets
      </h4>

      <h2
        className='mb-6'
      >
        PoolTogether Logos &amp; Usage
      </h2>

      <p>
        Here is a handy zipped-up package of all the latest logos, wordmarks, and symbols to assist you in building PoolTogether integrations or linking to us:
      </p>

      <BoxLinkWithIcon
        isExternal
        href='https://github.com/pooltogether/pooltogether--brand-assets/blob/141936c859553a2a42ac96ed807551b85a4d56d9/pooltogether-brand-assets-v1.2.0.zip?raw=true'
        title='Download brand assets zip package'
        icon={'download'}
      >
        pooltogether-brand-assets-v1.2.0.zip
      </BoxLinkWithIcon>

      <br/>

      <h4
        className='my-5'
      >
        By Style
      </h4>

      <p>
        If you would rather download one or two specific styles you can find them on the <a href='https://github.com/pooltogether/pooltogether--brand-assets'>GitHub brand assets repository</a>.
      </p>

      
      <div className='my-5'>
        <p className='text-base my-0 text-accent-1'>
          Examples:
        </p>

        <motion.div
          className={classnames(
            'flex flex-col xs:flex-row xs:flex-wrap justify-start items-start',
            'mt-2 mb-4 px-4 xs:px-8 rounded-xl -mx-4 lg:-mx-8',
          )}
          ref={ref}
          animate={controls}
          initial='hidden'
          variants={{
            visible: {
              transition: {
                staggerChildren: 0.2
              }
            },
            hidden: {
            },
          }}
        >
          <GridItemBrandAssets
            title={`Purple Wordmark`}
            img={PoolTogetherPurpleWordmarkImg}
          />
          <GridItemBrandAssets
            title={`White Mark`}
            img={PoolTogetherWhiteMarkImg}
          />
          <GridItemBrandAssets
            title={`Trophy`}
            img={PoolTogetherTrophyImg}
          />
        </motion.div>


      </div>
      
      <h4
        className='my-5'
      >Usage</h4>

      <p>
        We would like you to use any of the the assets 'as is'. If you need a modified version of any of the logos feel free to <a
          href='mailto:[email protected]'
        >reach out to us</a> and we'll be happy to help.
      </p>

      <p>
        Please do not use any of the PoolTogether assets as the logo or in your logo for your app or brand. Thanks!
      </p>
    </div>
  </>

}
Example #15
Source File: IndexIntegrations.jsx    From pooltogether-landing-site with MIT License 4 votes vote down vote up
IndexIntegrations = () => {
  const controls = useAnimation()
  const [ref, inView] = useInView()

  useEffect(() => {
    if (inView) {
      controls.start('visible')
    }
  }, [controls, inView])

  const containerVariants = {
    visible: {
      transition: {
        staggerChildren: 0.2
      }
    },
    hidden: {}
  }

  return (
    <>
      <div className='bg-secondary'>
        <div className='pool-container mx-auto pt-12 pb-6 sm:pt-20 sm:pb-16'>
          <div className='lg:px-20'>
            <div className='flex items-center justify-between'>
              <h1 className='leading-10 sm:leading-tight'>
                <div className='text-flashy'>Protocol</div>{' '}
                <div className='block -mt-2'>Integrations</div>
              </h1>
            </div>

            <div className='flex flex-col py-4'>
              <p className='text-sm xs:text-xl sm:text-xl lg:text-3xl lg:max-w-3xl'>
                Try community-built interfaces and get inspired by what you can build on the
                PoolTogether protocol.
              </p>

              <motion.div
                className={classnames(
                  'flex flex-col sm:flex-row sm:flex-wrap',
                  'mt-8 mb-4 rounded-xl text-base lg:text-lg -mx-4 sm:-mx-4 lg:-mx-8'
                )}
                ref={ref}
                animate={controls}
                initial='hidden'
                variants={containerVariants}
              >
                {/* <GridItem
                title={'Argent'}
                description={`Use the Argent app to join the pool.`}
                img={ArgentSvg}
                url='https://www.argent.xyz/'
              /> */}

                <GridItem
                  altBg
                  title={'Dharma'}
                  description={`Deposit into PoolTogether from your US bank.`}
                  img={DharmaSvg}
                  url='https://www.dharma.io/'
                />

                <GridItem
                  altBg
                  title={'ZapperFi'}
                  description={`Join PoolTogether using this portal to DeFi.`}
                  img={ZapperFiSvg}
                  url='https://www.zapper.fi/#/dashboard'
                />

                <GridItem
                  altBg
                  title={'Zerion'}
                  description={`Access DeFi & view your PoolTogether deposits.`}
                  img={ZerionSvg}
                  url='https://zerion.io/'
                />

                <GridItem
                  altBg
                  title={'Twitter Bot'}
                  description={`Updates each time someone joins or wins!`}
                  img={BotSvg}
                  url='https://twitter.com/PoolTogetherBot'
                  attribution={`bot icon by Sophia Bai from the Noun Project`}
                />
                {/* 
              <GridItem
                title={'EBO'}
                description={`EBO Finance is a wallet app for joining the pool.`}
                img={EBOSvg}
                url='https://ebo.io/'
              /> */}
              </motion.div>
            </div>
          </div>

          <div className='bg-card rounded-xl mx-auto text-center p-4 xs:p-12 sm:pt-12 sm:pb-12 sm:mt-10'>
            <div className='flex flex-col items-center'>
              <h2 className='mt-4 mb-8 text-center'>Check out our developer documentation</h2>
              <p className='text-sm xs:text-lg sm:text-xl max-w-lg text-center'>
                Learn about the PoolTogether protocol and emerging use cases
              </p>

              <ButtonLink
                secondary
                textSize='2xl'
                href='https://docs.pooltogether.com'
                as='https://docs.pooltogether.com'
                className='my-8 w-3/4 sm:w-1/2'
              >
                Go to docs
              </ButtonLink>
            </div>
          </div>
        </div>
      </div>
    </>
  )
}
Example #16
Source File: IndexSupportedBy.jsx    From pooltogether-landing-site with MIT License 4 votes vote down vote up
IndexSupportedBy = () => {
  const controls = useAnimation()
  const [ref, inView] = useInView()

  useEffect(() => {
    if (inView) {
      controls.start('visible')
    }
  }, [controls, inView])

  const containerVariants = {
    visible: {
      transition: {
        staggerChildren: 0.12
      }
    },
    hidden: {}
  }

  return (
    <div id='backed-by' className='bg-darkened text-center pt-12 pb-6 sm:pt-20 sm:pb-16'>
      <div className='pool-container mx-auto'>
        <h3 className='text-sm xs:text-lg sm:text-xl my-0 sm:mb-12 leading-tight'>
          Protocol supported by
        </h3>

        <motion.div
          className={classnames(
            'flex flex-col xs:flex-row xs:flex-wrap justify-start items-start',
            'mt-2 mb-4 px-4 xs:px-8 rounded-xl -mx-4 sm:-mx-12 lg:-mx-16'
          )}
          ref={ref}
          animate={controls}
          initial='hidden'
          variants={containerVariants}
        >
          <GridItemSupportedBy
            title={'ConsenSys'}
            img={ConsensysSvg}
            url='https://www.consensys.com'
          />

          <GridItemSupportedBy
            title={'IDEO'}
            img={IdeoSvg}
            url='https://www.ideo.com'
            maxHeight={30}
          />

          <GridItemSupportedBy
            title={'DTC Capital'}
            img={DTCCapitalSvg}
            url='https://www.dtc.capital'
          />

          <GridItemSupportedBy title={'ParaFi'} img={ParaFiSvg} url='https://www.parafi.capital/' />

          <GridItemSupportedBy
            title={'MetaCartel Ventures'}
            img={MetaCartelSvg}
            url='https://metacartel.org'
          />

          <GridItemSupportedBy title={'The LAO'} img={TheLaoSvg} url='https://thelao.io' />

          <GridItemSupportedBy
            title={'Robot Ventures'}
            img={RobotVenturesSvg}
            url='https://twitter.com/robotventures'
          />
        </motion.div>

        {/* <div className='flex justify-center items-center sm:-mx-2'>
        <a
          href='https://makerdao.com'
          title='View the Maker site'
          target='_blank'
          rel='noopener noreferrer'
        >
          <img
            src={MakerDaoSvg}
            className='mt-4'
          />
        </a>
      </div> */}
      </div>
    </div>
  )
}
Example #17
Source File: footer.js    From ar-episode2 with MIT License 4 votes vote down vote up
Footer = ({ setHamburgerPosition, onCursor }) => {
  const instagramRef = useRef(null)
  const instagramPosition = useElementPosition(instagramRef)

  const facebookRef = useRef(null)
  const facebookPosition = useElementPosition(facebookRef)

  const vimeoRef = useRef(null)
  const vimeoPosition = useElementPosition(vimeoRef)

  const animation = useAnimation()
  const [footerRef, inView] = useInView({
    triggerOnce: true,
    rootMargin: "-100px",
  })
  useEffect(() => {
    if (inView) {
      animation.start("visible")
    }
  }, [animation, inView])

  const menuHover = x => {
    onCursor("locked")
    setHamburgerPosition({ x: x })
  }

  return (
    <FooterNav
      ref={footerRef}
      animate={animation}
      initial="hidden"
      variants={{
        visible: {
          opacity: 1,
          y: 0,
          transition: { duration: 0.8, ease: [0.6, 0.05, -0.01, 0.9] },
        },
        hidden: { opacity: 0, y: 72 },
      }}
    >
      <Container>
        <Flex spaceBetween>
          <FooterContent>
            <p>902.315.1279</p>
            <p>[email protected]</p>
          </FooterContent>
          <FooterContent wider>
            <p>15 Camburhill Ct Unit C</p>
            <p>Charlottetown, PE C1E 0E2</p>
          </FooterContent>
          <FooterSocial>
            <a
              onMouseEnter={() => menuHover(instagramPosition.x)}
              onMouseLeave={onCursor}
              ref={instagramRef}
              href="/"
              target="_blank"
            >
              <Instagram />
            </a>
            <a
              onMouseEnter={() => menuHover(facebookPosition.x)}
              onMouseLeave={onCursor}
              ref={facebookRef}
              href="/"
              target="_blank"
            >
              <Facebook />
            </a>
            <a
              onMouseEnter={() => menuHover(vimeoPosition.x)}
              onMouseLeave={onCursor}
              ref={vimeoRef}
              href="/"
              target="_blank"
            >
              <Vimeo />
            </a>
          </FooterSocial>
        </Flex>
      </Container>
    </FooterNav>
  )
}
Example #18
Source File: SubmitForm.js    From webappdevtest with MIT License 4 votes vote down vote up
export function SubmitForm(props) {
    const {desktopSize, selectedCity, onNewLinkSubmit} = props
    const [isOpen, setIsOpen] = useState(window.innerWidth > desktopSize);
    const [isThankYou, setIsThankYou] = useState(false);
    const linkEl = useRef(null);
    const cityEl = useRef(null);
    const containerControls = useAnimation();
    const closeButtonControls = useAnimation();
    const chevronControls = useAnimation();
    const toggleButtonLabelControls = useAnimation();

    const container_variants = {"open": {height: 470, top: `calc(var(--vh, 1vh) * 100 - 470px)`},"close": {height: 50, top: `calc(var(--vh, 1vh) * 100 - 50px)`}}
    const closeButton_variants = {"open": {backgroundColor: '#1f2532'},"close": {backgroundColor: (window.innerWidth < desktopSize ? '#2d3142' : '#FF5853')}}
    const chevron_variants = {"open": {rotate: 0}, "close": {rotate: 180}}
    const toggleButton_variants = {"open": {opacity: 0}, "close": {opacity: 1}}

    useEffect(()=>{
        if(isOpen) {
            setIsOpen(selectedCity === null)
        }
    }, [selectedCity])

    containerControls.start(container_variants[isOpen ? "open": "close"])
    closeButtonControls.start(closeButton_variants[isOpen ? "open": "close"])
    chevronControls.start(chevron_variants[isOpen ? "open": "close"])
    toggleButtonLabelControls.start(toggleButton_variants[isOpen ? "open": "close"])

    const handleCloseToggle = () => {
        setIsOpen(!isOpen)
        !isOpen && Event("UserAction", "Opened submit link form", window.innerWidth > desktopSize ? "DESKTOP": "MOBILE")
        !isOpen && setIsThankYou(false)
        chevronControls.start({scale: 1})
    }

    return(
        <motion.div
            className="submitFormContainer"
            variants = {container_variants}
            initial = {isOpen? "open" : "close"}
            animate = {containerControls}
            transition = {{
                type: 'spring',
                damping: 16
            }}
            drag="y"
            dragConstraints={{top: 0, bottom:0}}
            dragMomentum={false}
            onDragEnd={(e, info) => {if((info.point.y > 10 && isOpen) || (info.point.y < -10 && !isOpen)) {handleCloseToggle()}}}
        >
            <motion.button
                className="toggleCloseButton"
                variants = {closeButton_variants}
                initial = {isOpen? "open" : "close"}
                animate = {closeButtonControls}
                onHoverStart = {() => chevronControls.start({scale: 1.3})}
                onHoverEnd = {() => chevronControls.start({scale: 1})}
                onClick={() => {
                    handleCloseToggle();
                }}
            >
                <motion.img
                    src={isOpen ? chevron_primary : chevron_white}
                    alt="toggle submit form button"
                    variants = {chevron_variants}
                    initial = {isOpen? "open" : "close"}
                    animate={chevronControls}
                />
                <motion.p
                    variants= {toggleButton_variants}
                    initial = {isOpen ? "open" : "close"}
                    animate={toggleButtonLabelControls}
                >Add to the map!p</motion.p>
            </motion.button>
            {!isThankYou &&
                <motion.div
                    className="submitFormBody"
                >
                    <h2>Add more to the map</h2>
                    <p>
                      What does this form do?
                    </p>
                    <form
                        onSubmit={(e) => {
                            e.preventDefault()
                            onNewLinkSubmit({
                                "link": linkEl.current.value,
                                "city": cityEl.current.value
                            })
                            linkEl.current.value = '';
                            cityEl.current.value = '';
                            setIsThankYou(true);
                            window.scrollTo(0, 0);
                        }}
                    >
                        <label htmlFor="form_link" className="field">
                            <span className="form_label">Link:</span>
                            <input required id="form_link" type="url" ref={linkEl} placeholder="https://..."/>
                        </label>
                        <label htmlFor="form_city" className="field">
                            <span className="form_label">City:</span>
                            <input required id="form_city" type="text" ref={cityEl} placeholder="Where did the protest happen?"/>
                        </label>
                        <motion.button
                            type= "submit"
                            className = "primary_btn submitButton"
                            whileHover = {{scale: 1.02}}
                            whileTap = {{scale: 0.98}}
                        >
                            Submit for review
                        </motion.button>
                    </form>
                    {/* <p className="sendVideoMessage">Want to send us the video instead, our WhatApp is open at +91-xxx-xxx-xxxx</p> */}
                </motion.div>
            }
            {isThankYou &&
                <div className="thankYouBody">
                    <h1>You are a rockstar!</h1>
                    <p>We appreciate your contribution. We will review the link you submitted and add it to the map as soon as we can</p>
                    <motion.button
                        onClick={() => handleCloseToggle()}
                        whileHover = {{scale: 1.02}}
                        whileTap = {{scale: 0.98}}
                        className= "primary_btn doneButton"
                    >OK
                    </motion.button>
                    <motion.img
                        src={fist}
                        initial = {{y:0}}
                        animate = {{y:10}}
                        transition = {{
                            yoyo: 'Infinity',
                            ease: 'easeInOut'
                        }}
                    />
                </div>
            }

        </motion.div>
    )
}
Example #19
Source File: HomeFeatured.js    From ar-episode2 with MIT License 4 votes vote down vote up
HomeFeatured = ({ onCursor }) => {
  const [hovered, setHovered] = useState(false)
  const animation = useAnimation()
  const [featured, inView] = useInView({
    triggerOnce: true,
    rootMargin: "-300px",
  })

  useEffect(() => {
    if (inView) {
      animation.start("visible")
    }
  }, [animation, inView])

  return (
    <HomeFeaturedSection
      ref={featured}
      animate={animation}
      initial="hidden"
      variants={{
        visible: {
          opacity: 1,
          y: 0,
          transition: { duration: 0.8, ease: [0.6, 0.05, -0.01, 0.9] },
        },
        hidden: { opacity: 0, y: 72 },
      }}
    >
      <Container>
        <Link to="/">
          <FeaturedContent
            onHoverStart={() => setHovered(!hovered)}
            onHoverEnd={() => setHovered(!hovered)}
            onMouseEnter={() => onCursor("hovered")}
            onMouseLeave={onCursor}
          >
            <Flex spaceBetween>
              <h3>Featured Project</h3>
              <motion.div
                animate={{ opacity: hovered ? 1 : 0 }}
                transition={{ duration: 0.6, ease: [0.6, 0.05, -0.01, 0.9] }}
                className="meta"
              >
                <h4>PEI Seafood</h4>
                <h4>2019</h4>
              </motion.div>
            </Flex>
            <h2 className="featured-title">
              NOT <br /> HUMBLE
              <span className="arrow">
                <motion.svg
                  animate={{ x: hovered ? 48 : 0 }}
                  transition={{ duration: 0.6, ease: [0.6, 0.05, -0.01, 0.9] }}
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 101 57"
                >
                  <path
                    d="M33 34H0V24h81.429L66 7.884 73.548 0l19.877 20.763.027-.029L101 28.618 73.829 57l-7.548-7.884L80.753 34H33z"
                    fill="#FFF"
                    fillRule="evenodd"
                  ></path>
                </motion.svg>
              </span>
            </h2>
          </FeaturedContent>
          <FeaturedVideo>
            <video
              loop
              autoPlay
              src={require("../../assets/video/featured-video.mp4")}
            ></video>
          </FeaturedVideo>
        </Link>
      </Container>
      <Container>
        <FeaturedProjects>
          <Flex flexEnd>
            <button>
              <span>All Projects</span>
            </button>
          </Flex>
        </FeaturedProjects>
      </Container>
    </HomeFeaturedSection>
  )
}
Example #20
Source File: CityDetailView.js    From webappdevtest with MIT License 4 votes vote down vote up
export function CityDetailView(props) {
    const {selectedCity, videoData, onCityDetailClose, desktopSize } = props;
    let currentScrollValue = useMotionValue(0);
    let touchStart = 0;
    let touchEnd = 0;
    const cityDetailViewEl = useRef(null)
    // let prevScrollValue = useMotionValue(0);
    const containerAnimControls = useAnimation();
    const headerAnimControls = useAnimation();
    const bodyAnimControls = useAnimation();

    const closeTransition = {ease: 'easeOut', duration: 0.2}
    const openTransition = {type: 'spring', damping: 16}

    const variants = {
        open: (window.innerWidth > desktopSize) ? {width: '30em', top: 0, transition: openTransition}:{width: 'calc(var(--vw, 1vw) * 100)', top: 'calc(var(--vh, 1vh) * 20)', transition: openTransition},
        close: (window.innerWidth > desktopSize) ? {width: 0, top: 0, y: 0, transition: closeTransition} : {width: 'calc(var(--vw, 1vw) * 100)', top: 'calc(var(--vh, 1vh) * 100)', y: 0, transition: closeTransition}
    }

    const childVariants = {
        open: {opacity: 1, y: 0, transition: {ease: 'easeOut'}}, close: {opacity: 0, y: 10, transition: {ease: 'linear'}}
    }

    const scrollToTop = {top: 0, transition:{ease:'linear', duration: 0.2}}

    const handleInOutAnimation = async () => {
        if(selectedCity) {
            containerAnimControls.start(variants.open)
            await headerAnimControls.start(childVariants.open)
            bodyAnimControls.start(childVariants.open)
        }
        else { 
            await headerAnimControls.start(childVariants.close)
            await bodyAnimControls.start(childVariants.close)
            containerAnimControls.start(variants.close)
        }
    }

    useEffect(()=> {
        cityDetailViewEl.current.scrollTo(0,0);
        handleInOutAnimation();
        cityDetailViewEl.current.addEventListener('touchstart', function(e){touchStart=e.changedTouches[0].clientY})
        cityDetailViewEl.current.addEventListener('touchend', function(e) {
        touchEnd = e.changedTouches[0].clientY;
        if(currentScrollValue.get() <= 0 && touchEnd > touchStart) {
            onCityDetailClose();
            touchStart = 0;
            touchEnd = 0;
        }
        });

        // window.addEventListener('wheel', function() {
        //     setTimeout(()=> {
        //         if(currentScrollValue.get() === prevScrollValue.get()) {
        //             onCityDetailClose();
        //             prevScrollValue.set(0)
        //         }
        //         else {
        //             prevScrollValue.set(currentScrollValue.get())
        //         }
        //     }, 500)
        // })
    }, [selectedCity])

    return (
        <AnimatePresence>
            <motion.div
                className="cityDetailView"
                ref = {cityDetailViewEl}
                variants={variants}
                initial="close"
                exit="close"
                animate = {containerAnimControls}
                onScroll = {(e) => {
                    currentScrollValue.set(e.nativeEvent.target.scrollTop);
                    if(currentScrollValue.get() > 0) {
                        containerAnimControls.start(scrollToTop)
                    }
                }}
                style={{height: 'calc(var(--vh, 1vh) * 100)', overflow: 'scroll', scrollBehavior: 'smooth', overscrollBehaviorY: 'none'}}
            >   
                <motion.div 
                    className="cityDetailView_Header" 
                    variants={childVariants}
                    initial="close"
                    animate = {headerAnimControls}
                >
                    <h1>{selectedCity}</h1>
                    <button className="close_btn" onClick={(e) => onCityDetailClose(e)}>
                        <img src={close} alt="close icon" />
                    </button>
                </motion.div>
                <motion.div 
                    className="cityDetailView_videoList" 
                    variants={childVariants}
                    initial="close"
                    animate={bodyAnimControls}
                    
                >
                    {videoData[selectedCity].blocks.slice(0).reverse().map((videoObj, index) => {
                        if(videoObj.link.indexOf('twitter.com') !== -1) {
                            let id = videoObj.link.split(/\/?\//)[4].split('?')[0];
                            return (
                                <div className="linkCard" key={id + index}>
                                    <p>{videoObj.date}</p>
                                    <h2>{videoObj.caption}</h2>
                                    <TwitterVideoEmbed id={id} 
                                        onLoad={e => {if(e){e.style.display = "inline-block"}}} 
                                    />
                                </div>
                            )
                        }
                        else if(videoObj.link.indexOf('instagram.com') !== -1) {
                            
                            return (
                                <div className="linkCard" key={videoObj.link+ index}>
                                    <p>{videoObj.date}</p>
                                    <h2>{videoObj.caption}</h2>
                                    <InstagramEmbed url={videoObj.link} 
                                        onLoad={e => {if(e){e.style.display = "inline-block"}}} 
                                    />
                                </div>
                            )
                        }

                        else {
                            return (
                                <div className="linkCard" key={index}>
                                    <p>{videoObj.date}</p>
                                    <h2>{videoObj.caption}</h2>
                                    <a href={videoObj.link} target="_blank" className='rawLink'>{videoObj.link} </a>
                                </div>
                            )
                        }   
                    })}
                </motion.div>  
              
            </motion.div>
        </AnimatePresence>
    )
}