Soiloui
Soiloui

Reputation: 13

React + Typescript + Styled Components pass props to keyframes & conditioning

I'm trying to pass props to keyframe element & do some conditional animation. Here's my code:

import styled, { keyframes } from "styled-components";
import {
  PRIMARY,
  SECONDARY,
  DANGER,
  TEXT,
  OUTLINE,
} from "../../constans";

interface PropTypes {
  color?: string;
  variant?: string;
  size?: string;
  shadow?: boolean;
  disabled?: boolean;
  hoverAnimation?: boolean;
}

const StyledButton = styled.button<PropTypes>`
  // [... SOME CODE ...]
  animation: ${(props) => hoverAnimate(props)} 2s infinite;
`;

const hoverAnimate = (props: PropTypes) => keyframes`
        100%{
            color: ${() => {
              console.log(props);
              if (props.variant) {
                if (props.color) {
                  return `var(--color-${props.color})`;
                }
                return "#444";
              }
              return "#fff";
            }};

            background: ${() => {
              if (props.variant === TEXT || props.variant === OUTLINE)
                return "#f00";
              console.log("object");
              if (props.color === PRIMARY) return "var(--color-primary)";
              if (props.color === SECONDARY) return "var(--color-secondary)";
              if (props.color === DANGER) return "var(--color-danger)";
              return "var(--color-default)";
            }};
        }
`;

What am I doing wrong?

TS complains:

Argument of type '() => string' is not assignable to parameter of type 'SimpleInterpolation'. Type '() => string' is missing the following properties from type 'readonly SimpleInterpolation[]': concat, join, slice, indexOf, and 17 more.

And, console.log(props) prints:

object

It's like a string. I can't expand this object in dev tools (even if try destructure).

Upvotes: 1

Views: 2473

Answers (1)

Ajeet Shah
Ajeet Shah

Reputation: 19813

It appears like you are trying to use an IIFE (immediately invoked function expression) to return a "string" that would be used inside template strings.

But you are getting TypeScript error:

Argument of type '() => string' is not assignable to parameter of type 'SimpleInterpolation'.

because your current code:

const hoverAnimate = (props: PropTypes) => keyframes`
  100%{
    color: ${() => {
      if (props.variant) {
        if (props.color) {
          return `var(--color-${props.color})`;
        }
        return "#444";
      }
      return "#fff";
    }};
    ...

doesn't properly call the IIFE.

Here is how to fix it by calling (note the additional ()s) the IIFE:

const hoverAnimate = (props: PropTypes) => keyframes`
  100%{
    color: ${(() => { // Here, at start
      if (props.variant) {
        if (props.color) {
          return `var(--color-${props.color})`;
        }
        return "#444";
      }
      return "#fff";
    })()}; // And, here
    ...

You need to do the same for background as well.

Upvotes: 1

Related Questions