Ashish Puttaa
Ashish Puttaa

Reputation: 65

Styled Components - How to style a component passed as a prop?

I am trying to build this simple component which takes title and Icon Component as props and renders them. The icons I use here are third party components like the ones from Material UI.

option.component.jsx

import { Wrapper } from './option.styles';

function Option({ title, Icon }) {
   return (
      <Wrapper>
         {Icon && <Icon />}
         <h4>{title}</h4>
      </Wrapper>
   );
}

option.styles.js

import styled from 'styled-components';

export const Wrapper = styled.div`
   display: flex;
   color: grey;

   &:hover {
      color: white;
   }
`;

// export const Icon = 

I've organized all my styles in a separate file and I intend to keep it that way.
I want to style <Icon /> , but I don't want to do it inside Option Component like this.

import styled from 'styled-components';
import { Wrapper } from './option.styles';

function Option({ title, Icon }) {
   const IconStyled = styled(Icon)`
      margin-right: 10px;
   `;

   return (
      <Wrapper>
         {Icon && <IconStyled />}
         <h4>{title}</h4>
      </Wrapper>
   );
}

What is the best way to style a component passed as a prop while maintaining this file organization?

I've looked through the documentation and I wasn't able find anything related to this. Any help would be appreciated.

Upvotes: 1

Views: 1887

Answers (1)

Luis Paulo Pinto
Luis Paulo Pinto

Reputation: 6036

You can do this in 2 ways:

1. As a SVG Icon (svg-icon):

option.styles.js as:

import styled from "styled-components";
import SvgIcon from "@material-ui/core/SvgIcon";


export const Wrapper = styled.div`
  display: flex;
  color: grey;

  &:hover {
    color: black;
  }
`;

export const IconStyled = styled(SvgIcon)`
  margin-right: 10px;
`;

And in your component, do like that:

import { Wrapper, IconStyled } from "./option.styles";

function Option({ title, Icon }) {
  return (
    <Wrapper>
      {Icon && <IconStyled component={Icon} />}
      <h4>{title}</h4>
    </Wrapper>
  );
}

const App = () => {
  return (
    <>
      <Option title="title" Icon={HomeIcon}></Option>
      <Option title="title" Icon={AccessAlarmIcon}></Option>
    </>
  );
};

2. As a Font Icon (font-icons):

Import material icons in <head>

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />

option.styles.js as:

import styled from "styled-components";
import Icon from "@material-ui/core/Icon";

export const Wrapper = styled.div`
  display: flex;
  color: grey;

  &:hover {
    color: black;
  }
`;

export const IconStyled = styled(Icon)`
  margin-right: 10px;
`;

And in your component, do like that:

import { Wrapper, IconStyled } from "./option.styles";

function Option({ title, icon }) {
  return (
    <Wrapper>
      {icon && <IconStyled>{icon}</IconStyled>}
      <h4>{title}</h4>
    </Wrapper>
  );
}

const App = () => {
  return (
    <>
      <Option title="title" icon='star'></Option>
      <Option title="title" icon='home'></Option>
    </>
  );
};

Upvotes: 3

Related Questions