Skip to main content

📘 Componentes e Estilos (Tailwind)

No capítulo anterior, utilizamos CSS para definir a apresentação visual dos componentes React.

Para cada componente, criamos uma folha de estilos correspondente:

Label.jsx ─────────────► Label.css
LabelTitle.jsx ────────► LabelTitle.css
InputText.jsx ─────────► InputText.css
InputPassword.jsx ─────► InputPassword.css
Button.jsx ────────────► Button.css
Login.jsx ─────────────► Login.css

Agora utilizaremos outra abordagem para estilizar a mesma aplicação: Tailwind CSS.

Com Tailwind, grande parte da estilização pode ser realizada diretamente no JSX utilizando classes utilitárias.

Por exemplo, anteriormente poderíamos ter:

<button className="btn">
Logar
</button>

e definir sua aparência em outro arquivo:

.btn {
width: 100%;
padding: 0.8rem;
background-color: #0066cc;
color: white;
}

Com Tailwind, essas características podem ser representadas diretamente no elemento:

<button className="w-full px-4 py-2 bg-blue-600 text-white">
Logar
</button>
Tailwind CSS

Tailwind utiliza uma abordagem conhecida como Utility-First CSS.

Em vez de criarmos uma classe CSS personalizada para cada elemento, combinamos classes utilitárias que representam propriedades específicas de estilo.


CSS tradicional x Tailwind

Podemos representar as duas abordagens da seguinte maneira:

CSS tradicional

Componente JSX
│
│ className="btn"
▼
Button.css
│
▼
propriedades CSS

Com Tailwind:

Tailwind

Componente JSX
│
▼
className="
w-full
px-4
py-2
bg-blue-600
text-white
"

As classes ficam próximas ao elemento que será estilizado.

tip

O objetivo deste capítulo não é substituir os conceitos de CSS estudados anteriormente.

Conhecer propriedades como padding, margin, display, color, background-color, border e Flexbox ajuda a compreender o significado das classes utilitárias utilizadas pelo Tailwind.


Estrutura do projeto

Continuaremos utilizando a mesma aplicação de Login.

A estrutura utilizada neste capítulo será:

index.html
│
└── src/
├── main.jsx
├── App.jsx
│
└── componentes/
└── tailwind/
├── Label.jsx
├── LabelTitle.jsx
├── InputText.jsx
├── InputPassword.jsx
├── Button.jsx
└── Login.jsx

Observe uma diferença importante em relação ao capítulo anterior.

Não teremos:

Label.css
LabelTitle.css
InputText.css
InputPassword.css
Button.css
Login.css

As classes utilitárias serão aplicadas diretamente nos componentes JSX.

O fluxo da aplicação continua:

index.html
│
▼
main.jsx
│
▼
App.jsx
│
▼
Login.jsx
│
├── LabelTitle.jsx
├── Label.jsx
├── InputText.jsx
├── InputPassword.jsx
└── Button.jsx

Carregando o Tailwind

Para os exemplos deste capítulo, utilizaremos a abordagem apresentada no projeto-base, carregando o Tailwind por meio de CDN.

No arquivo index.html, temos:

<!doctype html>

<html lang="en">

<head>
<meta charset="UTF-8" />

<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>

<title>ReactJS - Bolsa Futuro Digital</title>
</head>

<body>

<div id="root"></div>

<script src="https://cdn.tailwindcss.com"></script>

<script
type="module"
src="/src/main.jsx">
</script>

</body>

</html>

A linha:

<script src="https://cdn.tailwindcss.com"></script>

carrega o Tailwind para a página.

A partir desse momento, podemos utilizar suas classes utilitárias nos elementos da aplicação.

Por exemplo:

<p className="text-blue-600">
ReactJS
</p>

Nesse exemplo:

text-blue-600
│
▼
cor do texto
Neste capítulo

