Search code examples
javascriptreactjsif-statementstyled-componentsternary

Use custom function for CSS property in styled-components?


I use styled components and I want to set the transform to:

  • value x if condition is true,
  • value y if condition 2 is true,
  • null if none are true.

I didn't find much information online so I tried something like:

const altDirectionFunc = (props) => {
    if (props.altDirection === 'row') {
        return 'translate(30%, -50%)'
    } else if (props.altDirection === 'column') {
        return 'translate(-50%, 30%)'
    } else {
        return null
    }
}

const StyledCheckbox = styled.div`
    position: relative; 
    height: 2.5em;
    width: 2.5em;
    background: ${props => props.isChecked ? props.theme : 'transparent'};
    border-radius: 10px;
    border: 2px solid ${props => props.isChecked ? props.theme : vars.black};
    cursor: pointer;
    transition: all 400ms ease;
    border-radius: ${props => props.circular ? '50%' : null};
    &::before {
        font-family: "Font Awesome 5 Free";
        font-weight: 900;
        content: '${props => props.isChecked ? '\f00c' : null}';
        color: white;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -45%);
        font-weight: 900;
        font-size: 1.2em;
        transition: all 400ms ease;
        line-height: 16px;
    }
    &::after {
        content: '${props => props.altText}';
        opacity: ${props => props.isChecked ? '1' : '0'};
        transition: all 400ms ease;
        color: ${vars.black};
        position: absolute;
        left: 50%;
        top: 50%;
        width: max-content;
        transform: '${altDirectionFunc}'; // That's what matters
        font-family: ${vars.mainFont};

    }
`;

//

 <StyledTextField size={size} initalValue={initalValue} onChange={handleChange}
        fontFamily={fontFamily} theme={theme} {...otherProps} value={value} dir={direction}/>

However, I don't achive the result I want, there's no difference if I pass altDirection="row" or altDirection="column"

How can I fix it?

Seems like the transform isn't being called:

enter image description here

P.S. I used the ternary operator before, but this is much more clean. Is it not possible to use functions like that or did I made a mistake?


Solution

  • If I understand your question correctly, you'd like your styled component to call a custom function (ie altDirectionFunc) to obtain a value for the transform property.

    In your case, the syntax of your styling (with ' around the altDirectionFunc) will be causing incorrect styling to be evaluated for your component. Changing that to the following will allow the altDirectionFunc to be correctly called when the styled component is evaluated, and should achieve the desired result:

    transform: ${ (props) => altDirectionFunc(props) };
    

    Here's a complete example:

    const altDirectionFunc = (props) => {
        if (props.altDirection === 'row') {
            return 'translate(30%, -50%)'
        } else if (props.altDirection === 'column') {
            return 'translate(-50%, 30%)'
        } else {
            return 'unset' // Update this
        }
    }
    
    const StyledCheckbox = styled.div`
        position: relative; 
        height: 2.5em;
        width: 2.5em;
        background: ${props => props.isChecked ? props.theme : 'transparent'};
        border-radius: 10px;
        border: 2px solid ${props => props.isChecked ? props.theme : vars.black};
        cursor: pointer;
        transition: all 400ms ease;
        border-radius: ${props => props.circular ? '50%' : null};
        &::before {
            font-family: "Font Awesome 5 Free";
            font-weight: 900;
            content: ${props => props.isChecked ? '\f00c' : null}; // Fixed this too
            color: white;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -45%);
            font-weight: 900;
            font-size: 1.2em;
            transition: all 400ms ease;
            line-height: 16px;
        }
        &::after {
            content: ${props => props.altText}; // Fixed this too
            opacity: ${props => props.isChecked ? '1' : '0'};
            transition: all 400ms ease;
            color: ${vars.black};
            position: absolute;
            left: 50%;
            top: 50%;
            width: max-content;
            transform: ${ (props) => altDirectionFunc(props) }; // The fix
            font-family: ${vars.mainFont};
    
        }
    `;