Temporada chegando: avalie o atendimento da casa antes de contratar a equipe. Baixe o Raio-X grátis
Pular para o conteúdo

Design system

As peças do site, com as regras de uso

Tokens, componentes e padrões que montam as páginas da Servir & Encantar. Cada exemplo abaixo usa o componente real, importado do mesmo arquivo que as páginas públicas usam.

Tokens em src/app/globals.css. Componentes em src/components/ds e src/components/sections.

O sistema em resumo

  • Verde garrafa
  • Noite
  • Linho
  • Papel
  • Tinto
  • Latão
  • Latão claro
  • Sálvia
  • Tinta
  • Grafite

Fraunces

Albert Sans

Cores da marca
10
Famílias
2
Raios
2 a 6 px
Sombras
1

01 · Princípios

Quatro regras antes de qualquer tela

Valem para página nova, componente novo e ajuste pequeno.
  1. Um botão principal por tela.

    O verde cheio aparece uma vez por tela. Os outros caminhos vão em contorno ou em link de texto.

  2. Verde chama para a conversa, tinto entrega material.

    Botão verde (ou com o ícone do WhatsApp) leva a uma conversa com a Samara. Tinto, ou contorno com ícone de download, leva a um material gratuito.

  3. Filete no lugar de sombra.

    Blocos se separam com linhas de 1 px, como num cardápio impresso. A única sombra, shadow-papel, fica para o que flutua: cartão em destaque e menu aberto.

  4. Papelaria, não aplicativo.

    Cantos de 2 a 6 px em botões, campos e cartões. Formas redondas ficam para o prato, as fotos e o botão flutuante do WhatsApp.

02 · Tokens

Os valores por trás de tudo

Definidos no bloco @theme de src/app/globals.css. Cada token vira classe do Tailwind: --color-verde gera bg-verde, text-verde, border-verde e assim por diante.

Cores

As dez cores da marca e as cores de apoio da interface. Use sempre o nome do token, nunca o HEX solto.
  • verde

    Classes
    bg-verdetext-verde
    HEX
    #12392D
    Uso
    Cor principal: nome, títulos, botões
  • noite

    Classes
    bg-noitetext-noite
    HEX
    #0B241C
    Uso
    Fundos escuros, rodapé
  • linho

    Classes
    bg-linhotext-linho
    HEX
    #F4EEE3
    Uso
    Fundo principal
  • papel

    Classes
    bg-papeltext-papel
    HEX
    #FBF8F2
    Uso
    Cartões e superfícies
  • tinto

    Classes
    bg-tintotext-tinto
    HEX
    #7B2335
    Uso
    O &, ênfases, detalhes de destaque
  • latao

    Classes
    bg-lataotext-latao
    HEX
    #A8834A
    Uso
    Filetes, ícones e ornamentos sobre claro
  • latao-claro

    Classes
    bg-latao-clarotext-latao-claro
    HEX
    #C9A66B
    Uso
    O & e detalhes sobre fundo escuro
  • salvia

    Classes
    bg-salviatext-salvia
    HEX
    #DDE3D6
    Uso
    Superfícies secundárias
  • tinta

    Classes
    bg-tintatext-tinta
    HEX
    #1C2420
    Uso
    Texto principal
  • grafite

    Classes
    bg-grafitetext-grafite
    HEX
    #535C57
    Uso
    Texto secundário
  • verde-claro

    Classes
    bg-verde-clarotext-verde-claro
    HEX
    #1D4B3C
    Uso
    Hover do botão primário
  • tinto-escuro

    Classes
    bg-tinto-escurotext-tinto-escuro
    HEX
    #5F1828
    Uso
    Hover do botão destaque
  • tinto-claro

    Classes
    bg-tinto-clarotext-tinto-claro
    HEX
    #E3B7BF
    Uso
    Tinto suave. Ainda sem uso nos componentes.
  • linha

    Classes
    bg-linhatext-linha
    HEX
    #D8CFBE
    Uso
    Bordas, divisores e campos
  • erro

    Classes
    bg-errotext-erro
    HEX
    #9B2C2C
    Uso
    Mensagem e borda de campo com erro
  • sucesso

    Classes
    bg-sucessotext-sucesso
    HEX
    #2F6B4F
    Uso
    Confirmações. Ainda sem uso nos componentes.
  • whatsapp

    Classes
    bg-whatsapptext-whatsapp
    HEX
    #1FA855
    Uso
    Botão flutuante do WhatsApp