A utilização do CDN permite concentrar o conteúdo nos conceitos de componentes e estilização com classes utilitárias, sem introduzir uma etapa adicional de configuração do Tailwind.


Utilizando a versão Tailwind no App.jsx

O componente principal deverá utilizar a versão do Login criada neste capítulo.

App.jsx​

import Login from "./componentes/tailwind/Login.jsx";

function App() {

return (
<>
<Login />
</>
);
}

export default App;

O fluxo continua simples:

App
│
▼
Login
│
▼
demais componentes

A principal diferença está na implementação visual dos componentes.


Estilizando Label.jsx

Começaremos pelo componente utilizado para apresentar os rótulos dos campos.

Label.jsx​

import React, { useState } from 'react';

export default function Label({ texto }) {

const [valor] = useState(texto);

return (
<label
className="block text-base font-medium text-gray-800 mb-1"
>
{valor}
</label>
);
}

O funcionamento do componente continua semelhante ao estudado anteriormente.

A novidade está em:

className="block text-base font-medium text-gray-800 mb-1"

Em vez de criarmos uma classe personalizada em Label.css, combinamos diferentes utilitários.


Entendendo as classes​

ClasseFunção
blockFaz o elemento ocupar a linha como bloco
text-baseDefine o tamanho padrão da fonte
font-mediumDefine peso intermediário para a fonte
text-gray-800Define uma tonalidade escura de cinza
mb-1Adiciona uma pequena margem inferior

Podemos decompor:

className="
block
text-base
font-medium
text-gray-800
mb-1
"

Cada classe possui uma responsabilidade.


Comparando com CSS tradicional

No capítulo anterior poderíamos escrever:

.label {
display: block;
font-size: 1.2rem;
margin-bottom: 0.3rem;
color: #333;
}

e:

<label className="label">

Agora escrevemos:

<label
className="block text-base font-medium text-gray-800 mb-1"
>

Podemos visualizar:

CSS tradicional              Tailwind

display: block → block

font-size → text-base

font-weight → font-medium

color → text-gray-800

margin-bottom → mb-1
Utility-First

Cada classe representa uma pequena característica visual.

A aparência final do elemento surge da combinação de vários utilitários.


Estilizando LabelTitle.jsx

O título do formulário precisa possuir maior destaque visual.

LabelTitle.jsx​

import React, { useState } from 'react';

export default function LabelTitle({ texto }) {

const [valor] = useState(texto);

return (
<label
className="block text-2xl font-bold text-blue-800 mb-4 text-center"
>
{valor}
</label>
);
}

Novamente, toda a estilização está em:

className="block text-2xl font-bold text-blue-800 mb-4 text-center"

Classes utilizadas​

ClasseFunção
blockExibe o elemento como bloco
text-2xlAumenta o tamanho da fonte
font-boldAplica maior peso à fonte
text-blue-800Define uma tonalidade escura de azul
mb-4Adiciona margem inferior
text-centerCentraliza o texto

Podemos comparar visualmente:

LabelTitle
│
├── text-2xl
├── font-bold
├── text-blue-800
└── text-center
│
▼
destaque

Enquanto:

Label
│
├── text-base
├── font-medium
└── text-gray-800
│
▼
rótulo

Assim, continuamos estabelecendo uma hierarquia visual entre título e rótulos.


Espaçamento no Tailwind

Nos exemplos anteriores já encontramos:

mb-1
mb-4

O prefixo:

m

está relacionado a margin.

A letra seguinte indica a direção.

mt  → margin-top
mr → margin-right
mb → margin-bottom
ml → margin-left

Também encontraremos classes relacionadas a padding:

p   → padding
px → padding horizontal
py → padding vertical

Por exemplo:

px-3

adiciona espaçamento interno horizontal.

Enquanto:

py-2

adiciona espaçamento interno vertical.

Podemos representar:

          py
↓
┌──────────────┐
px →│ conteúdo │← px
└──────────────┘
↑
py

