Princípios de design para engenheiros de software
Fundamentos de design para engenheiros de software: tipografia, cores, espaçamento, animação, padrões de interface de IA, design tokens e 48 estudos de caso de produtos atuais.
Atualizado em 18 de agosto de 2026
Atualização de 18 de maio de 2026: O índice de estudos de design foi atualizado para refletir o conjunto atual de 48 estudos, e a seção de padrões de interface de IA foi ampliada com evidências de fluxos de trabalho agênticos: checkpoints, estados de aprovação, confiança nas fontes e verificação visível.
Atualização de maio de 2026: Foi adicionada uma observação sobre o rascunho de trabalho de março de 2026 do WCAG 3.0 e sobre a posição do W3C de que o WCAG 2.2 e o 3.0 coexistirão. O WCAG 2.2 continua sendo o padrão a seguir nos trabalhos atuais de acessibilidade.
Atualização de fevereiro de 2026: Foram adicionadas duas novas seções — padrões de interação (8 paradigmas identificados por meio do estudo de Framer, Flighty, Halide, Warp, Bear, Craft e Superhuman) e padrões de interface de IA (design com citações em destaque, fases de streaming e transparência de erros inspirados no Perplexity). Os padrões para web foram atualizados para 2026 com posicionamento por âncoras, animações orientadas por rolagem e @starting-style. A seção de acessibilidade foi atualizada para refletir a padronização ISO do WCAG 2.2. Consulte Estudos de design para análises aprofundadas de 48 produtos excepcionais.
Passei anos estudando design enquanto desenvolvia software, absorvendo princípios de lendas como Dieter Rams e analisando minuciosamente as interfaces de produtos como Linear, Stripe e Raycast. Este guia condensa esse conhecimento na referência abrangente que eu gostaria que existisse quando comecei a me preocupar com a aparência e a experiência de uso do meu software.
Design não é decoração. É comunicação. Cada pixel comunica função, hierarquia e significado. A diferença entre um software que parece amador e outro que parece profissional está em compreender esses princípios e aplicá-los de forma consistente.
Este guia pressupõe que você já saiba escrever código. Ele ensina você a enxergar — a entender por que algumas interfaces parecem intuitivas enquanto outras parecem caóticas e, mais importante, como criar as primeiras.
Sumário
Parte 1: Fundamentos
- Psicologia Gestalt
- Tipografia
- Teoria das cores
- Hierarquia visual
- Espaçamento e ritmo
- Princípios de animação
Parte 2: Interação e IA
Parte 3: Filosofia de design
Parte 4: Implementação
- Padrões web 2026
- Sistema de design tokens
- Dark mode feito do jeito certo
- Fluxos de extração do Figma
Parte 5: Referência
Psicologia Gestalt
“O todo é diferente da soma de suas partes.” — Kurt Koffka
A psicologia Gestalt, desenvolvida na Alemanha dos anos 1920, explica como os seres humanos percebem informação visual. O cérebro não enxerga pixels individuais — ele organiza elementos em padrões significativos. Domine esses princípios para controlar como os usuários percebem suas interfaces.
Proximidade
Elementos próximos entre si são percebidos como um grupo.
Este é o princípio Gestalt mais poderoso no design de UI. O espaço comunica relacionamento mais do que qualquer outra propriedade visual.
ERRADO (espaçamento igual = sem agrupamento):
┌─────────────────┐
│ Label │
│ │
│ Input Field │
│ │
│ Label │
│ │
│ Input Field │
└─────────────────┘
CORRETO (espaçamento desigual = grupos claros):
┌─────────────────┐
│ Label │
│ Input Field │ ← Apertado (4px) - relacionados
│ │
│ │ ← Amplo (24px) - separando grupos
│ Label │
│ Input Field │ ← Apertado (4px) - relacionados
└─────────────────┘
Implementação CSS:
.form-group {
margin-bottom: 24px; /* Between groups: wide */
}
.form-group label {
margin-bottom: 4px; /* Label to input: tight */
display: block;
}
Implementação SwiftUI:
VStack(alignment: .leading, spacing: 4) { // Tight within group
Text("Email")
.font(.caption)
.foregroundStyle(.secondary)
TextField("you@example.com", text: $email)
.textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24) // Wide between groups
Similaridade
Elementos que compartilham características visuais parecem relacionados.
Quando elementos têm a mesma aparência, os usuários assumem que funcionam da mesma forma. É por isso que sistemas de design usam estilos de botão consistentes, tratamentos de cards e tipografia padronizada.
Exemplo de navegação:
┌───────────────────────────────────┐
│ [Dashboard] [Projects] [Settings] │ ← Mesmo estilo = mesma função
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │Card │ │Card │ │Card │ │ ← Mesmo estilo = mesmo tipo de conteúdo
│ └─────┘ └─────┘ └─────┘ │
│ │
│ [+ New Project] │ ← Estilo diferente = função diferente
└───────────────────────────────────┘
Figura-fundo
O conteúdo deve se separar claramente do plano de fundo.
O cérebro precisa distinguir a “figura” (no que focar) do “fundo” (o plano de fundo). Relações fracas entre figura e fundo criam confusão visual.
Técnicas: - Contraste (figura clara sobre fundo escuro, ou vice-versa) - Sombras (elevar a figura acima do fundo) - Bordas (delimitar as arestas da figura) - Desfoque (desfocar o fundo, manter a figura nítida)
/* Strong figure-ground relationship */
.card {
background: var(--color-surface); /* Figure */
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); /* Elevation */
}
.modal-overlay {
background: rgba(0, 0, 0, 0.5); /* Dim ground */
backdrop-filter: blur(4px); /* Blur ground */
}
Região comum
Elementos dentro de um limite são percebidos como agrupados.
Envolver elementos em um contêiner visual (card, caixa, área com borda) sinaliza que eles pertencem ao mesmo grupo.
Continuidade
O olho segue caminhos, linhas e curvas.
Use alinhamento e fluxo visual para guiar a atenção ao longo da sua interface.
CONTINUIDADE NO ALINHAMENTO:
┌────────────────────────────────┐
│ Logo [Nav] [Nav] [Nav] │ ← Alinhados no eixo horizontal
├────────────────────────────────┤
│ │
│ Headline │
│ ───────────────────────────── │ ← O olho segue a margem esquerda
│ Paragraph text continues │
│ along the same left edge │
│ │
│ [Primary Action] │ ← Ainda na margem esquerda
└────────────────────────────────┘
Fechamento
O cérebro completa formas incompletas.
Os usuários não precisam que cada pixel seja desenhado — eles completam mentalmente formas familiares. Isso permite designs mais minimalistas e elegantes.
/* Horizontal scroll with partial card (closure) */
.card-carousel {
display: flex;
gap: 16px;
overflow-x: auto;
padding-right: 48px; /* Show partial card = scroll hint */
}
.card-carousel .card {
flex: 0 0 280px; /* Fixed width, partial visible */
}
Referência rápida de Gestalt
| Princípio | Regra | Uso principal |
|---|---|---|
| Proximidade | Relacionados = perto, não relacionados = longe | Campos de formulário, seções de conteúdo |
| Similaridade | Mesma aparência = mesma função | Botões, cards, navegação |
| Figura-fundo | Separação clara de camadas | Cards, modais, overlays |
| Região comum | Limites agrupam conteúdo | Seções de configurações, cards de usuário |
| Continuidade | Seguir linhas e alinhamento | Timelines, fluxo de leitura |
| Fechamento | O cérebro completa formas | Ícones, dicas de rolagem, skeletons |
Tipografia
“Tipografia é o ofício de dar à linguagem humana uma forma visual durável.” — Robert Bringhurst
A tipografia é a base do design de interfaces. O texto comunica funcionalidade, hierarquia e marca. Uma tipografia ruim torna as interfaces mais difíceis de usar; uma tipografia excelente é invisível — simplesmente funciona.
Escala tipográfica
Uma escala consistente cria harmonia visual. Use uma proporção matemática.
Escala 1.25 (recomendada para UI):
:root {
/* Base: 16px (1rem) */
--text-xs: 0.64rem; /* 10.24px - use sparingly */
--text-sm: 0.8rem; /* 12.8px - captions, labels */
--text-base: 1rem; /* 16px - body text */
--text-lg: 1.25rem; /* 20px - lead text */
--text-xl: 1.563rem; /* 25px - h4 */
--text-2xl: 1.953rem; /* 31.25px - h3 */
--text-3xl: 2.441rem; /* 39px - h2 */
--text-4xl: 3.052rem; /* 48.8px - h1 */
}
Altura de linha (leading)
A altura de linha afeta dramaticamente a legibilidade. Diferentes conteúdos precisam de diferentes espaçamentos entre linhas.
| Tipo de conteúdo | Altura de linha | Por quê |
|---|---|---|
| Títulos | 1.1 - 1.2 | Compactos, em negrito, curtos |
| Texto de UI | 1.3 - 1.4 | Labels, botões |
| Corpo de texto | 1.5 - 1.7 | Parágrafos legíveis |
| Textos longos | 1.7 - 2.0 | Artigos, documentação |
Comprimento de linha (medida)
O comprimento ideal de linha previne fadiga visual e melhora a compreensão na leitura.
- Ideal: 45-75 caracteres por linha
- Alvo: 50-65 caracteres
- Máximo absoluto: 85 caracteres
p {
max-width: 65ch; /* ch unit = width of '0' character */
}
.article-body {
max-width: 70ch;
margin: 0 auto;
}
Seleção de fontes
Fontes do sistema primeiro. Elas carregam instantaneamente, combinam com a plataforma e são otimizadas para telas.
:root {
--font-sans: system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
'JetBrains Mono', Consolas, monospace;
}
Use fontes personalizadas para: - Diferenciação de marca (sites de marketing) - Sensação editorial/publicação - Intenção de design específica não alcançável com fontes do sistema
Peso da fonte para hierarquia
Use peso para estabelecer hierarquia, não apenas tamanho.
h1 { font-weight: 700; } /* Bold */
h2 { font-weight: 600; } /* Semibold */
h3 { font-weight: 600; } /* Semibold */
.lead { font-weight: 500; } /* Medium */
p { font-weight: 400; } /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }
Referência rápida de tipografia
| Propriedade | Corpo de texto | Títulos | Labels de UI |
|---|---|---|---|
| Tamanho | 16-18px | 24-48px | 12-14px |
| Peso | 400 | 600-700 | 500 |
| Altura de linha | 1.5-1.7 | 1.1-1.2 | 1.3-1.4 |
| Comprimento de linha | 45-75ch | N/A | N/A |
| Alinhamento | Esquerda | Centro OK | Esquerda |
Teoria das cores
“A cor é uma força que influencia diretamente a alma.” — Wassily Kandinsky
A cor comunica mais rápido do que as palavras. Ela estabelece o clima, guia a atenção, sinaliza significado e constrói reconhecimento de marca.
A regra 60-30-10
A distribuição de cores mais confiável para interfaces equilibradas.
┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - Dominant (Background)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - Secondary (Cards, sections)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - Accent (Buttons, links)
└──────────────────────────────────────────┘
Criando uma paleta de cores
Toda interface precisa destas cores semânticas:
:root {
/* Brand */
--color-primary: hsl(220, 80%, 50%);
--color-primary-hover: hsl(220, 80%, 45%);
/* Semantic */
--color-success: hsl(142, 76%, 36%); /* Green - positive */
--color-warning: hsl(38, 92%, 50%); /* Amber - caution */
--color-error: hsl(0, 84%, 60%); /* Red - danger */
/* Neutrals */
--color-background: hsl(0, 0%, 100%);
--color-surface: hsl(220, 14%, 96%);
--color-border: hsl(220, 13%, 91%);
/* Text */
--color-text: hsl(220, 13%, 13%);
--color-text-secondary: hsl(220, 9%, 46%);
--color-text-muted: hsl(220, 9%, 64%);
}
Psicologia das cores
| Cor | Psicologia | Uso em UI |
|---|---|---|
| Azul | Confiança, estabilidade, calma | Finanças, tecnologia, corporativo |
| Verde | Crescimento, natureza, sucesso | Saúde, eco, estados positivos |
| Vermelho | Energia, urgência, perigo | Alertas, vendas, erros |
| Laranja | Calor, entusiasmo | CTAs, marcas descontraídas |
| Amarelo | Otimismo, cautela | Avisos, destaques |
| Roxo | Luxo, criatividade | Produtos premium |
| ### Design com modo escuro em primeiro lugar (Vercel) | ||
| Vercel projeta primeiro para o modo escuro e depois deriva o modo claro. Isso produz interfaces escuras melhores porque o modo escuro se torna a consideração principal, em vez de uma reflexão tardia. |
/* Design dark first, derive light */
:root {
/* Dark mode defaults */
--color-background: hsl(0, 0%, 0%);
--color-surface: hsl(0, 0%, 7%);
--color-border: hsl(0, 0%, 15%);
--color-text: hsl(0, 0%, 93%);
--color-text-secondary: hsl(0, 0%, 63%);
}
@media (prefers-color-scheme: light) {
:root {
--color-background: hsl(0, 0%, 100%);
--color-surface: hsl(0, 0%, 97%);
--color-border: hsl(0, 0%, 89%);
--color-text: hsl(0, 0%, 9%);
--color-text-secondary: hsl(0, 0%, 40%);
}
}
Quando usar: Ferramentas para desenvolvedores, apps de mídia, dashboards — contextos em que os usuários passam longas sessões e o modo escuro reduz o cansaço visual.
Contraste de acessibilidade
| Nível | Texto normal | Texto grande | Componentes de UI |
|---|---|---|---|
| AA | 4,5:1 | 3:1 | 3:1 |
| AAA | 7:1 | 4,5:1 | N/A |
| WCAG 2.2 se tornou um padrão ISO (ISO/IEC 40500:2025) em outubro de 2025, adicionando critérios de visibilidade do foco, entrada redundante e autenticação acessível. Principais adições: os indicadores de foco não devem ficar totalmente ocultos por outro conteúdo (2.4.11), e a autenticação não deve depender apenas de testes de função cognitiva (3.3.8). O W3C publicou uma versão atualizada do WCAG 2.2 em dezembro de 2024, com previsão de lançamento como ISO/IEC 40500:2026 até o fim de 2026. |
WCAG 3.0 ainda é um working draft. A revisão mais recente foi publicada em março de 2026 e não substitui o WCAG 2.2; o W3C afirma que os dois padrões vão coexistir. O Accessibility Guidelines Working Group planeja publicar um cronograma projetado para o WCAG 3 em 2026, mas o WCAG 2.2 continua sendo o padrão a mirar no trabalho atual.
Ferramentas: WebAIM Contrast Checker, seletor de cores do Chrome DevTools
Hierarquia visual
“O design é o embaixador silencioso da sua marca.” — Paul Rand
A hierarquia visual controla o que os usuários veem primeiro, segundo e terceiro. Sem uma hierarquia clara, os usuários precisam se esforçar para encontrar informações. Com ela, as interfaces parecem simples de usar.
As seis ferramentas da hierarquia
1. Tamanho — Elementos maiores chamam atenção primeiro
.hero-title { font-size: 3rem; } /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; } /* Baseline */
2. Peso — O negrito se destaca, o leve recua
h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }
3. Cor e contraste — Alto contraste = atenção
.title { color: var(--color-text); } /* Near black */
.meta { color: var(--color-text-muted); } /* Gray */
4. Posição — Posições-chave importam
F-PATTERN (content pages): Z-PATTERN (landing pages):
████████████████████████ 1 ──────────────────► 2
████████ ↘
████ ↘
██ ↘
3 ──────────────────► 4
5. Espaço em branco — O isolamento cria importância
.hero { padding: 120px 48px; } /* Generous space */
.data-table { padding: 12px; } /* Dense content */
6. Profundidade e elevação — Elementos que parecem avançar exigem atenção
:root {
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}
.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }
Padrões aplicados
Presença colaborativa (Figma): Vários cursores de usuários com rótulos de nome, destaques de seleção e contornos de componentes criam um documento vivo. A cor de cada colaborador é distinta, mas tem o mesmo peso visual: nenhum cursor é “mais chamativo” que outro.
Indicadores sutis de status (Vercel): O status do deploy usa indicadores sutis e persistentes, em vez de alertas intrusivos. Uma barra fina de cor no topo comunica o estado (em build, publicado, com falha) sem interromper o fluxo de trabalho.
Analogias de design do mundo real (Flighty): As visualizações de progresso do voo espelham instrumentos reais da aviação: curvas de altitude, indicadores de velocidade e mapas de portão usam metáforas visuais familiares em vez de barras de progresso abstratas.
O teste de semicerrar os olhos
Semicerre os olhos ao olhar para o seu design. Você ainda consegue ver a hierarquia? Se sim, ela está forte.
Espaçamento e ritmo
“O espaço em branco é como o ar: é necessário para que o design respire.” — Wojciech Zieliński
O espaçamento é a estrutura invisível do design. Um espaçamento consistente cria ritmo visual — a sensação de que os elementos pertencem a um sistema coerente.
A grade de 8px
A grade de 8px é o padrão do setor porque: - Divide uniformemente (8, 16, 24, 32, 40, 48…) - Funciona com densidades de tela comuns (1x, 1.5x, 2x, 3x) - Cria um ritmo consistente sem matemática
:root {
--space-1: 4px; /* Tight: icon gaps */
--space-2: 8px; /* Compact: inline elements */
--space-3: 12px; /* Snug: form fields */
--space-4: 16px; /* Default: most gaps */
--space-6: 24px; /* Spacious: card padding */
--space-8: 32px; /* Section gaps */
--space-12: 48px; /* Major sections */
--space-16: 64px; /* Page sections */
--space-20: 80px; /* Hero spacing */
}
Espaçamento interno vs externo
Interno (padding): Espaço dentro de um elemento Externo (margin): Espaço entre elementos
Regra: O espaçamento interno normalmente deve ser maior que o espaçamento externo dentro de grupos relacionados.
.card {
padding: 24px; /* Internal: spacious */
margin-bottom: 16px; /* External: less than padding */
}
Padrões de espaçamento de componentes
Cards:
.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; } /* Tight to subtitle */
Botões:
.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }
Formulários:
.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }
Referência rápida de espaçamento
| Contexto | Espaçamento recomendado |
|---|---|
| Do ícone ao texto | 4-8px |
| Do rótulo ao campo | 4px |
| Entre grupos do formulário | 24px |
| Padding do card | 20-24px |
| Espaçamento entre cards | 16-24px |
| Padding da seção (mobile) | 48-64px |
| Padding da seção (desktop) | 80-96px |
| Padding do botão (h/v) | 24px / 12px |
| — |
Princípios de animação
“Animação não é a arte de desenhos que se movem, mas a arte de movimentos que são desenhados.” — Norman McLaren
Animação dá vida às interfaces. Bem feita, ela direciona a atenção, comunica estado e cria conexão emocional. Mal feita, frustra e distrai.
O princípio fundamental
Animação deve parecer inevitável, não decorativa.
Boa animação: 1. Comunica algo que o design estático não consegue 2. Reduz a carga cognitiva ao mostrar relações 3. Parece natural e esperada 4. Desaparece da percepção consciente
Má animação: 1. Existe apenas porque “fica legal” 2. Atrasa o usuário 3. Chama atenção para si mesma 4. Gera ansiedade ou impaciência
Princípios-chave para UI
1. Antecipação — Prepare os usuários para o que vem a seguir.
.button {
transition: transform 0.1s ease-out;
}
.button:active {
transform: scale(0.97); /* Slight press before action */
}
2. Continuidade — Deixe o movimento se completar naturalmente com uma acomodação tipo mola.
.panel {
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
isOpen = true
}
3. Ease-In, Ease-Out — Nada na natureza se move em velocidade constante.
| Curva | Quando usar | Caráter |
|---|---|---|
ease-out |
Elementos entrando | Início rápido, parada suave |
ease-in |
Elementos saindo | Início suave, saída rápida |
ease-in-out |
Mudanças de estado | Suave do início ao fim |
linear |
Indicadores de carregamento | Contínuo, mecânico |
4. Encenação — Direcione a atenção para o que importa. Apenas um elemento deve se mover por vez, a menos que coreografado como grupo.
5. Escalonamento — Elementos devem chegar em sequência, não todos de uma vez.
.list-item {
animation: fadeSlideIn 0.3s ease-out both;
}
.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }
@keyframes fadeSlideIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
Diretrizes de tempo
| Duração | Caso de uso | Sensação |
|---|---|---|
| 50-100ms | Micro-interações (hover, press) | Feedback instantâneo |
| 150-200ms | Mudanças de estado simples (toggle, seleção) | Ágil |
| 250-350ms | Transições médias (painel deslizante, virada de card) | Suave |
| 400-500ms | Movimentos amplos (transições de página, modais) | Deliberado |
Performance: a regra de ouro
Anime apenas transform e opacity — esses são acelerados por GPU e não disparam recálculo de layout.
/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }
/* GOOD: Using transform */
.panel { transition: transform 0.3s; }
Quando NÃO animar
-
O usuário tem
prefers-reduced-motionativadocss @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } -
A animação não acrescenta informação — spinners gratuitos, elementos saltitantes
- O usuário está com pressa — estados de erro, validação de formulário, resultados de busca
- A animação atrasaria ações repetidas — atalhos de teclado devem ignorar animações
- Os dados já estão carregados — Bear usa zero estados de carregamento ao pré-carregar o conteúdo, fazendo o app parecer instantâneo. Se você consegue pré-carregar, pule o skeleton/spinner completamente.
// Bear's approach: preload so no loading state is needed
struct NoteListView: View {
@Query var notes: [Note] // SwiftData loads from disk instantly
// No loading state, no skeleton, no spinner — data is always there
var body: some View {
List(notes) { note in
NoteRow(note: note)
}
}
}
Referência rápida de animação
:root {
/* Durations */
--duration-instant: 0.1s;
--duration-fast: 0.15s;
--duration-normal: 0.25s;
--duration-slow: 0.4s;
/* Easings */
--ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
--ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
--ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
--ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}
Padrões de interação
“A melhor interface é nenhuma interface.” — Golden Krishna
Padrões de interação definem como os usuários manipulam, navegam e compreendem seu produto. Esses padrões foram extraídos do estudo de produtos que entregam interações excepcionais.
Manipulação direta (Framer)
Torne conceitos abstratos tangíveis. Framer transforma breakpoints de CSS — números abstratos — em alças arrastáveis. Os usuários veem os layouts se adaptarem em tempo real.
/* Breakpoint handle styling */
.breakpoint-handle {
position: absolute;
top: 0;
bottom: 0;
width: 4px;
background: var(--accent);
cursor: col-resize;
opacity: 0.6;
transition: opacity 0.15s ease;
}
.breakpoint-handle:hover,
.breakpoint-handle:active {
opacity: 1;
width: 6px;
}
Quando usar: Qualquer configuração em que o resultado é visual — arrastar para redimensionar, seletores de cor, scrubbing de timeline.
Interfaces sensíveis ao contexto (Flighty, Figma)
Mostre apenas o que é relevante para o momento atual. Flighty usa 15 estados distintos para rastreamento de voos. O painel de propriedades do Figma se transforma completamente com base no que você selecionou.
| Fase (Flighty) | O que o usuário vê |
|---|---|
| 24h antes | Código de confirmação, informações do terminal |
| No aeroporto | Número do portão, horário de embarque |
| Em voo | Tempo restante, progresso, horário estimado de chegada |
| Pouso | Portões de conexão, caminho a percorrer |
enum ContextState: CaseIterable {
case farOut, dayBefore, headToAirport, atAirport
case atGate, boarding, inFlight, landed, connection
static func current(for flight: Flight, context: UserContext) -> ContextState {
// Factor in: time, location, flight status
// Return the single most relevant state
}
}
Anti-padrão: Mostrar todos os controles e deixar os irrelevantes esmaecidos. Isso cria ruído visual.
Ativação inteligente (Halide)
Ferramentas devem perceber o contexto e se ativar automaticamente. A lupa de foco do Halide aparece ao arrastar o foco e desaparece ao soltar. Nenhum botão de alternância necessário.
struct IntelligentlyActivated<Content: View>: ViewModifier {
let isInteracting: Bool
@State private var isVisible = false
func body(content: Content) -> some View {
content
.opacity(isVisible ? 1 : 0)
.scaleEffect(isVisible ? 1 : 0.95)
.animation(.easeInOut(duration: 0.2), value: isVisible)
.onChange(of: isInteracting) { _, newValue in
if newValue {
withAnimation { isVisible = true }
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
if !isInteracting { isVisible = false }
}
}
}
}
}
Design de modo duplo (Halide, Warp)
Mudanças de modo devem transformar a UI, não apenas alternar elementos. Os modos Auto e Manual do Halide são interfaces completamente diferentes. Warp conecta CLI e GUI por meio de quatro métodos de entrada (digitação, paleta, IA, mouse) sem forçar os usuários a adotar um único paradigma.
Conteúdo estruturado (Warp, Bear, Craft)
Adicione estrutura a conteúdo tradicionalmente não-estruturado. Warp transforma a saída do terminal em blocos discretos que podem ser copiados, compartilhados ou reexecutados. Bear permite organizar notas inline enquanto escreve (#tag/subtag). Craft permite que qualquer bloco se torne uma página — a estrutura emerge do uso, não de uma hierarquia predefinida.
Treinamento progressivo (Superhuman)
Ensine aos usuários o caminho rápido por meio de exposição repetida. A paleta Cmd+K do Superhuman sempre exibe atalhos de teclado junto aos resultados. Cada uso é uma micro-lição.
/* Always show shortcut alongside command name */
.command-result {
display: flex;
justify-content: space-between;
padding: 8px 12px;
}
.command-shortcut {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
background: var(--bg-subtle);
padding: 2px 6px;
border-radius: 4px;
}
Anti-padrão: Modais de tutorial que explicam funcionalidades. Explicação é esquecida; prática é lembrada.
Padrões de interface de AI
“As melhores interfaces de AI tornam o processo da máquina visível e o resultado da máquina verificável.”
As interfaces de AI enfrentam desafios únicos: os usuários não conseguem prever o resultado, verificar a precisão apenas pela inspeção e, muitas vezes, nem mesmo saber se o sistema está funcionando ou com problemas.
O problema central
| Software tradicional | Software de AI |
|---|---|
| O resultado é previsível | O resultado varia |
| Os erros são óbvios | Os erros parecem plausíveis |
| Os usuários verificam fazendo testes | Os usuários verificam consultando as fontes |
| Carregamento = espera | Carregamento = trabalho em andamento (mostre isso) |
| Confiança por padrão | A confiança precisa ser conquistada |
Design centrado em citações (Perplexity)
Toda afirmação factual deve conter um link para sua fonte. O Perplexity insere citações inline [1] em cada afirmação, com prévias ao passar o cursor e um painel de fontes persistente.
.citation-marker {
position: relative;
color: var(--accent);
cursor: pointer;
font-size: 0.8em;
vertical-align: super;
}
.citation-preview {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
width: 280px;
padding: 12px;
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
Antipadrão: interfaces de AI que geram afirmações sem fontes rastreáveis. Se o modelo não conseguir citar uma fonte, a interface deve sinalizar isso.
Indicadores das etapas de streaming (Perplexity)
Mostre aos usuários o que a AI está fazendo, não apenas que ela está trabalhando. Substitua indicadores de carregamento genéricos por indicadores de etapa: “Pesquisando…” → “Lendo 4 fontes…” → “Escrevendo a resposta…”
.phase-indicator {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
background: color-mix(in srgb, var(--phase-color) 10%, transparent);
border-radius: 16px;
font-size: 13px;
color: var(--phase-color);
transition: all 0.3s ease;
}
.loading-dots span {
width: 4px;
height: 4px;
background: currentColor;
border-radius: 50%;
animation: pulse 1.4s ease-in-out infinite;
}
Transparência sobre erros
Quando a AI falhar ou estiver incerta, deixe isso claro — não esconda o problema atrás de um texto que pareça confiante.
| Situação | Padrão ruim | Padrão bom |
|---|---|---|
| Baixa confiança | Afirmar com confiança | “Não tenho certeza, mas…” com estilo menos destacado |
| Nenhuma fonte encontrada | Inventar um texto | “Não encontrei fontes para esta afirmação” |
| Fontes contraditórias | Escolher uma sem avisar | Mostrar ambas com o conflito destacado |
| Informações desatualizadas | Apresentar como atuais | “Em [data]…” com um indicador de atualidade |
Insight principal: os usuários perdoam uma AI que admite suas incertezas. Eles não perdoam uma AI que está errada e ainda assim demonstra confiança.
Evidências em fluxos de trabalho agênticos
Os agentes de AI precisam de estados de interface que comprovem o trabalho, não apenas descrevam o esforço. Um bom fluxo de trabalho agêntico torna o progresso compreensível por meio de checkpoints: plano aceito, fontes reunidas, alterações aplicadas, testes executados, revisão pendente e lançamento bloqueado ou pronto.
| Estado do agente | Padrão de interface | Por que isso é importante |
|---|---|---|
| Planejamento | Objetivo e critérios de aceitação explícitos | Impede que o agente otimize para gerar atividade em vez de alcançar o resultado |
| Exploração | Lista de fontes com nível de confiança e atualidade | Permite que os usuários diferenciem fatos verificados de hipóteses de trabalho |
| Execução | Resumo dos arquivos alterados vinculado aos checkpoints | Permite revisar as alterações sem ler toda a transcrição |
| Verificação | Evidência por meio de teste, rota, captura de tela ou execução | Separa as provas da confiança artificial |
| Lançamento | Estado de aprovação, deploy ou revisão nativa | Impede que a publicação esconda trabalho inacabado atrás de verificações locais bem-sucedidas |
Antipadrão: um único estado “Concluído” para um trabalho agêntico com várias etapas. Trabalhos complexos exigem uma cadeia de custódia visível: o que mudou, o que comprovou o resultado, o que foi recusado e o que ainda precisa do julgamento humano.
Dieter Rams: dez princípios
“Menos, porém melhor.” — Dieter Rams
Dieter Rams é o designer industrial mais influente do século 20. Como diretor de design da Braun de 1961 a 1995, ele criou produtos que continuam atemporais décadas depois. Seu trabalho inspirou diretamente a linguagem de design da Apple.
Os dez princípios do bom design
1. O bom design é inovador Não copie. Combine o avanço da tecnologia com um design inovador.
2. O bom design torna um produto útil Cada elemento deve cumprir uma finalidade. A forma segue a função.
3. O bom design é estético A beleza não é superficial — ela é essencial. Os produtos que usamos diariamente afetam nosso bem-estar.
4. O bom design torna um produto compreensível Os usuários não deveriam precisar de instruções. A própria interface ensina como usá-la.
5. O bom design é discreto O design deve dar suporte, não sobrecarregar. O conteúdo do usuário é o protagonista, não a sua UI.
/* Obtrusive: UI competes with content */
.editor {
background: linear-gradient(135deg, purple, blue);
border: 3px dashed gold;
}
/* Unobtrusive: UI recedes, content shines */
.editor {
background: var(--color-background);
border: 1px solid var(--color-border);
}
6. O bom design é honesto Não use padrões obscuros. Não prometa além do que pode cumprir. Seja transparente sobre as limitações.
7. O bom design é duradouro Evite tendências que ficarão ultrapassadas rapidamente. Prefira o clássico ao que está na moda.
TRENDY (will date): TIMELESS:
- Extreme glassmorphism - Clean typography
- Neon colors, glitch effects - Subtle elevation
- Aggressive gradients - Neutral palette with considered accent
8. O bom design é minucioso até o último detalhe Nada deve ser arbitrário. Estados de carregamento, estados vazios, estados de erro — tudo deve ser projetado.
9. O bom design é sustentável Performance também é uma questão ambiental. Respeite a atenção do usuário. Escreva código eficiente.
10. O bom design é o mínimo possível de design Remova tudo o que não for necessário. O melhor design é invisível.
Padrões web de 2026
O CSS nativo agora substitui o JavaScript em um conjunto cada vez maior de problemas de layout e interação. O período de 2025 a 2026 trouxe posicionamento por âncora, animações controladas por rolagem e @starting-style aos navegadores disponíveis em produção, enquanto meados de 2026 adicionaram dimensionamento automático de controles de formulário, decorações de espaçamento e ajuste automático de texto.
Aqui, o status de suporte importa mais do que a novidade. Um recurso disponível em um único mecanismo é um aprimoramento progressivo; um recurso classificado como Baseline Newly available pode ser usado com segurança. A tabela abaixo separa os dois casos em agosto de 2026.
| Recurso | Chrome | Firefox | Safari | Status |
|---|---|---|---|---|
field-sizing |
123 | 152 | 26.2 | Baseline Newly available |
shape-outside: rect() / xywh() |
149 | 149 | 17.2 | Baseline Newly available |
background-clip: border-area |
150 | — | 18.2 | Dois mecanismos |
Decorações de espaçamento (column-rule em grid/flex) |
149 | — | — | Somente Chrome |
text-fit |
150 | — | — | Somente Chrome |
focusgroup |
150 | — | — | Somente Chrome |
Fontes: Novidades da plataforma web em junho e julho, web.dev.
Consultas de contêiner
Dimensione os componentes com base no contêiner, não na viewport.
.card-grid {
container-type: inline-size;
container-name: card-grid;
}
.card {
display: grid;
gap: 16px;
padding: 20px;
}
@container card-grid (min-width: 400px) {
.card {
grid-template-columns: auto 1fr;
}
}
@container card-grid (min-width: 600px) {
.card {
padding: 32px;
gap: 24px;
}
}
O seletor :has()
Seleção do elemento pai com base nos filhos — algo que antes era impossível sem JavaScript.
/* Card with image gets different padding */
.card:has(img) {
padding: 0;
}
.card:has(img) .card-content {
padding: 20px;
}
/* Form group with error */
.form-group:has(.input:invalid) .form-label {
color: var(--color-error);
}
/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
background: var(--color-surface);
}
Aninhamento de CSS
Aninhamento nativo sem pré-processadores.
.card {
background: var(--color-surface);
border-radius: 12px;
padding: 24px;
& .card-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 8px;
}
& .card-body {
color: var(--color-text-secondary);
line-height: 1.6;
}
&:hover {
box-shadow: var(--shadow-md);
}
@media (min-width: 768px) {
padding: 32px;
}
}
Decorações de espaçamento
Os espaçamentos de grid e flex podem ter suas próprias linhas, então os divisores não exigem mais pseudoelementos, bordas em cada elemento filho nem um wrapper por coluna. Disponível somente no Chrome 149 e versões posteriores, o que torna esse recurso um aprimoramento progressivo, não uma base.
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 32px;
/* Vertical rules between columns, horizontal between rows */
column-rule: 1px solid var(--color-border);
row-rule: 1px solid var(--color-border);
}
A abordagem antiga aplicava um border-left a todos os itens, exceto ao primeiro, e deixava de funcionar assim que o grid passava para uma segunda linha. As decorações são desenhadas no próprio espaçamento, portanto continuam corretas quando os itens quebram de linha.
Como o suporte está limitado a um único mecanismo, trate essas linhas como decoração, nunca como o elemento que separa significados. Um layout que se torna ambíguo sem elas é um layout que falha no Firefox e no Safari.
Controles de formulário que se ajustam ao conteúdo
field-sizing: content permite que inputs, textareas e selects aumentem ou diminuam conforme o usuário digita, substituindo o JavaScript baseado na altura de rolagem que toda base de código acaba reimplementando.
.comment-box {
field-sizing: content;
min-height: 3lh; /* floor: three lines */
max-height: 12lh; /* ceiling: then scroll */
}
.tag-input {
field-sizing: content;
min-width: 8ch;
}
Sempre combine esse recurso com limites min-/max-. Sem um limite mínimo, um campo vazio encolhe até quase desaparecer; sem um limite máximo, um texto longo colado no campo empurra o botão de envio para fora da tela.
Esse recurso alcançou o status Baseline Newly available em junho de 2026, portanto pode ser usado com segurança como mecanismo principal, não apenas como aprimoramento.
Texto que se ajusta à caixa
text-fit dimensiona a fonte para preencher a largura do contêiner, atendendo aos casos de títulos de destaque e números grandes em dashboards que antes exigiam um script de medição.
.stat-value {
text-fit: consistent; /* one size for the whole box */
}
Disponível somente no Chrome 150. Defina primeiro um font-size normal para que outros mecanismos recebam um tamanho intencional, não um valor padrão:
.stat-value {
font-size: clamp(2rem, 8vw, 6rem); /* the real answer everywhere */
text-fit: consistent; /* refinement where supported */
}
clamp() já resolve a maior parte dos casos em que as pessoas recorrem a esse recurso e tem suporte universal. Use text-fit quando o comprimento do conteúdo variar tanto que nenhuma configuração única de clamp funcione.
Bordas em gradiente sem truques
background-clip: border-area pinta um fundo na caixa da borda, transformando as bordas em gradiente em uma regra de duas linhas, sem exigir elementos aninhados nem truques com mask-composite.
.featured-card {
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(var(--color-surface), var(--color-surface)) padding-box,
linear-gradient(135deg, #6366f1, #ec4899) border-area;
}
Disponível no Chrome 150 e no Safari 18.2; o Firefox ainda não implementou o recurso. Declare primeiro um border-color sólido para que o fallback seja uma borda real, não transparente.
Navegação com as setas sem um manipulador de keydown
O atributo focusgroup informa ao navegador que um conjunto de controles forma uma única unidade de teclado: Tab entra no grupo uma vez, as setas navegam dentro dele e Tab sai. Barras de ferramentas, listas de abas, controles segmentados e grupos de botões no estilo de opções de rádio precisam desse comportamento — e essa é a parte que componentes implementados manualmente erram com mais frequência.
<div role="toolbar" focusgroup="wrap">
<button>Bold</button>
<button>Italic</button>
<button>Underline</button>
</div>
wrap faz com que a seta no último item retorne ao primeiro. Por padrão, a navegação para nas extremidades.
Disponível somente no Chrome 150, portanto mantenha o manipulador de keydown existente até que o suporte aumente. Vale a pena conhecer o atributo desde já porque ele define com precisão o comportamento acessível: uma barra de ferramentas deve ocupar uma única parada de tabulação, não cinco, e essa expectativa antecede o atributo em décadas. As Práticas de criação da ARIA descrevem o padrão, independentemente de como ele é implementado.
Integração com HTMX
Interatividade controlada pelo servidor sem frameworks pesados de JavaScript.
<!-- Load content on click -->
<button hx-get="/api/more-items"
hx-target="#item-list"
hx-swap="beforeend"
hx-indicator="#loading">
Load More
</button>
<!-- Form with inline validation -->
<form hx-post="/api/contact"
hx-target="#form-response"
hx-swap="outerHTML">
<input type="email" name="email"
hx-post="/api/validate-email"
hx-trigger="blur"
hx-target="next .error" />
<span class="error"></span>
</form>
Posicionamento por âncora
Posicionamento nativo com CSS de um elemento em relação a outro — sem precisar de JavaScript. Tooltips, popovers e menus suspensos que acompanham seus elementos acionadores.
/* Anchor an element to another */
.trigger {
anchor-name: --my-trigger;
}
.tooltip {
position: fixed;
position-anchor: --my-trigger;
top: anchor(bottom);
left: anchor(center);
translate: -50% 8px;
}
Animações controladas por rolagem
Vincule o progresso da animação à posição de rolagem. Indicadores de progresso de leitura, efeitos de paralaxe e sequências de revelação sem JavaScript.
/* Reading progress bar */
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: var(--color-primary);
transform-origin: left;
animation: progress linear;
animation-timeline: scroll();
}
@keyframes progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
@starting-style
Defina os estilos iniciais dos elementos que entram no DOM, permitindo animações de entrada feitas somente com CSS, sem JavaScript.
.card {
opacity: 1;
transform: translateY(0);
transition: opacity 0.3s ease, transform 0.3s ease;
@starting-style {
opacity: 0;
transform: translateY(10px);
}
}
Sistema de design tokens
Um sistema completo de tokens para manter a consistência em todo o aplicativo.
:root {
/* Colors */
--color-text: #1a1a1a;
--color-text-secondary: #666666;
--color-text-muted: #999999;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-surface-elevated: #ffffff;
--color-border: #e5e7eb;
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-error: #ef4444;
/* Typography */
--font-sans: system-ui, -apple-system, sans-serif;
--font-mono: "SF Mono", Consolas, monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--leading-tight: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
/* Spacing (8px base) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
/* Borders */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
/* Transitions */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--duration-fast: 100ms;
--duration-normal: 200ms;
}
Dark mode bem-feito
Não se limite a inverter as cores — redesenhe para contextos escuros.
@media (prefers-color-scheme: dark) {
:root {
/* Neutrals */
--color-background: hsl(220, 13%, 10%);
--color-surface: hsl(220, 13%, 15%);
--color-surface-elevated: hsl(220, 13%, 18%);
--color-border: hsl(220, 13%, 23%);
/* Text (inverted) */
--color-text: hsl(220, 9%, 93%);
--color-text-secondary: hsl(220, 9%, 70%);
--color-text-muted: hsl(220, 9%, 55%);
/* Adjust saturation for dark mode */
--color-primary: hsl(220, 80%, 60%);
--color-success: hsl(142, 70%, 45%);
--color-error: hsl(0, 80%, 65%);
/* Shadows in dark mode need adjustment */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
Princípios do dark mode: - Reduza a saturação em superfícies grandes - Aumente a luminosidade das cores de destaque - Reforce as sombras (elas precisam de mais contraste) - Crie o dark mode de forma intencional, não como algo secundário
Fluxos de extração do Figma
Transformar arquivos de design em código pronto para produção exige a extração sistemática dos tokens de design — cores, tipografia, espaçamento e efeitos que definem a linguagem visual.
Exportação de variáveis do Figma
O recurso nativo Variables do Figma oferece o caminho mais simples para a extração:
Etapas de exportação:
1. Abra o arquivo do Figma → painel Local Variables e abra a coleção
2. Clique com o botão direito em um modo → “Export mode” (ou clique com o botão direito na coleção → “Export modes” — você receberá um arquivo JSON por modo)
3. Salve o(s) arquivo(s) exportado(s), por exemplo, figma-variables.json
A exportação e a importação nativas do Figma seguem o formato DTCG — chaves $value/$type, nomes de grupos unidos por / — e a importação aceita apenas tokens com essa estrutura.
Estrutura de tokens JSON:
{
"colors": {
"primitive": {
"blue-500": { "$value": "#3b82f6", "$type": "color" },
"blue-600": { "$value": "#2563eb", "$type": "color" }
},
"semantic": {
"primary": { "$value": "{colors.primitive.blue-500}", "$type": "color" },
"primary-hover": { "$value": "{colors.primitive.blue-600}", "$type": "color" }
}
},
"spacing": {
"1": { "$value": "4px", "$type": "spacing" },
"2": { "$value": "8px", "$type": "spacing" },
"4": { "$value": "16px", "$type": "spacing" }
}
}
Transformação de tokens em CSS
Propriedades personalizadas de CSS:
:root {
/* Primitive colors (direct values) */
--color-blue-50: #eff6ff;
--color-blue-100: #dbeafe;
--color-blue-500: #3b82f6;
--color-blue-600: #2563eb;
--color-blue-900: #1e3a8a;
/* Semantic colors (reference primitives) */
--color-primary: var(--color-blue-500);
--color-primary-hover: var(--color-blue-600);
--color-background: var(--color-white);
--color-surface: var(--color-gray-50);
/* Spacing (8px grid) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
/* Typography */
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
/* Effects */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
}
Tokens de dark mode:
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--color-gray-900);
--color-surface: var(--color-gray-800);
--color-text: var(--color-gray-100);
--color-text-secondary: var(--color-gray-400);
/* Adjusted shadows for dark mode */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
}
}
Transformação de tokens em SwiftUI
Extensão de cores:
import SwiftUI
extension Color {
// MARK: - Primitive Colors
static let blue50 = Color(hex: "eff6ff")
static let blue500 = Color(hex: "3b82f6")
static let blue600 = Color(hex: "2563eb")
// MARK: - Semantic Colors
static let brandPrimary = Color.blue500
static let brandPrimaryHover = Color.blue600
// MARK: - Surface Colors
static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}
extension Color {
init(hex: String) {
// Standard hex parsing implementation
}
init(light: Color, dark: Color) {
self.init(UIColor { traits in
traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
})
}
}
Constantes de espaçamento:
enum Spacing {
static let xs: CGFloat = 4 // --space-1
static let sm: CGFloat = 8 // --space-2
static let md: CGFloat = 16 // --space-4
static let lg: CGFloat = 24 // --space-6
static let xl: CGFloat = 32 // --space-8
}
// Usage
VStack(spacing: Spacing.md) {
// ...
}
.padding(Spacing.lg)
Checklist de entrega do designer
O que os designers devem exportar:
| Tipo de recurso | Formato | Observações |
|---|---|---|
| Cores | Variables JSON | Inclua os modos claro e escuro |
| Tipografia | Exportação de estilos | Fonte, tamanho, peso, line-height |
| Espaçamento | Variables JSON | Unidade-base documentada |
| Ícones | SVG | Contornos, uma única cor |
| Imagens | PNG @2x/@3x ou WebP | Com compactação |
| Componentes | Links do Figma | Para consulta durante a implementação |
Critérios de controle de qualidade:
- [ ] Todas as cores estão definidas como variáveis (sem valores hexadecimais fixos)
- [ ] A tipografia usa estilos de texto definidos
- [ ] O espaçamento segue o sistema de grid (base de 8px)
- [ ] Foram fornecidas variantes para dark mode
- [ ] Os estados interativos estão documentados (hover, active, disabled)
- [ ] Os breakpoints responsivos estão anotados
- [ ] Os requisitos de acessibilidade estão indicados (taxas de contraste)
O desenvolvedor recebe:
- Arquivos de tokens (JSON/CSS/Swift, dependendo da plataforma)
- Especificações dos componentes com medidas
- Recursos exportados nos formatos exigidos
- Documentação das interações (estados, animações)
- Anotações de acessibilidade
Tabelas de referência rápida
Princípios de Gestalt
| Princípio | Regra | Uso |
|---|---|---|
| Proximidade | Relacionados = próximos | Formulários, seções |
| Similaridade | Mesma aparência = mesma função | Botões, cards |
| Figura-fundo | Separação clara entre camadas | Modais, cards |
| Continuidade | Siga as linhas | Linhas do tempo, alinhamento |
| Fechamento | O cérebro completa as formas | Ícones, indicações de rolagem |
Tipografia
| Elemento | Tamanho | Peso | Altura da linha |
|---|---|---|---|
| Corpo do texto | 16px | 400 | 1,5-1,7 |
| Títulos | 24-48px | 600-700 | 1,1-1,2 |
| Rótulos da UI | 12-14px | 500 | 1,3-1,4 |
| Legendas | 12px | 400 | 1,4 |
Funções das cores
| Função | Modo claro | Modo escuro |
|---|---|---|
| Fundo | #ffffff | #0f172a |
| Superfície | #f4f5f7 | #1e293b |
| Borda | #e4e6ea | #334155 |
| Texto | #1a1a2e | #f1f5f9 |
| Texto atenuado | #6b7280 | #94a3b8 |
| Primária | #3b82f6 | #60a5fa |
| Sucesso | #22c55e | #4ade80 |
| Erro | #ef4444 | #f87171 |
Escala de espaçamento
| Token | Valor | Uso |
|---|---|---|
| –space-1 | 4px | Espaços entre ícones |
| –space-2 | 8px | Elementos inline |
| –space-4 | 16px | Espaços padrão |
| –space-6 | 24px | Padding dos cards |
| –space-8 | 32px | Espaços entre seções |
| –space-16 | 64px | Seções da página |
Checklist de design
Antes de lançar qualquer interface, verifique:
Gestalt
- [ ] Os elementos relacionados estão mais próximos do que os não relacionados (Proximidade)
- [ ] Funções semelhantes têm estilos semelhantes (Similaridade)
- [ ] Há uma separação clara entre o primeiro plano e o fundo (Figura-fundo)
- [ ] O olhar percorre o layout naturalmente (Continuidade)
Tipografia
- [ ] O tamanho-base da fonte é de pelo menos 16px
- [ ] A altura da linha é de 1,5 ou mais para o corpo do texto
- [ ] O comprimento das linhas é inferior a 75 caracteres
- [ ] A hierarquia está clara (3 níveis distinguíveis)
- [ ] Uma escala consistente é usada em toda a interface
Cor
- [ ] Todo o texto atende ao contraste de 4,5:1 (WCAG AA)
- [ ] A cor não é o único indicador (também há ícones/rótulos)
- [ ] O dark mode foi criado de forma intencional
- [ ] A distribuição 60-30-10 foi seguida
Hierarquia visual
- [ ] É possível identificar o elemento mais importante
- [ ] O olhar segue a ordem planejada
- [ ] Há um CTA claro por seção
- [ ] A escala tipográfica é consistente
Espaçamento
- [ ] Todo o espaçamento usa uma escala definida (sem números arbitrários)
- [ ] Cards/componentes têm padding consistente
- [ ] O espaçamento em dispositivos móveis é confortável
- [ ] O alinhamento do grid é consistente (base de 8px)
Interação
- [ ] Os usuários conseguem atingir seus objetivos sem precisar pensar na ferramenta?
- [ ] A UI se adapta ao contexto atual?
- [ ] As ferramentas ficam visíveis somente quando são relevantes?
- [ ] O uso repetido ensina métodos mais rápidos?
Interfaces de IA
- [ ] Toda afirmação factual tem uma fonte rastreável
- [ ] O streaming mostra as etapas do processo, não apenas um spinner
- [ ] Os estados de erro são transparentes, não ficam ocultos
- [ ] As respostas com baixa confiança são diferenciadas visualmente
Verificação de Dieter Rams
- [ ] É possível remover alguma coisa?
- [ ] Cada elemento cumpre uma função?
- [ ] Isso pareceria ultrapassado daqui a 5 anos?
- [ ] Projetei todos os estados?
Recursos
Livros: - As Little Design as Possible, de Sophie Lovell (Dieter Rams) - The Elements of Typographic Style, de Robert Bringhurst
Ferramentas: - Verificador de contraste do WebAIM - Gerador de escala tipográfica - Figma Tokens Studio — Gerenciamento de tokens de design
Sistemas de design: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui
Estudos de design
Análises aprofundadas de 48 produtos excepcionais, documentando padrões e princípios que vale a pena aproveitar.
Ferramentas para desenvolvedores e AI
| Produto | Principal contribuição |
|---|---|
| Figma | Presença multiusuário, painéis sensíveis ao contexto |
| Warp | Terminal baseado em blocos, ponte entre CLI e GUI |
| Framer | Design responsivo visual, controles de propriedades |
| Vercel | Excelência no modo escuro, status ambiente |
| Linear | Optimistic UI, fluxo de trabalho centrado no teclado |
| Raycast | Sistema de extensões, ações rápidas |
| Stripe | Excelência na documentação, design de API |
| Perplexity | AI centrada em citações, fases de streaming |
| Obsidian | Composição local-first, interfaces de grafos de conhecimento |
Ferramentas nativas da Apple e de criação
| Produto | Principal contribuição |
|---|---|
| Flighty | 15 estados inteligentes, Live Activities, visualização de dados |
| Halide | Ativação inteligente, controles por gestos |
| Bear | Tipografia em primeiro lugar, tags integradas ao texto |
| Craft | Experiência nativa em várias plataformas, páginas aninhadas |
| Things | Datas adiadas, padrões de entrada rápida |
| Darkroom | UI escura e imersiva, edição centrada em fotos |
| Procreate | Ferramentas criativas centradas em gestos |
| Overcast | Engenharia de áudio invisível como design de interface |
| Camo | UI profissional para produção de vídeo |
| Ivory | Timeline bem elaborada, precisão divertida |
| Anybox | Transparência nativa da plataforma |
| Drafts | Clareza na captura centrada em texto |
| Notion Calendar | Precisão no calendário, integração com o workspace |
Produtividade, conhecimento e finanças
| Produto | Principal contribuição |
|---|---|
| Superhuman | Regra dos 100 ms, treinamento da paleta de comandos, onboarding com prática |
| Notion | Sistema de blocos, comandos com barra |
| Arc | Espaços, visualização dividida, barra de comandos |
| Todoist | Minimalismo acolhedor, máxima contenção |
| Amie | Produtividade prazerosa, minimalismo acolhedor |
| Loom | Profissionalismo amigável em vídeos assíncronos |
| Pitch | Linguagem visual marcante para apresentações |
| Readwise Reader | Ferramentas para leitura profunda, identidade visual cósmica |
| Copilot Money | Visualização cinematográfica de dados financeiros |
| 1Password | Segurança sem atritos |
| Mercury | Sofisticação cinematográfica para serviços bancários |
Consumo, interação social e confiança
| Produto | Principal contribuição |
|---|---|
| Spotify | Cor, emoção e escala |
| Duolingo | Gamificação como linguagem de design |
| Signal | Segurança por meio da simplicidade |
| Airbnb | Confiança na escala de um marketplace |
| Bluesky | Transparência algorítmica |
| Letterboxd | Cinema como objeto social |
| Strava | Dados de GPS como moeda social |
| Apple Music | Voz editorial, áudio espacial |
| Headspace | Calma como estratégia de interface |
| Zomato | UX gastronômica guiada pela personalidade |
Produtos físicos, jogos e acessibilidade
| Produto | Principal contribuição |
|---|---|
| Balatro | Ciclos de feedback, sistemas de sensação de jogo |
| Rivian | Fotografia de aventura e tipografia monumental |
| Teenage Engineering | Restrições como identidade estética |
| OKO | Acessibilidade por áudio e resposta tátil |
| CARROT Weather | Personalidade como diferencial em aplicativos utilitários |
Este guia evolui com a prática. Os princípios de design são atemporais, mas sua aplicação muda com a tecnologia e o conhecimento.