# Styled Components

v5+

# Basics

// **Elements/Title.js**
import styled from "styled-components";

const Title = styled.h1`
  color: red;
`;

export default Title;
// **App.js**
import Title from "Elements/Title";

let App = () => {
  return (
    <div>
      <Title> foo </Title>
    </div>
  );
};

# Passed Props

// style
background: ${(props) => (props.primary ? "cyan" : "transparent")};
color: ${(props) => (props.color || "red"};

// jsx
<div>
  <Title primary> foo </Title>
  <Title color="blue"> foo </Title>
</div>

# Extend

// Base button
let Button = styled.button`
  color: red;
  padding: 2rem;
  margin: 2rem;
  background: transparent;
`;

// extend - AnyStyledComponent
// StyledComp are just ReactComponent
let ButtonDark = styled(Button)`
  background: #333;
`;
// jsx
<div>
  <Button> foo </Button>
  <ButtonDark> bar </ButtonDark>
  {// Also we can swap elements with
  // newTag / AnyReactComponent}
  <Button as="a" href="/">
    fooLink
  </Button>
</div>

# Styling any Components

  • It's same as extend above. Just with AnyReactComponent
  • Needs className
// ReactConponent
// If (props) is passed then
// use props.className , props.children
let Link = ({ className, children }) => {
  return (
    <a className={className} href="/">
      {children}
    </a>
  );
};

// StyledComponent
let LinkDark = styled(Link)`
  background: #333;
`;
// jsx
<div>
  <Link> foo </Link>
  <LinkDark> bar </LinkDark>
</div>

# Css Nesting

  • Provided by Stylis.
const Button = styled.button`
  color: red;

  // & = parentComponent

  &:hover {
    color: blue;
  }

  & ~ & {
    color: green;
  }

  // no space after dot
  &.myclass {
    color: black;
  }

  // space after dot (& is not needed)
  & .myinnerclass {
    color: white;
  }
`;
// jsx
<Button>foo</Button>
<Button>foo sibling</Button>
<Button className="myclass"></Button>
<Button>
  <div className="myinnerclass"> Zoo </div>
</Button>

# Attaching additional props/attrs

let Input = styled.input.attrs((props) => ({
  type: "text",
  size: props.size || "1em",
}))`
  color: red;
  background: #666;
`;

// we can override too
// Just extend then change
let Password = styled(Input).attrs((props) => ({
  type: "password",
}))`
  color: black;
  background: green;
`;
// jsx
<Input placeholder="foo" />
<Input placeholder="foo" size="3em" />

<Password
  placeholder="secret"
  size="2em"
/>

# Animations

// Gives unique instance to avoid nameclash
let rotate = keyframes`
  from{
    transform : rotate(0deg);
  }
  to{
    transform : rotate(360deg);
  }
`;

let Rotate = styled.div`
  animation: ${rotate} 2s linear infinite;
`;
// jsx
<Rotate> I'm rotating </Rotate>

# Advanced

# Theme

  • <ThemeProvider> uses ContextAPI.
// global theme
let theme = {
  primary: "grey",
};

// button
let Button = styled.button`
  color: ${(props) => props.theme.primary};
`;

// default theme for button
Button.defaultProps = {
  theme: {
    primary: "blue",
  },
};

// global theme2 (function)
// inherit from parent <ThemeProvider>
let theme2 = ({ primary }) => ({
  primary: "green",
  secondary: primary, // red
});
// jsx
<Button>DefaultColor</Button>

<ThemeProvider theme={theme}>
  <Button>ThemeColor</Button>

  <ThemeProvider theme={theme2}>
    <Button>Theme2Color</Button>
  </ThemeProvider>

  <Button theme={{primary:"red"}}>
    OverrideThemeColor
  </Button>

</ThemeProvider>

# API

# css helper

import { css } from "styled-components";

let styles = css`
  color: red;
`;

// We can also add internally
let Button = styled.button`
  color: grey;

  ${(props) =>
    props.success &&
    css`
      color: blue;
    `}

  ${(props) =>
    props.danger &&
    css`
      color: red;
    `}
`;
// jsx
<Button>normal</Button>
<Button success>success</Button>
<Button danger>danger</Button>

# Tooling

# Stylelint

  • Avoid it since my stylint config for react-refresh-app is working nicely for StyledComponents too.