Mobile-first UI com React
Migração completa para ReactJS: requisitos, implementação por componente, validação e defesa técnica.
▼
BASE
Escopo Real do TP3
Consolidar o que o enunciado cobra: migrar HTML/CSS estático para ReactJS com componentização, CSS3 e responsividade.
Este material foi organizado para funcionar como um guia de estudo orientado ao TP3 de Mobile-first UI com React. A proposta aqui não é apenas mostrar "a resposta pronta", mas ajudar você a entender o que o enunciado realmente pede, como quebrar o problema em partes menores e como migrar, com método, um site HTML/CSS estático para uma aplicação ReactJS organizada em componentes.
Ao longo desta página, você vai trabalhar exatamente as competências cobradas no teste: criação do projeto React, organização de arquivos CSS por componente, reaproveitamento da pasta assets, construção do menu com comportamento mobile-first, implementação do menu hamburger com exibir/ocultar, migração do header, manutenção dos breakpoints do projeto anterior, reaproveitamento do sistema de container, row e grid, criação dos componentes de Banner, Card, Partners e Footer e montagem da página Home com os itens mínimos exigidos no enunciado.
O desafio central deste TP não é "inventar um site novo" nem "escrever React avançado". O desafio é estruturar bem o que já existia, separar a interface em componentes reutilizáveis, manter a responsividade do projeto anterior e usar React de forma coerente para controlar comportamento, repetição de conteúdo e composição da página. Em outras palavras: sair do HTML/CSS estático e entrar em uma arquitetura de componentes com CSS3, sem perder clareza, organização e previsibilidade.
Por isso, esta página foi montada em uma ordem intencional. Primeiro, você vai ver o escopo real do trabalho e os requisitos obrigatórios. Depois, os pré-requisitos e o vocabulário mínimo para não se perder na leitura. Em seguida, a estrutura recomendada do projeto, a fundação visual com container, row e grid, e só então os componentes principais: Menu, Header, Banner, Card, Partners, Footer e Home. No fim, você encontra uma lista de validação e um roteiro de defesa técnica para explicar sua solução com segurança.
A melhor forma de usar este material é simples: não tente absorver tudo de uma vez. Leia cada seção como uma etapa do trabalho. Entenda o objetivo, observe o código, monte a parte correspondente no seu projeto, valide o comportamento no navegador e só depois avance. Se fizer isso, você não estará apenas "seguindo um tutorial"; estará aprendendo a pensar o projeto em camadas, que é exatamente o que o TP quer avaliar.
- Disciplina:
Mobile-first UI com React(TP3). - Objetivo: componentização com comportamento real (menu hamburger), grid responsivo e organização de código.
- Entrega: trabalho no
https://codesandbox.io/+ link em documento Google + PDF no padrãonome_sobrenome_DR3_TP3.
Para fins de estudo técnico, o conteúdo foi organizado como guia de revisão e checklist de implementação.
▼
EX.01
Checklist Técnico dos 15 Itens Obrigatórios
Transformar o enunciado em lista verificável para não deixar requisito de fora.
- 1. Criar projeto ReactJS.
- 2. Criar CSS ou SCSS por componente.
- 3. Adicionar pasta
assetsdo projeto estático. - 4. Criar componente
Menucom base no menu anterior. - 5. Implementar menu hamburger abrindo/fechando ao clique.
- 6. Criar componente de
cabeçalho/Header. - 7. Definir breakpoints em arquivo CSS/SCSS.
- 8. Migrar
container,rowegrid. - 9. Criar componente
Cardpara notícias. - 10. Criar componente
Banner. - 11. Renderizar 2 itens de banner na Home.
- 12. Renderizar 4 notícias na Home.
- 13. Criar componente de
rodapé/Footer. - 14. Criar componente de
parceiros. - 15. Renderizar 4 parceiros acima do rodapé.
Se qualquer item acima faltar, a entrega está incompleta.
▼
EX.02
Pré-requisitos e Glossário Mínimo
Garantir base de entendimento para quem ainda está inseguro com React.
Pré-requisitos: HTML/CSS do projeto anterior, noção de JSX, import/export, props, useState, map e organização de pastas.
Componente: peça reutilizável (Menu, Header, Card, Banner, Partners, Footer).Props: dados recebidos pelo componente.State: dado que muda por interação (ex.: menu aberto/fechado).useState: hook para controlar estado local.map: renderização de listas (2 banners, 4 notícias, 4 parceiros).Mobile-first: começar pela tela pequena e expandir com breakpoints.
▼
EX.03
Estrutura Recomendada de Projeto
Padronizar a arquitetura antes de implementar para evitar retrabalho.
src/
assets/
components/
Menu/Menu.jsx + Menu.css
Header/Header.jsx + Header.css
Banner/Banner.jsx + Banner.css
Card/Card.jsx + Card.css
Partners/Partners.jsx + Partners.css
Footer/Footer.jsx + Footer.css
pages/Home/Home.jsx + Home.css
styles/grid.css
App.jsx
main.jsx
Esse arranjo atende ao requisito "CSS/SCSS por componente" e mantém rastreabilidade da migração.
▼
EX.04
Setup Inicial + Entrega (CodeSandbox/PDF)
Criar base ReactJS, importar assets e fechar formato de submissão sem ambiguidade.
npm create vite@latest mobile-react-tp3 -- --template react
cd mobile-react-tp3
npm install
npm run dev
# depois
# 1) copiar assets para src/assets
# 2) criar componentes e css por componente
# 3) subir no CodeSandbox
# 4) gerar PDF com nome_sobrenome_DR3_TP3
A entrega deve mencionar explicitamente: CodeSandbox, documento Google com link e PDF no padrão solicitado.
▼
EX.05
Base CSS: Container, Row e Grid
Migrar a fundação visual antes de montar componentes específicos.
/* src/styles/grid.css */
* { box-sizing: border-box; }
html, body, #root { margin: 0; padding: 0; min-height: 100%; }
img { display: block; max-width: 100%; }
.container { width: min(1120px, calc(100% - 2rem)); margin-inline: auto; }
.row { display: grid; grid-template-columns: repeat(12, 1fr); gap: 1rem; }
.col-12 { grid-column: span 12; }
@media (min-width: 768px) { .col-md-6 { grid-column: span 6; } }
@media (min-width: 1024px) {
.col-lg-3 { grid-column: span 3; }
.col-lg-6 { grid-column: span 6; }
}
Sem essa base, Banner/Card/Partners ficam sem consistência de layout.
▼
EX.06
Menu com Flexbox + Hamburger (useState)
Implementar comportamento real do menu no ReactJS.
/* Menu.jsx */
import { useState } from "react";
import "./Menu.css";
export default function Menu() {
const [open, setOpen] = useState(false);
return (
<nav className="menu">
<button onClick={() => setOpen(!open)} aria-expanded={open}>☰</button>
<ul className={`menu__list ${open ? "menu__list--open" : ""}`}>...</ul>
</nav>
);
}
- Mobile: botão hamburger visível e lista recolhida.
- Clique: alterna estado com
setOpen(!open). - Desktop: menu horizontal via media query.
▼
EX.07
Header Component + Breakpoints
Separar cabeçalho como componente e manter evolução mobile-first.
/* Header.jsx */
import Menu from "../Menu/Menu";
export default function Header() {
return (
<header className="site-header" id="home">
<div className="container site-header__content">
<h1>Meu Site</h1>
<Menu />
</div>
</header>
);
}
/* breakpoints exemplo */
@media (min-width: 768px) { ...tablet... }
@media (min-width: 1024px) { ...desktop... }
▼
EX.08
Banner Component (2 Itens na Home)
Cumprir o requisito de dois banners com reuso via props e map.
/* Banner.jsx */
export default function Banner({ items }) {
return (
<section className="banner">
<div className="container">
<div className="row">
{items.map((item, index) => (
<article className="col-12 col-lg-6" key={index}>...</article>
))}
</div>
</div>
</section>
);
}
Condição de conformidade: 2 banners renderizados na Home.
▼
EX.09
Card de Notícias (4 Itens Mínimos)
Aplicar componente reutilizável para conteúdo repetido.
/* Card.jsx */
export default function Card({ image, title, description }) {
return (
<article className="news-card">
<img src={image} alt={title} />
<div className="news-card__body">
<h3>{title}</h3>
<p>{description}</p>
</div>
</article>
);
}
Condição de conformidade: 4 notícias exibidas na Home com
map.
▼
EX.10
Partners + Footer
Fechar a composição da página com parceiros e rodapé componentizados.
/* Partners.jsx */
import "./Partners.css";
export default function Partners({ items }) {
return (
<section className="partners" id="partners">
<div className="container">
<h2>Parceiros</h2>
<div className="row">
{items.map((partner, index) => (
<article className="col-12 col-md-6 col-lg-3 partner-card" key={index}>
<img src={partner.image} alt={partner.name} />
<h3>{partner.name}</h3>
</article>
))}
</div>
</div>
</section>
);
}
/* Partners.css */
.partners {
padding: 2rem 0;
background: #f9fafb;
}
.partner-card {
background: #fff;
border-radius: 12px;
padding: 1rem;
text-align: center;
border: 1px solid #e5e7eb;
}
/* Footer.jsx */
import "./Footer.css";
export default function Footer() {
return (
<footer className="site-footer" id="footer">
<div className="container site-footer__content">
<div>
<h3>Meu Site</h3>
<p>Projeto React migrado do HTML/CSS estático.</p>
</div>
<div>
<h4>Links</h4>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#news">Notícias</a></li>
<li><a href="#partners">Parceiros</a></li>
</ul>
</div>
</div>
</footer>
);
}
/* Footer.css */
.site-footer {
background: #111827;
color: #fff;
padding: 2rem 0;
}
.site-footer__content {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.site-footer a {
color: #fff;
text-decoration: none;
}
.site-footer ul {
list-style: none;
padding: 0;
margin: 0;
}
@media (min-width: 768px) {
.site-footer__content {
flex-direction: row;
justify-content: space-between;
}
}
Condição de conformidade: 4 parceiros acima do rodapé.
▼
EX.11
Montagem da Home + App Final
Orquestrar componentes e dados em fluxo único.
/* Home.jsx */
import Banner from "../../components/Banner/Banner";
import Card from "../../components/Card/Card";
import Partners from "../../components/Partners/Partners";
import Footer from "../../components/Footer/Footer";
import "./Home.css";
import banner1 from "../../assets/banner1.jpg";
import banner2 from "../../assets/banner2.jpg";
import news1 from "../../assets/news1.jpg";
import news2 from "../../assets/news2.jpg";
import news3 from "../../assets/news3.jpg";
import news4 from "../../assets/news4.jpg";
import partner1 from "../../assets/partner1.jpg";
import partner2 from "../../assets/partner2.jpg";
import partner3 from "../../assets/partner3.jpg";
import partner4 from "../../assets/partner4.jpg";
const bannerItems = [
{
image: banner1,
title: "Banner 1",
description: "Primeiro destaque da página inicial."
},
{
image: banner2,
title: "Banner 2",
description: "Segundo destaque da página inicial."
}
];
const newsItems = [
{ image: news1, title: "Notícia 1", description: "Resumo da notícia 1." },
{ image: news2, title: "Notícia 2", description: "Resumo da notícia 2." },
{ image: news3, title: "Notícia 3", description: "Resumo da notícia 3." },
{ image: news4, title: "Notícia 4", description: "Resumo da notícia 4." }
];
const partnerItems = [
{ image: partner1, name: "Parceiro 1" },
{ image: partner2, name: "Parceiro 2" },
{ image: partner3, name: "Parceiro 3" },
{ image: partner4, name: "Parceiro 4" }
];
export default function Home() {
return (
<>
<Banner items={bannerItems} />
<main className="home-main container" id="news">
<h2>Notícias</h2>
<div className="row">
{newsItems.map((item, index) => (
<div className="col-12 col-md-6 col-lg-3" key={index}>
<Card
image={item.image}
title={item.title}
description={item.description}
/>
</div>
))}
</div>
</main>
<Partners items={partnerItems} />
<Footer />
</>
);
}
/* Home.css */
.home-main {
padding: 2rem 0;
}
.home-main h2 {
margin-top: 0;
}
/* App.jsx */
import "./styles/grid.css";
import Header from "./components/Header/Header";
import Home from "./pages/Home/Home";
export default function App() {
return (
<>
<Header />
<Home />
</>
);
}
▼
CHECK
Validação Final + Defesa Técnica
Fechar a entrega com evidência verificável, explicação clara e prevenção dos erros mais comuns.
- Validação 1: projeto ReactJS abre sem erro.
- Validação 2: assets usados em banners/cards/parceiros.
- Validação 3: existe CSS ou SCSS por componente.
- Validação 4: hamburger aparece no mobile e alterna ao clique.
- Validação 5: menu desktop horizontal em breakpoint maior.
- Validação 6: Home renderiza 2 banners, 4 notícias e 4 parceiros.
- Validação 7: Footer componentizado e posicionado corretamente.
Como explicar a sua solução:
"Eu parti do site estático do TP anterior e não reescrevi o layout do zero. Primeiro migrei a base do CSS, com container, row e grid, para preservar a responsividade. Depois quebrei o HTML em componentes reutilizáveis: Menu, Header, Banner, Card, Partners e Footer. O menu hamburger foi resolvido com useState, e a Home foi montada com arrays para renderizar 2 banners, 4 notícias e 4 parceiros."
Se perguntarem "por que isso é React e não só HTML espalhado?", responda:
"Porque cada bloco repetível ou semanticamente isolado virou componente, e os conteúdos variáveis são passados por props ou renderizados com map."
"Eu parti do site estático do TP anterior e não reescrevi o layout do zero. Primeiro migrei a base do CSS, com container, row e grid, para preservar a responsividade. Depois quebrei o HTML em componentes reutilizáveis: Menu, Header, Banner, Card, Partners e Footer. O menu hamburger foi resolvido com useState, e a Home foi montada com arrays para renderizar 2 banners, 4 notícias e 4 parceiros."
Se perguntarem "por que isso é React e não só HTML espalhado?", responda:
"Porque cada bloco repetível ou semanticamente isolado virou componente, e os conteúdos variáveis são passados por props ou renderizados com map."
Erros mais comuns:
- Fazer tudo dentro de
App.jsx(perde componentização). - Usar um único arquivo CSS gigante (o enunciado pede CSS/SCSS por componente).
- Hamburger visual sem abrir/fechar de verdade ao clique.
- Copiar 4 cards e 4 parceiros manualmente, sem props/map.
- Inventar um layout totalmente novo em vez de migrar o estático.
- Não validar em larguras diferentes (mobile, tablet e desktop).
Conclusão: com código completo nos componentes e na Home, mais validação e defesa técnica, esta página passa a cumprir integralmente o papel pedagógico e técnico do arquivo de respostas.