Estilizando InputText.jsx

Agora utilizaremos Tailwind no campo de texto.

Continuaremos com os conceitos estudados anteriormente:

useState
onChange
e.target.value
validação
renderização condicional

A novidade será a apresentação visual.

InputText.jsx​

import React, { useState } from 'react';

export default function InputText({ placeholder }) {

const [valor, setValor] = useState("");
const [erro, setErro] = useState(false);

function handleChange(e) {

const novoValor = e.target.value;

setValor(novoValor);

setErro(novoValor.trim() === "");
}

return (
<div className="flex flex-col mb-3">

<input
type="text"
placeholder={placeholder}
value={valor}
onChange={handleChange}
className="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:border-blue-600 focus:ring-1 focus:ring-blue-400 outline-none"
/>

{erro && (
<p className="text-sm text-red-600 mt-1">
O campo não pode ficar vazio. ⚠️
</p>
)}

</div>
);
}

Organizando o componente

O elemento externo utiliza:

<div className="flex flex-col mb-3">

Temos:

ClasseFunção
flexAtiva Flexbox
flex-colOrganiza os elementos em coluna
mb-3Adiciona margem inferior

Portanto:

div
│
│ flex flex-col
▼
┌───────────────────────────┐
│ Input │
│ │
│ Mensagem de erro │
└───────────────────────────┘

Dimensionamento do Input

O campo utiliza:

w-full

Essa classe faz com que o elemento ocupe toda a largura disponível no contêiner.

Podemos relacioná-la ao CSS:

width: 100%;

Assim:

w-full
│
▼
┌───────────────────────────┐
│ largura total │
└───────────────────────────┘

Padding com px e py

O campo também utiliza:

px-3
py-2

Temos:

px-3
│
└── padding horizontal

e:

py-2
│
└── padding vertical

Isso cria espaço interno entre o texto digitado e as bordas do campo.


Tamanho do texto

text-sm

define um tamanho menor de fonte.

Observe que o prefixo:

text-

pode aparecer em diferentes contextos.

Por exemplo:

text-sm

está relacionado ao tamanho.

Enquanto:

text-red-600

está relacionado à cor.

O restante do nome da classe indica sua finalidade.


Bordas

O campo utiliza:

border
border-gray-300
rounded-md

Podemos interpretar:

border
│
└── adiciona borda

border-gray-300
│
└── define a cor da borda

rounded-md
│
└── arredonda os cantos

No CSS tradicional, teríamos propriedades como:

border: 1px solid #ccc;
border-radius: 4px;

Estados visuais com focus:

Uma das características importantes do Tailwind é a utilização de variantes diretamente no nome das classes.

Observe:

focus:border-blue-600
focus:ring-1
focus:ring-blue-400

O prefixo:

focus:

indica que a classe deverá ser aplicada quando o elemento estiver com foco.

Assim:

Campo normal
│
│ usuário seleciona o campo
▼
:focus
│
├── border-blue-600
├── ring-1
└── ring-blue-400
Variantes

Tailwind permite combinar estados visuais com utilitários.

Por exemplo:

focus:border-blue-600

significa:

quando o elemento estiver com foco, utilize uma borda azul.


ring

No campo encontramos:

focus:ring-1
focus:ring-blue-400

O ring cria um destaque ao redor do elemento.

Nesse caso:

ring-1

define o destaque e:

ring-blue-400

define sua tonalidade.

O efeito ajuda a indicar qual campo está ativo.


outline-none

Também utilizamos:

outline-none

Essa classe remove o outline padrão do elemento.

No exemplo, o feedback visual do foco passa a ser fornecido pelas classes:

focus:border-blue-600
focus:ring-1
focus:ring-blue-400

Estilizando a mensagem de erro

A mensagem:

<p className="text-sm text-red-600 mt-1">
O campo não pode ficar vazio. ⚠️
</p>

utiliza:

