Blog

Saiba como utilizar Theme Provider com styled-components

Desenvolvedor codando e utilizando Theme Provider.
Desenvolvimento / Desenvolvimento de Software / Padrões / Programação

Saiba como utilizar Theme Provider com styled-components

Em um projeto de desenvolvimento de software, é comum seguir uma linha de padrões de estilo, tais como: cores, tamanhos, fontes, etc. Com o Styled-components, uma boa forma de organizar essas constantes é criando um arquivo de tema. Englobando todos os componentes filhos com o theme provider, você conseguirá acessar esses estilos em qualquer componente de estilização

Assim, poderá criar padrões que facilitam a manutenção do código. Por exemplo, podemos mudar uma cor de todo o projeto em apenas um arquivo.

Neste artigo, você verá como é fácil e mais efetivo utilizar os temas globais do styled-components.

Styled-components

­Styled-components é uma biblioteca para React e React Native, que permite a criação de componentes previamente estilizados. Isso não apenas com CSS, mas também é utilizado Javascript nele, para passar variáveis, propriedades e temas padrões.

Dessa forma, podemos passar esses temas através de um Theme Provider, que utiliza a context API para englobar toda a aplicação. Ou seja, ao criá-lo, todos os componentes filhos herdarão suas propriedades automaticamente.

Iniciando o projeto

Para iniciar, temos um projeto com React e styled-components. Para utilizá-lo, vamos precisar ter previamente instalado em nossa máquina o Node JS e o Git. Posteriormente, basta cloná-lo e executá-lo em sua máquina realizando os seguintes comandos em seu terminal e em um local da sua preferência:

Após clonar, devemos abrir o local do projeto com:

  • cd .\React-Styled-Components-Ts-Boilerplate\

Após abrir o local do projeto, devemos instalar as dependências do projeto com:

  • npm install

E executá-lo com:

  • npm start

Modificando os temas

Primeiramente, iremos modificar o arquivo de tema. Nele vamos declarar um objeto com as constantes que iremos utilizar no nosso projeto.

Por isso, vamos modificar o arquivo chamado “Theme.ts” e estruturar da melhor forma para atender o nosso projeto:

const Theme = {
  color: {
    background: "#141827",
    primary: {
      main: "#fffae3",
      contrastText: "#c1d9d0",
    },
    secundary: {
      main: "#736681",
      contrastText: "#62455b",
    },
  },

  border: {
    radius: "15px",
    style: "2px solid #736681",
  },

  font: {
    small: "0.5rem",
    default: "1rem",
    big: "2rem",
    bigger: "3rem",
  },
};

export default Theme;

Modificando o arquivo de declaração

Para utilizar os temas, precisamos modificar a interface padrão do styled-components, fazendo ele reconhecer as propriedades que colocamos no nosso arquivo.

Assim, vamos modificar o arquivo chamado “styled.d.ts”.

import 'styled-components';

import Theme from './Theme'

export type ITheme = typeof Theme

declare module 'styled-components' {
  export interface DefaultTheme extends ITheme {}
}

Aqui, importamos nosso tema criado anteriormente e estendemos sua interface ao tema padrão o DefaultTheme.

Theme Provider

Agora, para poder utilizá-lo em todos os componentes, iremos englobar toda a aplicação com o Theme Provider.

No arquivo “index.tsx”, iremos colocar o Theme Provider como componente pai do app:

import ReactDOM from "react-dom/client";
import App from "./App";

import { ThemeProvider } from "styled-components";
import Theme from "./styles/Theme";

const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
  <ThemeProvider theme={Theme}>
    <App />
  </ThemeProvider>
);

É sua escolha onde deverá colocar. Entretanto, para um tema global, é recomendado que seja no arquivo “index.tsx” ou no “app.tsx” da raiz. Pois são neles que todos os componentes filhos herdarão suas propriedades.

Exemplos

Já está tudo preparado no nosso projeto. Então, podemos utilizar os temas na estilização de nossos componentes.

Criaremos três componentes “Button.ts”, “Container.ts”, “Title.ts”:

Button.ts:

import styled from "styled-components";
export const ButtonWithTheme = styled.button`
  color: ${(props) => props.theme.color.secundary.main};
  background-color: ${(props) => props.theme.color.secundary.contrastText};

  border: ${(props) => props.theme.border.style};
  border-radius: ${(props) => props.theme.border.radius};

  font-size: ${(props) => props.theme.font.big};
`;

Container.ts:

import styled from "styled-components";

export const ContainerTheme = styled.div`
  padding: 15px;
  background-color: ${(props) => props.theme.color.background};
  border-radius: ${props=>props.theme.border.radius};
`;
export const Container = styled.div`
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  height: 100vh;
`;