Nomes semânticos

Usados pelos componentes de interface em src/components/ui (shadcn). Nas páginas, prefira os nomes da marca.

background
linho
foreground
tinta
card
papel
card-foreground
tinta
popover
papel
popover-foreground
tinta
primary
verde
primary-foreground
linho
secondary
salvia
secondary-foreground
verde
muted
salvia
muted-foreground
grafite
accent
papel
accent-foreground
verde
destructive
erro
destructive-foreground
papel
border
linha
input
linha
ring
tinto

Tipografia

Classes utilitárias com tamanho fluido. A escala completa, com os valores do manual, está no manual da marca.
  • t-displayFraunces 400 · clamp(2.6rem, 1.55rem + 4.1vw, 4.6rem) · entrelinha 1.04Taça
  • t-h1Fraunces 400 · clamp(2.3rem, 1.6rem + 2.6vw, 3.5rem) · 1.08Salão
  • t-h2Fraunces 400 · clamp(1.85rem, 1.4rem + 1.6vw, 2.55rem) · 1.14Turno
  • t-h3Fraunces 400 · clamp(1.35rem, 1.2rem + 0.55vw, 1.65rem) · 1.25Mise en place
  • t-leadAlbert Sans · clamp(1.125rem, 1.05rem + 0.3vw, 1.25rem) · 1.6Couvert e carta
  • t-smallAlbert Sans · 0.875rem · 1.55Conversa inicial gratuita
  • t-eyebrowAlbert Sans 600 · 0.75rem · espaçamento 0.18em · caixa altaCarta de serviços
font-display · font-sans
Fraunces e Albert Sans, carregadas pelo next/font, com fontes de reserva.
leader
Filete pontilhado da carta, entre o nome e o detalhe.
prosa
Texto longo (guias, privacidade): largura de 68ch, listas com traço tinto, links sublinhados em latão.
<em> em títulos
Em h1, h2, h3 e .t-display, sai em itálico tinto; dentro de seção escura, em latão claro.

Espaçamento

Base de 4 px: cada unidade do Tailwind vale 0,25rem. p-5 dá 20 px, gap-8 dá 32 px. Evite valores fora da escala, como p-[13px].
  • 14 px
  • 28 px
  • 312 px
  • 416 px
  • 520 px
  • 624 px
  • 832 px
  • 1040 px
  • 1248 px
  • 1456 px
  • 1664 px
  • 2080 px
  • 2496 px

Respiro das seções

Prop spacing do Section. Há também none, para faixas que cuidam do próprio respiro, como o PageHero.

  • compact56 px / 80 pxpy-14 md:py-20
  • default80 px / 112 pxpy-20 md:py-28
  • large96 px / 144 pxpy-24 md:py-36

celular desktop

Container

Largura máxima de 1200 px (default), 820 px (narrow) ou 1320 px (wide), com margem lateral de 20 px no celular e 32 px a partir de 640 px.

Raios e sombra

Cantos quase retos, como papel cortado. Uma sombra só, para o que flutua sobre a página.
  • rounded-sm

    2 px: Botões, campos, cartões

  • rounded-md

    3 px

  • rounded-lg

    4 px

  • rounded-xl

    6 px

  • rounded-full

    círculo: Prato, fotos, botão do WhatsApp

Filete

border border-linha: o padrão para separar e emoldurar.

Sombra papel