ClasseFunção
text-smDefine texto menor
text-red-600Define a cor vermelha
mt-1Adiciona margem superior

Observe que a renderização condicional continua funcionando da mesma forma:

{erro && (
...
)}

Portanto:

Estado erro
│
├── false → mensagem não aparece
│
└── true → mensagem aparece
│
▼
Tailwind define
sua aparência

Isso demonstra uma separação importante:

React
│
└── controla quando o elemento aparece

Tailwind
│
└── controla como o elemento aparece

Estilizando InputPassword.jsx

Aplicaremos uma estrutura semelhante ao campo de senha.

InputPassword.jsx​

import React, { useState } from 'react';

export default function InputPassword({ placeholder }) {

const [senha, setSenha] = useState("");

return (
<div className="flex flex-col mb-3">

<input
type="password"
placeholder={placeholder}
value={senha}
onChange={(e) => setSenha(e.target.value)}
className="w-full px-3 py-2 text-sm border border-gray-300 rounded-md focus:border-green-600 focus:ring-1 focus:ring-green-400 outline-none"
/>

{senha !== "" && (
<p className="text-sm text-gray-600 italic mt-1">
Senha digitada: {senha}
</p>
)}

</div>
);
}

Grande parte das classes é semelhante ao InputText.

Temos novamente:

w-full
px-3
py-2
text-sm
border
border-gray-300
rounded-md
outline-none

A diferença está principalmente no estado visual de foco:

focus:border-green-600
focus:ring-1
focus:ring-green-400

Assim:

InputText
│
└── foco azul

InputPassword
│
└── foco verde

Texto em itálico

A mensagem utiliza:

italic

Essa classe aplica estilo itálico ao texto.

Também temos:

text-gray-600

para uma tonalidade de cinza.

Assim:

<p className="text-sm text-gray-600 italic mt-1">

combina:

text-sm       → tamanho
text-gray-600 → cor
italic → estilo
mt-1 → espaçamento
Exemplo didático

A apresentação do conteúdo digitado no campo de senha continua sendo utilizada apenas para demonstrar o funcionamento do estado e da renderização condicional.

Não devemos exibir senhas dessa maneira em aplicações reais.


Estilizando Button.jsx

Agora aplicaremos classes utilitárias ao botão.

Button.jsx​

import React, { useState } from 'react';

export default function Button({ valor }) {

const [texto, setTexto] = useState(valor);

function handleClick() {
setTexto("Você clicou!");
}

return (
<button
onClick={handleClick}
className="w-full px-4 py-2 bg-blue-600 text-white text-base rounded-md cursor-pointer hover:bg-blue-800 transition-colors"
>
{texto}
</button>
);
}

O funcionamento continua igual:

valor (prop)
│
▼
texto (state)
│
│ clique
▼
handleClick()
│
▼
setTexto("Você clicou!")

Tailwind será responsável apenas pela apresentação.


Classes do botão

ClasseFunção
w-fullOcupa toda a largura
px-4Adiciona padding horizontal
py-2Adiciona padding vertical
bg-blue-600Define fundo azul
text-whiteDefine texto branco
text-baseDefine tamanho padrão da fonte
rounded-mdArredonda os cantos
cursor-pointerAltera o cursor
hover:bg-blue-800Escurece o botão no hover
transition-colorsSuaviza a mudança das cores

Cores de fundo

Observe:

bg-blue-600

O prefixo:

bg-

indica background.

Portanto:

bg-blue-600
│ │ │
│ │ └── tonalidade
│ └─────── cor
└─────────── background

Cor do texto

text-white

define a cor branca para o conteúdo textual.

Assim:

bg-blue-600
+
text-white
↓
botão azul com texto branco

Estado hover:

Observe:

hover:bg-blue-800

O prefixo:

hover:

indica que a classe será aplicada quando o ponteiro estiver sobre o elemento.

Temos:

Botão normal
│
└── bg-blue-600