Title.ts:

import styled from "styled-components";
export const TitleTheme = styled.h1`
  color: ${(props) => props.theme.color.primary.main};
  font-size: ${(props) => props.theme.font.bigger};
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color:
${props => props.theme.color.primary.contrastText};
`;

Como podemos ver, os temas são passados pelas props padrões do styled-components. Isso porque nós estendemos nossa interface ao DefaultTheme. Assim, permitindo usar em todos componentes criados.

Nosso código no “App.tsx”:

import {  ButtonWithTheme } from "./components/Button";
import { Container, ContainerTheme } from "./components/Container";
import {  TitleTheme } from "./components/Title";

function App() {
  return (
    <>
    <Container>
      <ContainerTheme>
        <TitleTheme>Título com Tema :D</TitleTheme>
        <ButtonWithTheme>Botão com Tema :D</ButtonWithTheme>
      </ContainerTheme>
      <div>
        <h1>Título sem tema :(</h1>
        <button>Botão sem tema :(</button>
      </div>
    </Container>
    </>
  );
}

export default App;

Temos como resultado:

Theme Provider com variáveis

Para finalizar, iremos criar uma variação do nosso tema. Então, faremos o tema claro apenas trocando a ordem de algumas cores.

Vamos criar um arquivo chamado “LightTheme.ts” e iremos fazer um novo objeto que contenha as mesmas propriedades do primeiro tema. Para isso, atribuímos o tipo DefaultTheme. Assim, ele dará erro se tiver alguma propriedade faltando:

import { DefaultTheme } from "styled-components";

const LightTheme: DefaultTheme = {};

export default LightTheme;

Neste momento, teremos que colocar as mesmas propriedades e atribuir da forma que preferirmos. Aqui no nosso projeto, vamos apenas inverter a ordem das cores já estabelecidas:

import Theme from "./Theme";

const LightTheme: DefaultTheme = {
  color: {
    background: Theme.color.primary.contrastText,
    primary: {
      main: Theme.color.background,
      contrastText: Theme.color.primary.main,
    },
    secundary: {
      main: Theme.color.secundary.contrastText,
      contrastText: Theme.color.secundary.main,
    },
  },

  border: {
    radius: "15px",
    style: "2px solid " + Theme.color.secundary.contrastText,
  },

  font: Theme.font,
};

Dessa forma, nosso projeto está pronto para ser utilizado em qualquer componente de nossa aplicação. Para o exemplo, vamos adicionar no “App.tsx” um novo Theme Provider.

Agora, temos dois provider, um externo com o tema antigo e um interno com o novo tema claro:

//Mantenha as importações anteriores e adicione o seguinte
import { ThemeProvider } from "styled-components";
import LightTheme from "./styles/LightTheme";

function App() {
  return (
    <>
      <Container>

        <ThemeProvider theme={LightTheme}>
          <ContainerTheme>
            <TitleTheme>Título com Tema Claro :D</TitleTheme>
            <ButtonWithTheme>Botão com Tema Claro!! :D</ButtonWithTheme>
          </ContainerTheme>
        </ThemeProvider>

        <ContainerTheme>
          <TitleTheme>Título com Tema Escuro :D</TitleTheme>
          <ButtonWithTheme>Botão com Tema Escuro :D</ButtonWithTheme>
        </ContainerTheme>
      </Container>
    </>
  );
}

export default App;

Também podemos fazer o uso da mudança de estado com useState, para deixar nosso tema dinâmico:

//Manter restante do código acima
import Theme from "./styles/Theme";
import { useState } from "react";

function App() {
  const [isDarkTheme, setIsDarkTheme] = useState(true);

  const handleButton = () => {
    setIsDarkTheme(!isDarkTheme);
  };

  return (
    <>
      <ThemeProvider theme={isDarkTheme ? Theme : LightTheme}>
        <Container>
          <ContainerTheme>
            <TitleTheme>Título com Tema Variável</TitleTheme>
            <ButtonWithTheme onClick={handleButton}>
              Click Para mudar o tema
            </ButtonWithTheme>
          </ContainerTheme>
        </Container>
      </ThemeProvider>
    </>
  );
}
//Manter restante do código abaixo

Leia também:
Saiba como fazer validação de formulário

Autor: Alexandre Roberto Lima da Silva.

Select the fields to be shown. Others will be hidden. Drag and drop to rearrange the order.
  • Image
  • SKU
  • Rating
  • Price
  • Stock
  • Availability
  • Add to cart
  • Description
  • Content
  • Weight
  • Dimensions
  • Additional information
  • Attributes
  • Custom attributes
  • Custom fields
Click outside to hide the comparison bar
Compare