shadow-papel: cartão em destaque e menu aberto.

Movimento

Pouco e curto. O movimento confirma uma ação; nunca carrega informação sozinho.

ease-servico

cubic-bezier(0.2, 0.7, 0.2, 1): começa rápido e termina devagar. Classe ease-servico.

Passe o mouse aqui para ver a curva.

animate-surgir

Opacidade e 10 px de subida em 0,6 s, com ease-servico. Usada na abertura da home.

Abrir e fechar o exemplo

Do primeiro olá à última taça.

Movimento reduzido

Com prefers-reduced-motion, animações e transições caem para 0,01 ms e a rolagem suave é desligada.

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

03 · Componentes

Cada peça, em funcionamento

Nome, import, propriedades e uma demonstração com o próprio componente. Nos exemplos de botão, os links apontam para esta mesma página.

ButtonLink e Button

ButtonLink é um link com cara de botão. Endereço externo (WhatsApp, Instagram) abre em nova aba, e com download vira um link de download. Button é o botão de formulário. buttonClasses devolve só as classes.

Um primário por tela, e o texto do botão sempre começa por um verbo.

import { Button, ButtonLink, buttonClasses } from "@/components/ds/button";
variant
primario (padrão), destaque, contorno, claro, contorno-claro, texto
size
md (44 px, padrão) ou lg (52 px)
icon
seta (padrão do ButtonLink), whatsapp, download, nenhum (padrão do Button)
cta
nome do clique, gravado em data-cta (ButtonLink)
download
true ou nome do arquivo (ButtonLink)
estados
hover: primário clareia, destaque escurece, contorno enche de verde. Foco: anel tinto. Desativado: 60% de opacidade.

Sobre claro: primario, destaque, contorno, texto

Sobre escuro: claro, contorno-claro, texto

Tamanhos: md e lg

Desativado (Button)

Ícones: seta, whatsapp, download, nenhum

Eyebrow

Rótulo curto acima do título, com um filete à esquerda. Tinto no claro e latão claro no escuro, sem configurar nada: a cor muda sozinha dentro de seção verde ou noite.

import { Eyebrow } from "@/components/ds/layout";
children
texto curto, sem ponto final
as
p (padrão), span ou div

Carta de serviços

Carta de serviços

SectionHeader

Cabeçalho padrão de seção: rótulo, título e abertura. Marque com <em> a palavra que carrega a frase. Passe id e use o mesmo valor no labelledBy da seção.

import { SectionHeader } from "@/components/ds/layout";
eyebrow
rótulo (opcional)
title
texto ou JSX, com <em> na palavra principal
intro
abertura em t-lead (opcional)
align
left (padrão) ou center
level
h2 (padrão) ou h1

Como o trabalho acontece

Da porta à despedida, cada momento tem dono

Quando cada etapa tem responsável e padrão, o cliente não fica perdido.

Alinhado ao centro

Do treinamento de uma tarde ao projeto de seis meses

Para seções curtas, de uma coluna.

Section e tons

Faixa de fundo inteiro com respiro padrão. Nos tons verde e noite a seção ganha a classe on-dark, e os componentes dentro dela trocam de cor sozinhos. Dentro da seção, use Container para a largura.

import { Container, Section } from "@/components/ds/layout";
tone
linho (padrão), papel, salvia, verde, noite
spacing
compact, default (padrão), large, none
id · labelledBy
âncora da seção e id do título que a nomeia
linho

Cada momento tem dono

Fundo principal das páginas

papel

Cada momento tem dono

Faixas de destaque, com filete em cima e embaixo

salvia

Cada momento tem dono

Bloco secundário, como o do Raio-X

verde

Cada momento tem dono

Método e chamada final

noite

Cada momento tem dono

Rodapé e fundos mais escuros

Carta

Lista em forma de cardápio: nome, filete pontilhado e detalhe. No celular o detalhe desce para baixo do nome. Use em listas curtas.