mouse sobre o botão
│
▼
hover
│
▼
bg-blue-800

No CSS tradicional, teríamos algo semelhante a:

.btn:hover {
background-color: ...;
}

No Tailwind:

hover:bg-blue-800

Transição de cores

Também utilizamos:

transition-colors

Essa classe adiciona uma transição às alterações de cores.

Assim, a passagem:

bg-blue-600
↓
bg-blue-800

ocorre de maneira mais suave.

Estados visuais

Até este momento já utilizamos duas variantes importantes:

focus:
hover:

Elas permitem definir comportamentos visuais diretamente no className.


Integrando os componentes em Login.jsx

Agora reuniremos todos os componentes.

Login.jsx​

import React from "react";

import Label from "./Label.jsx";
import LabelTitle from "./LabelTitle.jsx";
import Button from "./Button.jsx";
import InputText from "./InputText.jsx";
import InputPassword from "./InputPassword.jsx";

function Login() {

return (
<div
className="flex justify-center items-center h-screen w-screen bg-gray-100"
>

<form
className="bg-white p-8 rounded-lg shadow-md w-80"
>

<LabelTitle texto="Login" />

<div className="mb-4 flex flex-col">
<Label texto="Usuário:" />
<InputText placeholder="user..." />
</div>

<div className="mb-4 flex flex-col">
<Label texto="Senha:" />
<InputPassword placeholder="password..." />
</div>

<Button valor="Logar" />

</form>

</div>
);
}

export default Login;

Esse componente demonstra como diferentes classes Tailwind podem ser combinadas para construir o layout completo da página.


Centralizando a interface

O container principal utiliza:

flex
justify-center
items-center
h-screen
w-screen
bg-gray-100

Vamos analisar.


flex​

flex

ativa o modelo Flexbox.

Equivale conceitualmente ao CSS:

display: flex;

justify-center​

justify-center

centraliza o conteúdo no eixo principal.


items-center​

items-center

centraliza os elementos no outro eixo.

Combinando:

flex
justify-center
items-center

temos:

┌─────────────────────────────────┐
│ │
│ │
│ ┌───────────┐ │
│ │ Login │ │
│ │ │ │
│ └───────────┘ │
│ │
│ │
└─────────────────────────────────┘

Essa é a mesma ideia de Flexbox estudada no capítulo de CSS.

A diferença é a forma de escrevê-la.

CSS​

display: flex;
justify-content: center;
align-items: center;

Tailwind​

flex justify-center items-center

Ocupando a tela

Utilizamos:

h-screen
w-screen

Temos:

h-screen
│
└── altura da tela

e:

w-screen
│
└── largura da tela

Assim, o container ocupa a área visível da página.


Cor de fundo

bg-gray-100

define um fundo cinza claro para a página.

Isso ajuda a criar contraste com o formulário branco.


Criando o Card

O formulário utiliza:

<form
className="bg-white p-8 rounded-lg shadow-md w-80"
>

As classes são:

ClasseFunção
bg-whiteFundo branco
p-8Espaçamento interno
rounded-lgBordas arredondadas
shadow-mdSombra
w-80Define a largura do formulário

Visualmente:

fundo cinza
┌──────────────────────────────────┐
│ │
│ ┌──────────────────┐ │
│ │ Login │ │
│ │ │ │
│ │ Usuário │ │
│ │ [____________] │ │
│ │ │ │
│ │ Senha │ │
│ │ [____________] │ │
│ │ │ │
│ │ [ Logar ] │ │
│ └──────────────────┘ │
│ │
└──────────────────────────────────┘

Esse formato mantém a ideia de Card Layout utilizada no capítulo anterior.


Espaçamento interno com p-8

A classe:

p-8

adiciona padding em todas as direções.

Podemos representar:

┌───────────────────────────────┐
│ padding │
│ ┌───────────────────────┐ │
│ │ │ │
│ │ conteúdo │ │
│ │ │ │
│ └───────────────────────┘ │
│ padding │
└───────────────────────────────┘

Bordas arredondadas

rounded-lg

define um arredondamento maior para os cantos do formulário.

Anteriormente utilizamos:

rounded-md

nos inputs e no botão.

Portanto:

rounded-md
│
└── arredondamento médio

rounded-lg
│
└── arredondamento maior

Sombra

shadow-md

aplica uma sombra ao formulário.

No CSS tradicional utilizamos:

box-shadow: ...;

Com Tailwind utilizamos uma classe predefinida:

shadow-md

Largura do formulário

w-80

define a largura do card.

No exemplo utilizado, essa classe produz um formulário com aproximadamente 320 pixels de largura.


Organizando os grupos

Cada conjunto de Label e Input utiliza:

<div className="mb-4 flex flex-col">

Temos:

mb-4
│
└── espaço abaixo do grupo

flex
│
└── ativa Flexbox

flex-col
│
└── organiza em coluna

Portanto:

form-group
│
├── Label
│
└── Input

é apresentado como:

Label
↓
Input

Comparando CSS e Tailwind

Agora podemos comparar diretamente as duas versões da aplicação.

CSS tradicional​

<div className="login-container">

<form className="login-form">

...

</form>

</div>

Com um arquivo separado:

.login-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f5f5f5;
}

.login-form {
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
width: 320px;
}

Tailwind​

<div
className="flex justify-center items-center h-screen w-screen bg-gray-100"
>

<form
className="bg-white p-8 rounded-lg shadow-md w-80"
>

...

</form>

</div>

Podemos relacionar alguns conceitos:

CSSTailwind
display: flexflex
justify-content: centerjustify-center
align-items: centeritems-center
height: 100vhh-screen
largura da viewportw-screen
fundo cinzabg-gray-100
background: whitebg-white
paddingp-8
border-radiusrounded-lg
box-shadowshadow-md
largura do cardw-80
Duas formas de estilizar

CSS tradicional e Tailwind não alteram os conceitos fundamentais do React.

Continuamos utilizando:

Componentes
Props
State
Eventos
Renderização condicional

O que muda é principalmente a forma utilizada para declarar os estilos.


Padrões das classes Tailwind

Ao observar os exemplos deste capítulo, podemos identificar alguns padrões.

Cores de texto​

text-gray-800
text-blue-800
text-red-600
text-gray-600
text-white

Cores de fundo​

bg-gray-100
bg-white
bg-blue-600

Espaçamento​

p-8

px-3
px-4

py-2

mt-1
mb-1
mb-3
mb-4

Dimensões​

w-full
w-80
w-screen
h-screen

Tipografia​

text-sm
text-base
text-2xl

font-medium
font-bold

italic
text-center

Bordas e sombras​

border
border-gray-300

rounded-md
rounded-lg

shadow-md

Layout​

flex
flex-col
justify-center
items-center

Estados​

hover:bg-blue-800

focus:border-blue-600
focus:ring-1
focus:ring-blue-400

focus:border-green-600
focus:ring-green-400

Transições​

transition-colors

Identificar esses padrões facilita a leitura das classes.


Responsividade

O Tailwind também possui recursos para aplicar estilos de acordo com diferentes tamanhos de tela.

Alguns prefixos utilizados para isso são:

sm:
md:
lg:

A estrutura geral é:

prefixo:classe

Por exemplo:

md:w-80

indica que determinada regra está associada ao breakpoint md.

Outro exemplo seria:

text-base md:text-lg

Temos:

text-base
│
└── comportamento inicial

md:text-lg
│
└── comportamento a partir do breakpoint md
info

Neste capítulo, nosso foco principal está nas classes utilitárias utilizadas pela aplicação de Login.

Os prefixos responsivos sm:, md: e lg: representam uma possibilidade de evolução da mesma abordagem para diferentes tamanhos de tela.


