Search code examples
cssreactjsstyled-components

Styled components props inside conditional props


My styled component code:

import React, { Component } from "react";
import PropTypes from "prop-types";
import styled, { ThemeProvider } from "styled-components";

import { theme } from "../shared/theme";

const ContainerDiv = styled.div`
    padding-bottom: ${props => props.theme.paddings.text.small};
    padding-top: ${props => props.theme.paddings.text.small};
    padding-left: ${props => props.theme.paddings.text.normal};
    padding-right: ${props => props.theme.paddings.text.normal};
    font-size: ${props => {
        if (props.bigLabel && props.bigLabel === true)
            return props.theme.typography.sizes.big;

        return props.theme.typography.sizes.normal;
    }};
    width: 100%;
    font-weight: ${props =>
        props.bold && props.bold === true ? "bold" : "normal"};
    ${props =>
        props.type &&
        props.type === "danger" &&
        `
        color: ${props => props.theme.colors.text.danger};
        `}
    ${props =>
        props.type &&
        props.type === "primary" && 
        `
        color: ${props => props.theme.colors.text.primary};
        `}
`;

class Text extends Component {
    static propTypes = {
        href: PropTypes.string,
        bold: PropTypes.bool,
        paragraph: PropTypes.bool,
        type: PropTypes.string
    };

    render = () => {
        let { href, bold, paragraph, type } = this.props;

        let content = this.props.children;
        if (paragraph && paragraph === true) content = <p>{content}</p>;

        return (
            <ThemeProvider theme={theme}>
                <ContainerDiv href={href} bold={bold} type={type}>
                    {content}
                </ContainerDiv>
            </ThemeProvider>
        );
    };
}

export default Text;

Using the type property is supposed to change the text color, but in my tests the desired color is not being applied:

<Text type="primary">Primary text</Text>
<Text type="danger">Danger text</Text>

In both cases the color remains the default one.

How do I properly set the text color according to my type property?


Solution

  • When using props within a ${props => declaration, you do not need to also call the function in the inner function because you have access to props from the outer function call.

    So this:

    ${props =>
      props.type &&
      props.type === "danger" &&
      `
        color: ${props => props.theme.colors.text.danger};
      `}
    

    would become this:

    ${props =>
      props.type &&
      props.type === "danger" &&
      `
        color: ${props.theme.colors.text.danger};
      `}
    

    notice how color is now color: ${props.theme.colors.text.danger}; instead of color: ${props => props.theme.colors.text.danger}

    Additionally I would consider another prop name instead of type because this will cause type to be rendered to the DOM in your HTML (because type is a valid HTML attribute).


    Also on a separate note, you can safely just check for props.type === "danger" instead of checking for the existence of props.type first, the result is the same.

    So ${props => props.type === "danger" && ...your styles