import { Carta, type CartaItem } from "@/components/ds/content";
items
{ title, detail?, description?, href? }[]
className
ajustes de espaço

Moments

Sequência numerada com filete em cima. Use para método e jornada do cliente; os números (01, 02...) saem sozinhos.

import { Moments, type Moment } from "@/components/ds/content";
items
{ title, text }[]
columns
2, 3 ou 4 (padrão) no desktop
  1. Chegada

    Quem chega é cumprimentado em segundos, mesmo que a mesa ainda não esteja pronta.

  2. Mesa

    A equipe sabe quem pediu o quê. Ninguém chega à mesa perguntando de quem é o filé.

  3. Conta

    Pedir a conta e pagar recebem o mesmo cuidado que pedir o prato.

  4. Despedida

    O cliente sai com um agradecimento olho no olho e um motivo para voltar.

Quote

Citação de cliente. Só fala literal, copiada das transcrições em src/content/depoimentos.ts. Nada de reescrever ou resumir o que a cliente disse.

import { Quote } from "@/components/ds/content";
children
a fala, literal
name · role
quem falou e de onde
size
md (padrão) ou lg

size="md"

Existe uma jornada do cliente aqui dentro que é muito bem pontuada, para que ele não se sinta perdido.
Marina, proprietária da GreenCake

size="lg", sobre verde

Ela nos ensinou a fazer um processo. Então hoje o nosso cliente é orientado desde o momento que ele entra na nossa porta até o momento que nós nos despedimos dele.
Marina, proprietária da GreenCake

Faq

Perguntas com details e summary. Nas páginas, os mesmos itens alimentam os dados estruturados (faqSchema), então o texto visível e o do schema nunca divergem.

import { Faq, type FaqItem } from "@/components/ds/content";
items
{ q, a }[]

Por que o FAQ usa details e summary?

Porque abre e fecha sem JavaScript, funciona com teclado e o texto continua no HTML, onde os buscadores leem.

Dá para abrir mais de uma pergunta ao mesmo tempo?

Dá. Cada pergunta é independente, e o sinal de mais gira para virar um x quando ela está aberta.

Tag

Selo pequeno de informação, ao lado de um título ou botão. Não é botão e não leva link.

import { Tag } from "@/components/ds/content";
children
texto curto
GratuitoPDFPronto para imprimir
GratuitoPDFPronto para imprimir

Campos de formulário

Rótulo sempre visível. Campo opcional ganha “(opcional)” sozinho; obrigatório, um asterisco tinto. Ajuda e erro ficam ligados ao campo por aria-describedby, e o erro marca aria-invalid.

Esta demonstração não envia nada. As mensagens de erro são as mesmas do formulário real.

import { CheckboxField, SelectField, TextAreaField, TextField } from "@/components/ds/fields";
id · label
obrigatórios; o id também vira name
hint
ajuda abaixo do campo (some quando há erro)
error
mensagem de erro, com borda vermelha no campo
required
asterisco no rótulo
options
lista de opções (SelectField)

Com DDD.

Onde fica a casa.

Breadcrumbs

Trilha visível e BreadcrumbList nos dados estruturados, no mesmo componente. O “Início” entra sozinho. O PageHero já inclui a trilha: a versão sobre claro está no topo desta página.

import { Breadcrumbs } from "@/components/sections/shared";
trail
{ name, path }[], sem o Início; o último item é a página atual

PlateRing

Borda de prato: o anel duplo do símbolo, sem o &. Emoldura fotos redondas, selos e números. A cor vem de uma classe text-*; o anel é decorativo e fica fora da leitura de tela.

import { PlateRing } from "@/components/ds/layout";
className
tamanho e cor (text-latao, text-tinto, text-latao-claro)
Samara Telles
01chegada
no canto

Ornament

Filete com o prato no meio, como a dobra de um cardápio. Separa blocos de texto longos; não use entre todas as seções.

import { Ornament } from "@/components/ds/layout";
className
largura e espaço em volta