Conceitos-chave do Tailwind

Podemos consolidar os principais conceitos trabalhados:

ConceitoDescrição
Utility-First CSSEstilos construídos pela combinação de classes utilitárias
Escala de coresClasses como gray-100, blue-600 e green-400
EspaçamentoUtilitários como p-8, px-3, py-2 e mb-4
FlexboxUtilitários como flex, flex-col, justify-center e items-center
Estados visuaisVariantes como hover: e focus:
RingDestaque visual aplicado principalmente em elementos com foco
TransiçõesClasses como transition-colors
ResponsividadePrefixos como sm:, md: e lg:
Consistência visualUso de escalas predefinidas de tamanho, cor e espaçamento

Visão geral da aplicação

Ao final, temos:

                        Login.jsx
│
┌─────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
Componentes React Tailwind
│ │ │
│ ┌────┴─────┐ │
│ │ │ │
▼ ▼ ▼ ▼
reutilização props state apresentação
│
▼
eventos
│
▼
nova renderização

Tailwind não substitui a lógica React.

Ele trabalha na camada visual:

React
│
├── estrutura
├── componentes
├── props
├── state
└── eventos

Tailwind
│
├── layout
├── cores
├── espaçamento
├── bordas
├── tipografia
└── estados visuais

Exercício de Fixação

Neste capítulo, utilizamos Tailwind CSS para estilizar os componentes desenvolvidos anteriormente.

O objetivo do exercício é implementar, executar, testar e validar todos os códigos apresentados.

Atividade​

Crie a estrutura:

src/
└── componentes/
└── tailwind/
├── Label.jsx
├── LabelTitle.jsx
├── InputText.jsx
├── InputPassword.jsx
├── Button.jsx
└── Login.jsx

Implemente todos os componentes apresentados neste capítulo.

Configure também o carregamento do Tailwind no index.html, conforme utilizado nos exemplos:

<script src="https://cdn.tailwindcss.com"></script>

Depois, ajuste o App.jsx:

import Login from "./componentes/tailwind/Login.jsx";

function App() {

return (
<>
<Login />
</>
);
}

export default App;

Execute a aplicação e valide o funcionamento dos componentes.


Testando Label​

Verifique se:

<Label texto="Usuário:" />

apresenta corretamente o conteúdo recebido pela prop.

Observe visualmente os efeitos de:

block
text-base
font-medium
text-gray-800
mb-1

Altere temporariamente algumas dessas classes e observe o resultado.

Depois, retorne ao código original.


Testando LabelTitle​

Verifique se:

<LabelTitle texto="Login" />

possui destaque em relação aos demais rótulos.

Observe principalmente:

text-2xl
font-bold
text-blue-800
text-center
mb-4

Compare visualmente LabelTitle com Label.


Testando InputText​

Digite diferentes valores no campo.

Valide o comportamento do estado:

digitação
│
▼
onChange
│
▼
handleChange
│
▼
setValor

Depois apague o conteúdo.

Verifique se a mensagem:

O campo não pode ficar vazio. ⚠️

é apresentada.

Teste também inserir apenas espaços para validar:

novoValor.trim() === ""

Clique no campo e observe os efeitos:

focus:border-blue-600
focus:ring-1
focus:ring-blue-400

Testando InputPassword​

Digite uma senha.

Verifique se:

  • os caracteres são ocultados pelo type="password";
  • o estado senha é atualizado;
  • a renderização condicional funciona;
  • o campo recebe o destaque verde quando está com foco.

Observe:

focus:border-green-600
focus:ring-1
focus:ring-green-400

Compare o comportamento visual com o InputText.

warning

A exibição da senha é utilizada apenas para fins didáticos.

Não utilize esse comportamento em aplicações reais.


Testando Button​

Observe inicialmente:

Logar

Passe o ponteiro sobre o botão.

Verifique o comportamento de:

hover:bg-blue-800

Observe também a suavização fornecida por:

transition-colors

Depois clique no botão.

O texto deverá mudar para:

Você clicou!

Isso permite validar simultaneamente:

Tailwind
│
└── aparência

React
│
└── comportamento

Testando Login​

Valide a integração:

Login
│
├── LabelTitle
│
├── Label
│ └── InputText
│
├── Label
│ └── InputPassword
│
└── Button

Observe se a tela está centralizada horizontal e verticalmente.

Identifique as classes responsáveis:

flex
justify-center
items-center
h-screen
w-screen

Verifique também:

bg-gray-100

no fundo da tela.


Testando o Card​

Observe o formulário e identifique o efeito das classes:

bg-white
p-8
rounded-lg
shadow-md
w-80

Altere temporariamente:

shadow-md

e observe o efeito.

Faça o mesmo com:

rounded-lg

Depois retorne aos valores originais.


Comparando CSS e Tailwind​

Abra também a versão desenvolvida no capítulo anterior.

Compare:

componentes/CSS/Login.jsx

com:

componentes/tailwind/Login.jsx

Identifique como propriedades que anteriormente estavam em arquivos .css agora aparecem como classes utilitárias no JSX.

Por exemplo:

CSS                          Tailwind

display: flex → flex

justify-content → justify-center

align-items → items-center

padding → p-8 / px-3 / py-2

border-radius → rounded-md / rounded-lg

background-color → bg-blue-600

color → text-white

box-shadow → shadow-md

Validação final

Ao concluir os testes, certifique-se de que consegue identificar:

  • o conceito de Utility-First CSS;
  • a utilização de classes Tailwind no className;
  • classes de cores;
  • classes de espaçamento;
  • classes de tamanho;
  • classes de tipografia;
  • classes de borda;
  • classes de sombra;
  • utilização de Flexbox;
  • flex-col;
  • justify-center;
  • items-center;
  • variantes hover:;
  • variantes focus:;
  • utilização de ring;
  • utilização de transition-colors;
  • integração do Tailwind com componentes React;
  • manutenção do funcionamento de props, states e eventos;
  • diferença entre a implementação com CSS tradicional e a implementação com Tailwind.
Objetivo do exercício

Não se limite a verificar se a interface ficou visualmente correta.

Durante os testes, procure relacionar cada classe Tailwind com a propriedade ou o comportamento visual correspondente.

Por exemplo:

rounded-md
│
▼
bordas arredondadas

bg-blue-600
│
▼
cor de fundo

hover:bg-blue-800
│
▼
mudança da cor durante o hover

focus:ring-blue-400
│
▼
destaque durante o foco

O objetivo é compreender como a combinação de pequenas classes utilitárias constrói a interface completa.


Resumo

Neste capítulo, mantivemos a aplicação React desenvolvida anteriormente, mas alteramos a estratégia utilizada para sua estilização.

Anteriormente:

Componente.jsx
│
▼
className
│
▼
arquivo.css

Agora:

Componente.jsx
│
▼
className
│
▼
classes utilitárias Tailwind

Trabalhamos com:

Utility-First CSS
│
├── cores
├── tipografia
├── espaçamento
├── dimensões
├── bordas
├── sombras
├── Flexbox
├── hover
├── focus
└── transições

Ao mesmo tempo, todos os conceitos React estudados anteriormente continuam presentes:

Componentes
│
├── Props
├── State
├── Eventos
├── Inputs controlados
└── Renderização condicional

Assim, podemos visualizar a evolução dos conteúdos:

Estrutura do React
│
▼
Componentes
│
▼
Props
│
▼
State
│
▼
Eventos
│
▼
CSS
│
▼
Tailwind
│
▼
Interface React estilizada

O Tailwind oferece uma forma diferente de organizar a camada visual da aplicação, utilizando classes utilitárias diretamente nos elementos JSX.