Você está interessado em criar sua própria biblioteca de componentes React com temas? Talvez você queira controle total sobre a paleta de cores do seu projeto e uma grande variedade de temas diferentes disponíveis para seus usuários. Talvez você seja apenas um amador tentando exercitar seus músculos criativos. Seja qual for o acampamento em que você está, não procure além deste artigo!
Estaremos estabelecendo a base para a criação de uma biblioteca de componentes React escalonável, totalmente personalizável e temática.
Para nosso projeto de exemplo, usaremos Tailwind CSS para criar um tema para nossos componentes. Se você nunca usou Tailwind CSS antes, está perdendo.
O Tailwind é composto por uma grande variedade de classes utilitárias CSS. Isso significa que você não precisa escrever nenhum CSS-basta adicionar a classe Tailwind apropriada aos seus elementos HTML para aplicar o estilo desejado. Margem, preenchimento, cor de fundo e quase todo o resto estão a uma classe de distância.
Combine isso com componentes React reutilizáveis e você estará no caminho certo para criar uma biblioteca escalável e temática.
Configure o projeto
Vamos começar criando nosso projeto React:
$ yarn criar projeto temático-reagir-app-react projeto temático-reagir $ cd
A seguir, configuraremos o Tailwind seguindo as instruções dos documentos oficiais . Primeiro, instalaremos o Tailwind e suas dependências de pares:
$ yarn add-D tailwindcss @ npm: @ tailwindcss/postcss7-compat postcss @ ^ 7 autoprefixer @ ^ 9
Agora precisamos instalar o CRACO :
$ yarn add @ craco/craco
No arquivo package.json
, modifique os scripts start
, build
e test
para usar craco
em vez de react-scripts
:
{ /*... */ "scripts": { "start":"craco start", "build":"craco build", "teste":"teste de craco", "eject":"react-scripts eject" }, /*... */ }
Observe que não estamos usando CRACO para o script eject
.
Crie um arquivo craco.config.js
na raiz do projeto com o seguinte conteúdo:
//craco.config.js module.exports={ estilo: { postcss: { plugins: [ require ('tailwindcss'), requer ('autoprefixer'), ], }, }, }
Crie um arquivo tailwind.config.js
na raiz do projeto parecido com este:
//tailwind.config.js module.exports={ purga: ["./src/**/*.{js,jsx,ts,tsx}","./public/index.html"], darkMode: false, tema: { ampliar: {}, }, variantes: { ampliar: {}, }, plugins: [], };
Finalmente, substitua src/index.css
pelo seguinte, o que permite que o Tailwind use seus estilos em tempo de construção:
//src/index.css @tailwind base; componentes @tailwind; @tailwind utilities;
Terminamos de configurar tudo! Agora vamos começar a trabalhar em nosso tema.
Temas com Tailwind
Uma das melhores coisas sobre o Tailwind é como ele é configurável. Fora da caixa, ele vem com uma enorme paleta de cores. No entanto, se você estiver criando componentes com temas para seu site, a paleta de cores padrão pode ser um pouco demais.
Vamos começar definindo três cores: primária, secundária e uma cor para o texto. Podemos fazer isso facilmente alterando nosso arquivo tailwind.config.js
para ficar assim:
//tailwind.config.js module.exports={ purga: ["./src/**/*.{js,jsx,ts,tsx}","./public/index.html"], darkMode: false,//ou'media'ou'class' tema: { cores: { primário:"azul", secundário:"vermelho", "base de texto":"branco", }, ampliar: {}, }, variantes: { ampliar: {}, }, plugins: [], };
Agora podemos usar essas cores para qualquer classe do utilitário Tailwind que aceite uma cor. Vamos testar nosso tema criando um componente de botão personalizado.
Dentro da pasta src
, crie outra pasta chamada componentes
. Agora crie um arquivo Button.js
dentro dele. Usaremos as cores que definimos em nossa configuração do Tailwind para definir as cores do plano de fundo e do texto. Também usaremos algumas classes integradas do Tailwind para arredondar os cantos e adicionar algum preenchimento ao botão:
//src/components/Button.js Botão const=({filhos,... resto})=> { Retorna ( ); }; botão padrão de exportação;
Observe que capturamos quaisquer adereços extras na variável rest
e, em seguida, os passamos para o componente botão
HTML de base. Isso é para que possamos definir qualquer comportamento típico de botão, como um retorno de chamada onClick
.
Vamos para App.js
e teste nosso botão. Removeremos o código padrão e apenas adicionaremos o botão que criamos:
//src/App.js importar botão de"./components/Button"; function App () { Retorna (); } exportar aplicativo padrão;
Você deve ver nosso botão personalizado com nossa cor primária como plano de fundo!
Esta é uma ótima primeira etapa, mas nosso botão não é muito personalizável, pois codificamos a cor como bg-primary
. E se quiséssemos usar nossa cor secundária como plano de fundo? Não há problema-vamos apenas passar a cor como um suporte e usar a interpolação de strings para definir dinamicamente a cor do nosso botão:
//src/components/Button.js Botão const=({filhos, cor,... resto})=> { Retorna ( ); }; Button.defaultProps={ cor:"primária", }; botão padrão de exportação;
Definimos a cor padrão como primária para que não tenhamos que passar o adereço todas as vezes. Vamos tentar mudar a cor para secundária
de volta no App.js
para ter certeza de que funciona:
importar botão de"./components/Button"; function App () { Retorna (); } exportar aplicativo padrão;
Isso funciona muito bem, mas seria bom aplicar os adereços que passamos. Dessa forma, se alguém cometer um erro de digitação com o adereço color
, haverá uma mensagem de aviso no console explicando por que o componente não está se comportando conforme o esperado.
Dentro de nossa pasta components
, vamos fazer um arquivo chamado themeProps.js
onde definiremos os adereços que serão comuns a todos os nossos componentes temáticos:
//src/components/themeProps.js importar {oneOf} de"prop-types"; const props={ cor: oneOf (["primário","secundário"]), }; exportar adereços padrão;
Agora podemos usar themeProps
em nosso componente Button
personalizado:
//src/components/Button.js importar themeProps de"./themeProps"; Botão const=({filhos, cor,... resto})=> { Retorna ( ); }; Button.propTypes={ ... themeProps, }; Button.defaultProps={ cor:"primária", }; botão padrão de exportação;
Com nossos tipos de adereços agora aplicados, vamos prosseguir para definir dinamicamente nosso tema.
Definindo o tema dinamicamente
No momento, definimos nossas cores primárias, secundárias e de texto em nosso arquivo de configuração do Tailwind.
Podemos definir quantas cores quisermos em nossa configuração de tema do Tailwind, mas temos uma limitação: as cores que escolhemos são codificadas no arquivo de configuração. E se quisermos alternar dinamicamente o tema no tempo de execução? Isso seria útil se tivéssemos um modo escuro, por exemplo, e um usuário quisesse ver nosso site no modo escuro durante a noite.
Em vez de codificar nossa paleta de cores diretamente na configuração do Tailwind, podemos definir nossas cores usando variáveis CSS . Então, podemos alterar dinamicamente o valor dessas variáveis em tempo de execução para alterar o tema como quisermos. Altere seu arquivo tailwind.config.js
para ficar assim:
//tailwind.config.js module.exports={ purga: ["./src/**/*.{js,jsx,ts,tsx}","./public/index.html"], darkMode: false,//ou'media'ou'class' tema: { cores: { primário:"var (-theme-primary)", secundário:"var (-tema-secundário)", "text-base":"var (-theme-text-base)", }, ampliar: {}, }, variantes: { ampliar: {}, }, plugins: [], };
Estamos usando três variáveis chamadas --theme-primary
, --theme-secondary
e --theme-text-base
em nosso arquivo de configuração do Tailwind. Eles não estão definidos agora, então vamos trabalhar nisso. Na pasta src
de seu projeto React, crie uma nova pasta chamada themes
e adicione um arquivo chamado base.js
. Este será o nosso tema base, e mais tarde podemos adicionar outros temas como quisermos. Coloque isso em seu arquivo base.js
:
//src/themes/base.js const baseTheme={ "--theme-primary":"blue", "--theme-secondary":"red", "--theme-text-base":"branco" }; exportar baseTheme padrão;
Isso mapeia o nome de nossas variáveis CSS para a cor que queremos associar à variável, mas as próprias variáveis CSS ainda não serão definidas. Felizmente, é fácil definir variáveis CSS em JavaScript, então vamos fazer uma função que aceitará um objeto de tema e criará variáveis CSS correspondentes com os valores que definimos.
Crie um arquivo utils.js
em sua pasta themes
e adicione o seguinte:
//src/themes/utils.js export function applyTheme (theme) { const root=document.documentElement; Object.keys (theme).forEach ((cssVar)=> { root.style.setProperty (cssVar, theme [cssVar]); }); }
Agora vamos usar esta função para aplicar nosso tema base quando nosso aplicativo for montado. Podemos fazer isso com o gancho useEffect . Modifique seu arquivo App.js
para ficar assim:
import {useEffect} de"react"; importar botão de"./components/Button"; import {applyTheme} de"./themes/utils"; importar baseTheme de"./themes/base"; function App () { useEffect (()=> { applyTheme (baseTheme); }, []); Retorna (); } exportar aplicativo padrão;
No navegador, o aplicativo ainda deve ter a aparência que tinha antes. No momento, só temos nosso tema base, e seria bom criar um tema escuro. No entanto, antes de fazermos isso, podemos limpar a maneira como definimos nossos temas. Nosso arquivo de tema base.js
mapeia diretamente nomes de variáveis CSS para uma cor, mas seria bom definir nossas cores de uma maneira mais amigável.
Vamos criar uma função createTheme
em nosso arquivo utils.js
que mapeará nomes como primário
e secundário
aos nomes de variáveis CSS correspondentes que decidimos usar. Aqui está nosso arquivo utils.js
atualizado:
export function applyTheme (theme) { const root=document.documentElement; Object.keys (theme).forEach ((cssVar)=> { root.style.setProperty (cssVar, theme [cssVar]); }); } função de exportação createTheme ({ primário, secundário, textBase, }) { Retorna { "--theme-primary": principal, "--theme-secondary": secundário, "--theme-text-base": textBase, }; }
Agora vamos ajustar nosso arquivo de tema base.js
para usar a função createTheme
:
import {createTheme} de"./utils"; const baseTheme=createTheme ({ primário:"azul", secundário:"vermelho", textBase:"branco", }); exportar baseTheme padrão;
Vamos criar um arquivo dark.js
em nossa pasta themes
que usa o mesmo padrão para definir um tema escuro:
import {createTheme} de"./utils"; const darkTheme=createTheme ({ primário:"# 212529", secundário:"# 343A40", textBase:"branco", }); exportar darkTheme padrão;
Vamos modificar App.js
para mostrar dois botões que podem modificar dinamicamente nosso tema:
import {useEffect} de"react"; importar botão de"./components/Button"; import {applyTheme} de"./themes/utils"; importar baseTheme de"./themes/base"; importar darkTheme de"./themes/dark"; function App () { useEffect (()=> { applyTheme (baseTheme); }, []); Retorna (); } exportar aplicativo padrão;
Primeiro, você verá nosso tema básico:
Agora clique no botão Tema escuro e você os verá mudar!
Adicionando hover
Poderíamos adicionar quantos temas quisermos com quantas cores quisermos, mas nossos botões ainda são um pouco chatos. Eles são sempre da mesma cor-devemos fazer com que eles mudem para uma cor mais clara quando o usuário passa o mouse sobre eles.
Felizmente para nós, o Tailwind torna isso muito fácil. Tudo o que precisamos fazer é adicionar um prefixo hover:
a qualquer classe que desejamos aplicar apenas quando o componente estiver passando.
Tanto para o nosso tema escuro quanto para o tema base, vamos definir mais duas cores que serão aplicadas quando o botão for passado: luz primária
e luz secundária
. Vamos primeiro atualizar nosso arquivo tailwind.config.js
para usar essas cores conforme definido pelas variáveis CSS --theme-primary-light
e --theme-primary-dark
:
//tailwind.config.js module.exports={ purga: ["./src/**/*.{js,jsx,ts,tsx}","./public/index.html"], darkMode: false,//ou'media'ou'class' tema: { cores: { primário:"var (-theme-primary)", "primary-light":"var (-theme-primary-light)", secundário:"var (-tema-secundário)", "luz secundária":"var (-luz secundária do tema)", "text-base":"var (-theme-text-base)", }, ampliar: {}, }, variantes: { ampliar: {}, }, plugins: [], };
A seguir, em nosso arquivo de tema utils.js
, atualizaremos nossa função createTheme
para criar essas novas variáveis:
//src/themes/utils.js export function applyTheme (theme) { const root=document.documentElement; Object.keys (theme).forEach ((cssVar)=> { root.style.setProperty (cssVar, theme [cssVar]); }); } função de exportação createTheme ({ primário, primaryLight, secundário, SecondLight, textBase, }) { Retorna { "--theme-primary": principal, "--theme-primary-light": primaryLight, "--theme-secondary": secundário, "--theme-secondary-light": SecondLight, "--theme-text-base": textBase, }; }
Agora vamos definir variantes mais leves de nossas cores primárias e secundárias em nosso arquivo de tema base.js
:
//src/themes/base.js import {createTheme} de"./utils"; const baseTheme=createTheme ({ primário:"azul", primaryLight:"# 4d4dff", secundário:"vermelho", SecondLight:"# ff4d4d", textBase:"branco", }); exportar baseTheme padrão;
Agora faremos o mesmo com nosso tema escuro:
//src/themes/dark.js import {createTheme} de"./utils"; const darkTheme=createTheme ({ primário:"# 212529", primaryLight:"# 464f58", secundário:"# 343A40", SecondLight:"# 737f8c", textBase:"branco", }); exportar darkTheme padrão;
Por fim, aplicaremos as variantes de foco ao nosso botão. Lembre-se, uma vez que color
é passado como um suporte, podemos usar a interpolação de string para aplicar dinamicamente a variante de foco correta.
Tudo o que precisamos fazer é adicionar uma classe chamada hover: bg-$ {color}-light
, e então isso se tornará hover: bg-primary-light
ou hover: bg-secondary-light
dependendo da estaca:
//src/components/Button.js importar themeProps de"./themeProps"; Botão const=({filhos, cor,... resto})=> { Retorna ({crianças} ); }; Button.propTypes={ ... themeProps, }; Button.defaultProps={ cor:"primária", }; botão padrão de exportação;
Experimente em seu navegador e você notará que os botões mudam de cor quando você passa o mouse sobre eles!
Conclusão
Nós apenas criamos um componente de botão temático, mas podemos criar facilmente uma grande variedade de componentes temáticos usando o código com o qual começamos aqui.
Qualquer biblioteca temática também precisará de uma paleta de cores muito maior do que a que definimos neste projeto. No entanto, como vimos ao adicionar nossas variantes para cores primárias e secundárias, é fácil adicionar mais cores aos nossos temas, conforme necessário.
Para obter o código-fonte completo, você pode acessar tudo em minha conta GitHub .
A postagem Componentes Theming React com Tailwind CSS apareceu primeiro em LogRocket Blog .