Search code examples
javascripttypescriptmixinsstyled-components

Reusable parametric css with styled components


I'm using styled-components library in my react app and I've come across an interesting problem I wasn't able to find an elegant solution to online. What I want to achieve is to have a reusable piece of code, maybe similar to sass mixins, that would allow me to extend all my buttons with code that animates background darken on hover.

const DarkenHover = css<{ active?: boolean; normalColor: string; activeColor: string }>`
    background-color: ${p => (p.active ? p.normalColor : p.activeColor)};
    &:hover {
        background-color: ${p => darken(0.1)(p.active ? p.normalColor : p.activeColor)};
    }
    transition: background-color .1s ease-in;
`;

const FooButton = styled.div<{ active?: boolean }>`
    ${p => DarkenHover({
        active: p.active,
        normalColor: "red",
        activeColor: "blue",
    })}
`;

const FooButton = styled.div<{ active?: boolean }>`
    ${p => DarkenHover({
        active: p.active,
        normalColor: "white",
        activeColor: "green",
    })}
`;

This obviously is not valid syntax but it demonstrates my use case. How can I use this DarkenHover css object with attributes?


Solution

  • You can save the styles in a var and reuse later.

    const animation = css`
     background-color: ${p => p.active ? ThemeColors.backgroundDark : "white"};
        &:hover {
            background-color: ${p =>  darken(0.1)(p.active ? p.normalColor : p.activeColor)};
        }
        transition: background-color .1s ease-in;
     }
    `;
    

    The when you use it in another component, it should be able to access its props:

    const FooButton = styled.div`
        ${animation};
    `
    

    Also to be able to have separate props per each styled components, those can be passed via attrs method:

    const FooButton = styled.div.attrs({normalColor: '#000000' })`
       ${animation}
    `;