Search code examples
reactjsstyled-components

Styling Generic Component with Styled Components


I'm running into annoying typescript errors when trying to style my generic component like follows:

const StyledParentComponent = styled(ParentComponent)`
  ${GenericComponent} {
    ...
  }
`;

It throws a bunch of errors about JSX not being assignable to some Interpolation type.

Here is a small example that produces the error:

import styled from "styled-components";

const ParentComponent = () => {
  return (
    <ParentComponentContainer>
      <GenericComponent value={10} />
    </ParentComponentContainer>
  );
};

interface GenericComponentProps<T> {
  value: T;
  className?: string;
}

const GenericComponent = <T,>({
  value,
  className,
}: GenericComponentProps<T>) => {
  console.log(value);

  return (
    <GenericComponentContainer>
      Logging generic component value
    </GenericComponentContainer>
  );
};

const GenericComponentContainer = styled.div``;

const RegularComponent = () => {
  return <RegularContainer></RegularContainer>;
};

const RegularContainer = styled.div``;

const ParentComponentContainer = styled.div` 
  // this is where it will throw the error
  ${GenericComponent} {
    display: flex;
  }

  ${RegularContainer} {
    display: flex;
  }
`;

I was running what the standard pattern is for dealing with this issue. It's important that I'm able to style it this way so that I can have generic components as children and be able to style them with the above pattern.


Solution

  • I think your GenericComponent itself needs to be styled(GenericComponent) in order to be used within a style block.

    We use something like this in our codebase.

    const StyledGenericComponent = styled(GenericComponent)`
      color: green;
    `;
    
    const Container = styled.div`
      ${StyledGenericComponent} {
          color: red;
      }
    `;
    

    However to keep the generic types flowing through we have to use a satisfies.

    const StyledGenericComponent = styled(GenericComponent)``
      satisfies typeof GenericComponent;