Demian Sims
Demian Sims

Reputation: 921

Passing a direction prop into styled-components keyframe component?

I'm trying to implement a reusable text animation component where a direction prop can be passed in. I probably close but doesn't seem to be working. Also open to better ways of implementing it a better way.

import React from "react"
import styled from "styled-components"
import { GlobalStyles } from "./global"
import TextAnimations from "./Components/TextAnimations"

const Container = styled.div`
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
`
const NavBar = styled.nav`
  background: #3a3a55;
  padding: 0.25rem;
  width: 100%;
  height: 10vh;
`
const Main = styled.main`
  background: #3a3a55;
  color: white;
  padding: 0.25rem;
  flex: 10 1 auto;
  height: 100vh;
`

const Break = styled.div`
  flex-basis: 100%;
  width: 0;
`

function App() {
  return (
    <>
      <GlobalStyles />
      <Container>
        <NavBar>NavBar</NavBar>
        <Break />
        <Main>
          <TextAnimations text='Sample text from the left' direction='left' />
          <TextAnimations text='Sample text from the right' direction='right' />
        </Main>
      </Container>
    </>
  )
}

export default App

and then the animation component:

import { motion } from "framer-motion"
import styled, { keyframes } from "styled-components"

type TextAnimationProps = {
  text: string
  direction: string
}

const Left = keyframes`
  0% { left: -3.125em; }
  100% { left: 3em;}
`

const Right = keyframes`
  0% { Right: -3.125em; }
  100% { Right: 3em;}
`

const HomeHeader = styled.div`
  h1 {
    font-weight: lighter;
  }
  position: relative;
  top: 0;
  animation: ${(props) => (props.defaultValue === "left" ? Left : Right)} // is this right?
  animation-duration: 3s;
  animation-fill-mode: forwards;
`

const TextAnimations = ({ text, direction }: TextAnimationProps) => {
  return (
    <HomeHeader defaultValue={direction}>
      <h1>{text}</h1>
    </HomeHeader>
  )
}

export default TextAnimations

I'd also like to make it more flexible so that I can add 'top', 'bottom', etc.

Is this the best way to handle text animations?

Upvotes: 0

Views: 1022

Answers (1)

Ivan Popov
Ivan Popov

Reputation: 696

You can create a separate function to set the animation. The function will receive the props of the styled component from which the function will access the direction prop.

const setHomeHeaderAnimation = ({ direction = "left" }) => {
  const animation = keyframes`
    0% {
      ${direction}: -3.125em; 
    }
    100% { 
      ${direction}: 3em;
    }
  `;
    
  return css`
    position: relative;
    animation: ${animation};
    animation-duration: 3s;
    animation-fill-mode: forwards;
  `;
};

const HomeHeader = styled.div`
  ${setHomeHeaderAnimation}

  h1 {
    font-weight: lighter;
  }
`;

const App = () => (
  <div>
    <HomeHeader>
      <div>Some text</div>
    </HomeHeader>
    <HomeHeader direction="right">
      <div>Some text</div>
    </HomeHeader>
    <HomeHeader direction="top">
      <div>Some text</div>
    </HomeHeader>
    <HomeHeader direction="bottom">
      <div>Some text</div>
    </HomeHeader>
  </div>
);

Upvotes: 1

Related Questions