React Themes with Styled-Components
Tags: react, reactnative, programming
Published: 2023-03-15 15:18:30

## What is styled-components?
Styled-components is a library for styling React components. It lets you use CSS-in-JS by adding JavaScript logic to your CSS. This makes it simple to create dynamic styles for your React components and integrate your react component library.


## Advantages of Styled-Components

1. Easy to learn
2. Prevents class name collisions with unique class names
3. Dynamic and adaptive styles
4. Component-level styling for easier debugging
5. Server-side rendering support
6. Sass style support
7. Custom style theme support
8. Simple theme setup

## Getting Started with Styled-Components

This section will explore how to add the styled-components library to your React application, style React components, and add light and dark themes. First, create a React app and install the styled-components library by running one of the commands below:

`yarn add styled-components`

or

`npm install --save styled-components`

Once we install the library, we will start styling the application.

## Styling a React App with Styled-Components

Styled-components lets you add styles to React components with the react inline style styled interface. You'll use tagged template literals to pass style rules to the component.
import styled from "styled-components";
‍
`import styled from "styled-components";

const [Component Name] = styled.[DOM Element]`
  [CSS Style Rules]
`;`

The component name follows the React naming convention. Access the DOM element you want to style from the styled object and pass the style rules within template literals.

Styling a real-life project's nav will look similar to this code block:

`function App(){
  return <Nav /> 
}

const Nav = styled.nav`
  background-color: #fff;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 40px;
  border-bottom: 1px solid #878787;
`;`

The code block above creates a styled nav element. You can pass props or add JavaScript logic to styled-components.

`const MyComponent = styled.div`
    opacity: ${(props)=> props.show ? 1 : 0};
`;`

In the code block, the opacity style value depends on the show prop. If show is true in MyComponents, the div's opacity is 1, else 0. Use createGlobalStyle for global styles that are not tied to a specific component.

import { createGlobalStyle } from "styled-components";

`const GlobalStyle = createGlobalStyle`
  [global style rules]
`;

function App(){
  return (
    <div classname="app">
      <GlobalStyle />
      <Nav>
       <BrandText>Theme With Styled-Components</BrandText>
      </Nav>
      ...
    </div>
  );
}
`
The code block above creates a global styled component that we can use to style components outside its scope.

## React Themes
Styled components supports multiple themes for React apps; use ThemeProvider to provide the theme via a context API. To do so, pass a theme rule object as a value to its theme prop, access the theme rule in all styled-components using prop.theme, and set up a theme object in the theme folder.

`const darktheme = {
  primary: "#00bcd4",
  secondary: "#f3f3f3",
  border: "#e0e0e0",
  text: "#fff",
  background: "#212121",
  indicator: "#FFCC00",
};

const lightTheme = {
  primary: "#003366",
  secondary: "#eee",
  border: "#878787",
  text: "#000",
  background: "#fff",
  indicator: "#ccc",
};

const defaultTheme = {
  fontSize: {
    xs: "12px",
    sm: "14px",
    md: "16px",
    lg: "18px",
  },
  borderRadius: {
    small: "5px",
    medium: "10px",
    large: "15px",
    circle: "50%",
  },
};

const theme = {
  dark: {
    color: darktheme,
    ...defaultTheme,
  },
  light: {
    color: lightTheme,
    ...defaultTheme,
  },
};

export default theme;`

The theme object exported as the default in the code block above has two properties: dark and light. We’ll pass the proper property to the ThemeProvider component based on the selected theme. The following action will wrap the application with ThemeProvider:

`import styled, { ThemeProvider } from "styled-components";
import theme from "./theme";

...
function App() {
  const [currentTheme, setCurrentTheme] = useState("light");
...

return (
  <ThemeProvider theme={theme[currentTheme]}>
  <Nav>
    <BrandText>Theme With Styled-Components</BrandText>
    <ToggleButton>
    currentTheme={currentTheme}
    onClick={() => {
       if (currentTheme === "light") {
       setCurrentTheme("dark");
     } else {
       setCurrentTheme("light");
     }
    }}>
      <span></span>
    </ToggleButton>
  </Nav>
  ...
  </ThemeProvider>
 );
}`

From the code block above, we have the currentTheme state; this controls the theme rule to pass to ThemeProvider. The ToggleButton component allows us to toggle between light and dark themes.

## Using Themes in Styled-Components

To use the theme rules in the style component, we will need to access the theme from the props object:

`const Nav = styled.nav`
  background-color: ${({ theme }) => theme.color.background};
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 40px;
  border-bottom: 1px solid ${({ theme }) => theme.color.border};
`;`

In the code block above, we are destructuring the theme property from the props object. This will give us access to all of the theme rules. Using the code sample above, we have:

`background-color: ${({ theme }) => theme.color.background};`

This will apply the primary color from the current selected theme's theme rule

## Conclusion
This article explored how to add styled-components to your React application and create component-level styles. In addition, we looked at how to create light and dark themes for React applications using ThemeProvider. If you would like to look further into styled-components, check out the official documentation. You can also find the complete code for the project used in this article in my Github Repository or test the live version here: https://theme-sc.vercel.app/. Want to learn more? Check out this article about how to implement drag and drop in React.Styled-Components