CtaFinal

Fechamento de página: WhatsApp como caminho curto, formulário como alternativa. Escolha o contexto do WhatsApp pela página (prop wa); o nome do clique segue o contexto.

import { CtaFinal } from "@/components/sections/shared";
title · text
título com <em> e frase de apoio
wa
contexto da mensagem (padrão conversa)
formHref
destino do botão do formulário (padrão /contato)
eyebrow · tone
padrões: “Próximo passo” e verde

Próximo passo

Quer ver o padrão funcionando na sua casa?

Conte como a casa funciona hoje e o que incomoda. A Samara diz por onde faz sentido começar.

Conversa inicial gratuita e sem compromisso. Resposta em até 24 horas úteis.

LeadMagnetSection

Bloco do material gratuito, com a capa do Raio-X, a lista do que vem no checklist e o formulário de cadastro embutido. Não aparece aqui para não criar um segundo formulário de verdade nesta página.

import { LeadMagnetSection } from "@/components/sections/shared";
id
âncora (padrão raio-x)
tone
padrão salvia
title · intro
têm texto padrão; troque só quando a página pedir

Veja o componente em uso na home, nas páginas de serviço e nos guias. A página do material mostra o formulário completo.

Ver o Raio-X do Atendimento

04 · Padrões de CTA

Verde para conversar, tinto para baixar

Dois tipos de chamada, com cores e ícones próprios. Pela cor, quem lê sabe se vai falar com a Samara ou baixar um material.

Material gratuito

Leva ao Raio-X do Atendimento ou a um guia. Tinto (destaque) quando o material é a ação principal da tela; contorno com ícone de download quando divide espaço com uma conversa.

Lado a lado com uma conversa, como na abertura da home: o verde fica com a conversa e o material vai de contorno.

Mensagens do WhatsApp por contexto

Cada botão de WhatsApp abre a conversa com uma mensagem pronta, para a Samara saber de onde a pessoa veio. As mensagens ficam em waMessages (src/lib/whatsapp.ts), waLinkFor(contexto) monta o link e o botão flutuante escolhe o contexto pela rota, com waContextForPath.
  • padrao

    Mensagem
    “Olá, Samara! Vim pelo site da Servir & Encantar e quero conversar sobre o atendimento da minha casa.”
    Botão flutuante em
    //samara-telles/privacidade
  • conversa

    Mensagem
    “Olá, Samara! Quero marcar a reunião inicial sobre o atendimento da minha casa.”
    Botão flutuante em
    /contato
  • treinamento

    Mensagem
    “Olá, Samara! Quero saber sobre o Treinamento Garçom 0 a 100 para a minha equipe.”
    Botão flutuante em
    /treinamento-de-equipe
  • vinhos

    Mensagem
    “Olá, Samara! Quero saber sobre o Treinamento Vinhos Finos para a minha equipe.”
    Botão flutuante em
    Só em botões com o contexto explícito
  • temporada

    Mensagem
    “Olá, Samara! Quero preparar minha equipe para a temporada. Podemos conversar?”
    Botão flutuante em
    /guias/equipe-temporaria-para-a-temporada
  • clienteOculto

    Mensagem
    “Olá, Samara! Quero saber como funciona o Cliente Oculto para a minha casa.”
    Botão flutuante em
    Só em botões com o contexto explícito
  • diagnostico

    Mensagem
    “Olá, Samara! Quero saber sobre o Diagnóstico Operacional 360º para a minha casa.”
    Botão flutuante em
    Só em botões com o contexto explícito
  • consultoria

    Mensagem
    “Olá, Samara! Quero conversar sobre a Consultoria Servir & Encantar para a minha casa.”
    Botão flutuante em
    /consultoria-de-atendimento
  • sommelier

    Mensagem
    “Olá, Samara! Quero conversar sobre a carta de vinhos da minha casa.”
    Botão flutuante em
    /sommelier
  • cases

    Mensagem
    “Olá, Samara! Vi os depoimentos no site da Servir & Encantar e quero conversar sobre a minha casa.”
    Botão flutuante em
    /cases
  • raioX

    Mensagem
    “Olá, Samara! Fiz o Raio-X do Atendimento e quero conversar sobre o resultado.”
    Botão flutuante em
    /raio-x-do-atendimento
  • guia

    Mensagem
    “Olá, Samara! Li um guia no site da Servir & Encantar e quero tirar uma dúvida sobre a minha casa.”
    Botão flutuante em
    /guias/guias/como-montar-carta-de-vinhos/guias/reclamacao-de-cliente-no-restaurante

