Rodapé de quatro colunas
Rodapé de quatro colunas — newsletter com campo e botão de enviar dentro, links, contato, redes e chave claro/escuro.
usa o ROD-01
O código
/* ===== rodape.css ================================================================== */
/* ROD-01 · Rodapé de colunas — no modelo do original do 21st.dev, sem React nem shadcn.
Uma coluna no celular (com a marca sozinha em cima, centrada, e as duas colunas de conteúdo lado
a lado), duas a partir de 768 px e quatro a partir de 1024 px. Títulos de coluna em 1,125rem,
links em 0,875rem, redes em ícones redondos de contorno, faixa inferior com borda.
Sem o formulário de newsletter e sem a chave claro/escuro do original: o primeiro não tinha ação
nenhuma e a segunda não ligava em nada. Se precisar deles, o original está em original/. */
.c-rodape {
--c-rod-fundo: #000;
--c-rod-tinta: #ebebeb;
--c-rod-tinta-2: #a8a8a8;
--c-rod-tinta-3: #6a6a6a;
--c-rod-linha: rgba(235, 235, 235, .12);
--c-rod-destaque: #e8ad32;
--c-rod-gutter: 24px;
padding: 48px var(--c-rod-gutter) 0;
background: var(--c-rod-fundo);
color: var(--c-rod-tinta);
}
.c-rodape__grade { display: grid; gap: 40px; }
@media (min-width: 768px) { .c-rodape__grade { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .c-rodape__grade { grid-template-columns: repeat(4, 1fr); } }
.c-rodape__marca { display: grid; justify-items: center; text-align: center; }
.c-rodape__logo { width: 150px; height: auto; margin: 0 auto 16px; }
.c-rodape__lema {
margin-bottom: 8px;
font-size: .8rem;
font-weight: 600;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--c-rod-destaque);
}
.c-rodape__texto { font-size: .9rem; color: var(--c-rod-tinta-2); }
.c-rodape__titulo { margin: 0 0 8px; font: 600 1.125rem/1.2 inherit; }
.c-rodape__coluna { display: grid; align-content: start; gap: 8px; font-size: .875rem; }
.c-rodape__coluna > a, .c-rodape__contato a { color: var(--c-rod-tinta); text-decoration: none; transition: color .2s ease; }
.c-rodape__coluna > a:hover, .c-rodape__contato a:hover { color: var(--c-rod-destaque); }
.c-rodape__contato { display: grid; gap: 8px; margin-top: 12px; font-style: normal; color: var(--c-rod-tinta-2); }
.c-rodape__icones { display: flex; flex-wrap: wrap; gap: 12px; }
.c-rodape__icone {
width: 44px;
height: 44px;
flex-shrink: 0; /* na coluna estreita do celular o alvo de 44 px não cede: quebra de linha antes */
display: grid;
place-items: center;
border: 1px solid var(--c-rod-linha);
border-radius: 50%;
color: var(--c-rod-tinta);
transition: border-color .2s ease, color .2s ease;
}
.c-rodape__icone:hover { border-color: var(--c-rod-destaque); color: var(--c-rod-destaque); }
.c-rodape__icone svg { width: 18px; height: 18px; }
.c-rodape__base {
margin-top: 48px;
padding-top: 32px;
padding-bottom: calc(32px + env(safe-area-inset-bottom, 0px));
border-top: 1px solid var(--c-rod-linha);
text-align: center;
font-size: .875rem;
color: var(--c-rod-tinta-3);
}
/* ---------- celular: as duas colunas de conteúdo lado a lado, a marca sozinha em cima ----------
As duas medidas saem de UMA conta: a coluna da direita tem de caber a fileira dos três alvos de
44 px sem que eles encolham nem quebrem de linha.
coluna(L) = (L − 2 × gutter − column-gap) / 2 fileira = 3 × 44 + 2 × gap-dos-ícones
Com column-gap 16 e gap 12 a fileira dá 156 px e só cabe de 376 px para cima — medido nos dois
motores. Com 12 e 8 a fileira é 148 px e a coluna a 360 px é 150: cabe do iPhone SE para cima.
De ~356 px para baixo ela ainda quebra, de propósito: o alvo de 44 px nunca cede.
Mora no FIM do arquivo porque sobrescreve o column-gap da grade e o gap dos ícones, declarados
acima: media query não soma especificidade, então quem ganha é quem vem depois. */
@media (max-width: 767.98px) {
.c-rodape__grade { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 12px; }
.c-rodape__marca { grid-column: 1 / -1; }
.c-rodape__icones { gap: 8px; }
}
/* ===== markup.html ================================================================= */
<!-- ROD-01 · Rodapé. Quatro blocos na grade: marca, duas colunas de conteúdo e as redes.
No celular a marca ocupa a linha inteira e as duas colunas ficam lado a lado. -->
<footer class="c-rodape">
<div class="c-rodape__grade">
<div class="c-rodape__marca">
<img class="c-rodape__logo" src="logo.png" alt="Nome da marca" width="150" height="58">
<p class="c-rodape__lema">Uma linha de assinatura</p>
<p class="c-rodape__texto">Uma frase curta sobre o que a casa faz.</p>
</div>
<nav class="c-rodape__coluna" aria-label="Links rápidos">
<h2 class="c-rodape__titulo">Links rápidos</h2>
<a href="#">O espaço</a>
<a href="#">Valores</a>
<a href="#">Perguntas</a>
</nav>
<div class="c-rodape__coluna">
<h2 class="c-rodape__titulo">Contato</h2>
<address class="c-rodape__contato">
<a href="tel:+5521000000000">(21) 00000-0000</a>
<a href="mailto:oi@exemplo.com">oi@exemplo.com</a>
<span>Rio de Janeiro, RJ</span>
</address>
</div>
<div class="c-rodape__coluna">
<h2 class="c-rodape__titulo">Redes</h2>
<div class="c-rodape__icones">
<a class="c-rodape__icone" href="#" aria-label="Instagram">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="2" y="2" width="20" height="20" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor" stroke="none"/></svg>
</a>
<a class="c-rodape__icone" href="#" aria-label="WhatsApp">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 12a9 9 0 0 1-13.1 8L3 21l1.1-4.8A9 9 0 1 1 21 12z"/></svg>
</a>
<a class="c-rodape__icone" href="#" aria-label="LinkedIn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-4 0v7h-4V9h4z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg>
</a>
</div>
</div>
</div>
<div class="c-rodape__base">© 2026 Nome da marca. Todos os direitos reservados.</div>
</footer>
/* ===== 03-rodape.tsx =============================================================== */
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Textarea } from "@/components/ui/textarea"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import { Facebook, Instagram, Linkedin, Moon, Send, Sun, Twitter } from "lucide-react"
function Footerdemo() {
const [isDarkMode, setIsDarkMode] = React.useState(true)
const [isChatOpen, setIsChatOpen] = React.useState(false)
React.useEffect(() => {
if (isDarkMode) {
document.documentElement.classList.add("dark")
} else {
document.documentElement.classList.remove("dark")
}
}, [isDarkMode])
return (
<footer className="relative border-t bg-background text-foreground transition-colors duration-300">
<div className="container mx-auto px-4 py-12 md:px-6 lg:px-8">
<div className="grid gap-12 md:grid-cols-2 lg:grid-cols-4">
<div className="relative">
<h2 className="mb-4 text-3xl font-bold tracking-tight">Stay Connected</h2>
<p className="mb-6 text-muted-foreground">
Join our newsletter for the latest updates and exclusive offers.
</p>
<form className="relative">
<Input
type="email"
placeholder="Enter your email"
className="pr-12 backdrop-blur-sm"
/>
<Button
type="submit"
size="icon"
className="absolute right-1 top-1 h-8 w-8 rounded-full bg-primary text-primary-foreground transition-transform hover:scale-105"
>
<Send className="h-4 w-4" />
<span className="sr-only">Subscribe</span>
</Button>
</form>
<div className="absolute -right-4 top-0 h-24 w-24 rounded-full bg-primary/10 blur-2xl" />
</div>
<div>
<h3 className="mb-4 text-lg font-semibold">Quick Links</h3>
<nav className="space-y-2 text-sm">
<a href="#" className="block transition-colors hover:text-primary">
Home
</a>
<a href="#" className="block transition-colors hover:text-primary">
About Us
</a>
<a href="#" className="block transition-colors hover:text-primary">
Services
</a>
<a href="#" className="block transition-colors hover:text-primary">
Products
</a>
<a href="#" className="block transition-colors hover:text-primary">
Contact
</a>
</nav>
</div>
<div>
<h3 className="mb-4 text-lg font-semibold">Contact Us</h3>
<address className="space-y-2 text-sm not-italic">
<p>123 Innovation Street</p>
<p>Tech City, TC 12345</p>
<p>Phone: (123) 456-7890</p>
<p>Email: hello@example.com</p>
</address>
</div>
<div className="relative">
<h3 className="mb-4 text-lg font-semibold">Follow Us</h3>
<div className="mb-6 flex space-x-4">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" className="rounded-full">
<Facebook className="h-4 w-4" />
<span className="sr-only">Facebook</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Follow us on Facebook</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" className="rounded-full">
<Twitter className="h-4 w-4" />
<span className="sr-only">Twitter</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Follow us on Twitter</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" className="rounded-full">
<Instagram className="h-4 w-4" />
<span className="sr-only">Instagram</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Follow us on Instagram</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" className="rounded-full">
<Linkedin className="h-4 w-4" />
<span className="sr-only">LinkedIn</span>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Connect with us on LinkedIn</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<div className="flex items-center space-x-2">
<Sun className="h-4 w-4" />
<Switch
id="dark-mode"
checked={isDarkMode}
onCheckedChange={setIsDarkMode}
/>
<Moon className="h-4 w-4" />
<Label htmlFor="dark-mode" className="sr-only">
Toggle dark mode
</Label>
</div>
</div>
</div>
<div className="mt-12 flex flex-col items-center justify-between gap-4 border-t pt-8 text-center md:flex-row">
<p className="text-sm text-muted-foreground">
©️ 2024 Your Company. All rights reserved.
</p>
<nav className="flex gap-4 text-sm">
<a href="#" className="transition-colors hover:text-primary">
Privacy Policy
</a>
<a href="#" className="transition-colors hover:text-primary">
Terms of Service
</a>
<a href="#" className="transition-colors hover:text-primary">
Cookie Settings
</a>
</nav>
</div>
</div>
</footer>
)
}
export { Footerdemo }
Já rodou em
- trento-pedro · home v3 — seção 10
Exige
- react
- shadcn/ui (Button, Input, Label, Switch, Tooltip*)
- lucide-react (Facebook, Instagram, Linkedin, Twitter, Send, Sun, Moon)
Como se configura
--c-rod-fundo--c-rod-tinta--c-rod-tinta-2--c-rod-linha--c-rod-destaque
A ficha
O que o 21st.dev entregou
Dependências: react, primitivos do shadcn/ui (Button, Input, Label, Switch, Tooltip*; Textarea é importado e não usado), lucide-react (Facebook, Instagram, Linkedin, Twitter, Send, Sun, Moon). "use client" é diretiva do Next.js.
Vale o modelo do componente (Rafa, 14/09), com o logo da Trento dentro; o conteúdo é trocado.
Estrutura: grade de 1 coluna no celular, 2 a partir de md (768 px), 4 a partir de lg (1024 px), e uma faixa inferior.
- "Stay Connected": título
text-3xl, texto de newsletter, campo de e-mail com botão redondo de enviar dentro, brilho desfocado no canto. O formulário não tem ação: enviar recarrega a página. - "Quick Links": 5 links para
#. - "Contact Us": endereço, telefone e e-mail fictícios.
- "Follow Us": 4 botões redondos de rede social com dica ao passar o mouse, e uma chave claro/escuro que põe ou tira a classe
darkdo<html>. - Faixa inferior: copyright "2024 Your Company" e 3 links legais (Privacy, Terms, Cookie Settings).
Estado sobrando: isChatOpen nunca é usado.
O que a Trento já tem de dado real para ele (odoo/views/rodape-trento.arch.xml, o rodapé da dev):
- "Fotografia · Conteúdo · Publicidade";
- WhatsApp 21 99878-4219, @trentoproducoes, trentoproducoes@gmail.com;
- Rua Siqueira Campos, 143, 2º pavimento, loja 8, Copacabana;
- "Sete dias por semana, das 7h às 23h".
O que não cabe como está:
- A chave claro/escuro (o site não tem tema escuro alternável).
- A newsletter (não há lista de e-mail).
- Facebook, Twitter e LinkedIn — a fachada do estúdio mostra Instagram, TikTok e YouTube.
- O
lucide-reactnão costuma trazer ícone de marca como WhatsApp e TikTok.
O logo da Trento vai dentro deste rodapé (decisão do Rafa, 14/09) — onde, é pergunta.
O que a adaptação da OCTA mudou
- Quatro colunas viram uma no celular, sem breakpoint tipográfico
Lacunas do original
- O formulário de newsletter não tem ação — enviar recarrega a página
Textareaé importado e não usado- A chave claro/escuro não liga em nada
- O brilho desfocado no canto depende de
overflow-hiddenno rodapé