Atributo data-cta

Todo CTA leva um nome no atributo data-cta, usado para ler os cliques por botão. No ButtonLink, passe a prop cta; em links soltos, escreva o atributo direto.
<ButtonLink href="/contato" cta="hero-conversa">
  Agendar uma conversa
</ButtonLink>

// vira
<a href="/contato" data-cta="hero-conversa">...</a>

Como dar o nome

  • Minúsculas, palavras ligadas por hífen.
  • Primeiro o lugar, depois a ação: hero-conversa, header-raio-x.
  • Em página interna, a página vem antes: consultoria-hero-whatsapp, guia-{slug}-whatsapp.
  • No CtaFinal, o contexto do WhatsApp entra no nome: final-whatsapp-conversa.

Nomes dos componentes compartilhados

hero-conversahero-raio-x
Abertura da home
header-conversaheader-raio-x
Cabeçalho
menu-conversamenu-raio-x
Menu do celular
faixa-temporada
Faixa da temporada, no topo
whatsapp-flutuante
Botão flutuante do WhatsApp
footer-whatsapp
Rodapé
final-whatsapp-{contexto}final-formulario
CtaFinal
video-{id}
Play dos depoimentos em vídeo

05 · Acessibilidade

Para ler bem e navegar pelo teclado

O que cada componente precisa garantir, e como os componentes atuais fazem isso.

Anel de foco

Todo elemento focável ganha contorno de 2 px em tinto, afastado 3 px (:focus-visible, no globals.css). Dentro de seção escura, o contorno passa para latão claro. Aperte Tab nesta página para ver o anel de verdade.

Simulação do foco, sobre claro e sobre verde.

Contraste

Texto principal em tinta (13,8:1 sobre linho) e secundário em grafite (6,0:1). Títulos em verde (11,0:1) e ênfases em tinto (8,5:1). No escuro, rótulos e o & em latão claro (7,1:1 sobre noite).

Latão sobre linho fica em 3,0:1. Serve para filete, ícone e ornamento, nunca para texto pequeno. Rótulo sobre claro é sempre tinto.

Pular para o conteúdo

Primeiro link do cabeçalho, escondido até receber foco. Leva a #conteudo, o main de todas as páginas.

Como ele aparece ao receber foco, no canto da tela.

FAQ com details e summary

Abre e fecha com Enter ou espaço, sem JavaScript. A pergunta é um h3 dentro do summary, o que mantém a ordem dos títulos. O sinal de mais é decorativo.

<details>
  <summary>
    <h3>Pergunta</h3>
    <Plus aria-hidden />
  </summary>
  <p>Resposta</p>
</details>

Movimento reduzido

Com prefers-reduced-motion, animações e transições caem para 0,01 ms e a rolagem suave é desligada. Nenhuma informação pode depender de animação.

Regra global em src/app/globals.css, dentro de @layer base. Componente novo não precisa repetir.

Campos, ícones e idioma

Todo campo tem rótulo visível; ajuda e erro são ligados por aria-describedby, e o erro sai com role="alert". Ícone decorativo leva aria-hidden. A página declara lang="pt-BR".

Logo ao lado do nome escrito recebe title="", para não ser lido duas vezes. Sozinho, o logo leva o nome da marca como texto alternativo.