Icon

Glifo geométrico puro. Stroke único de 1.5 px. Três tamanhos.

Abrir no Storybook ↗

Quando usar

Dentro de Button, Chip, Card, Search Field, listagem. Como marcador visual de ação, categoria ou estado — quando adiciona clareza ao texto sem redundância.

Quando não usar

  • Para ilustração — ícone não é mini-cena. Detalhe ilustrativo vira anti-padrão #4.
  • Para decoração pura em texto corrido — se não adiciona informação, corta.

Anatomia

Um ícone é um SVG com uma só geometria e um stroke de espessura fixa. Não há mais camadas.

  • path — forma geométrica única com stroke 1.5 px. Sem detalhes decorativos internos.
  • grid — 16/24/32 px, cabe no sistema de 8 px em qualquer escala.
  • fill — transparente por default; sólido só em estado ativo específico (ex.: bookmark salvo).

Variantes

Não há variantes estéticas. O ícone muda por nome (significado semântico) e por tamanho (sm/md/lg). A cor é herdada do contexto via currentColor.

sm — 16 px

md — 24 px

lg — 32 px

Estados

default. Em estado ativo de um contêiner (ex.: bookmark salvo, item de nav selecionado), o ícone pode trocar de stroke para filled — mantendo o stroke único, com fill="currentColor" e sem stroke. A classe .peppe-icon--active sinaliza o estado ao container; a troca stroke→filled acontece no SVG.

Tokens aplicáveis

TokenPapel
--icon-strokeEspessura única de stroke (1.5 px). Aplicada no SVG, não via CSS.
--icon-size-smTamanho sm (16 px)
--icon-size-mdTamanho md (24 px) — default de UI
--icon-size-lgTamanho lg (32 px)
--color-ink-secondaryCor default do ícone contextual (herdada via currentColor)
--color-ink-primaryCor em estado ativo (.peppe-icon--active)
--color-functional-{tone}Cor funcional quando dentro de Chip ou estado de sistema

Conteúdo

Cada ícone tem nome semântico único, em inglês, kebab-case. O catálogo inicial cobre 12 glifos funcionais. Vocabulário completo será formalizado em .claude/product-design/icons.md conforme crescer.

  • search
  • arrow-right
  • check
  • calendar
  • alert
  • plus
  • close
  • chevron-down
  • edit
  • trash
  • user
  • bell

Acessibilidade

  • role="img" + aria-label quando o ícone tem significado próprio (standalone, sem texto redundante ao lado).
  • aria-hidden="true" quando é decorativo ao lado de texto redundante — ex.: Button com label + ícone (o label já descreve a ação).
  • Fallback de canal: voz omite; WhatsApp substitui por emoji semântico (check → ✅, alert → ⚠); SMS por ASCII quando possível.

Do / Don't

Fazer

Stroke fixo 1.5 px em todos os ícones. Consistência na mesma tela.

Não fazer

Ícones com strokes diferentes na mesma tela (2.5 px e 1 px lado a lado).

Boleto pago

Fazer

Ícone como marcador — adiciona clareza ao texto.

Saldo do mês

Não fazer

Decoração pura — ícones sem função semântica ao redor de texto.

Componentes relacionados

Todos os componentes que aceitam slot de ícone:

  • ButtoniconLeading / iconTrailing opcionais.
  • Chip — ícone à esquerda do label, tamanho sm.
  • Search FieldiconLeading search + iconTrailing close quando filled.
  • Card — ícone como marcador de categoria ou ação no body/footer.

Markup de referência

HTML copiável — semente da story de componente. CSS aplicável: componente-icon.css.

<!-- Ícone standalone com significado próprio --> <span className="peppe-icon peppe-icon--md" role="img" aria-label="buscar lançamento"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"> <circle cx="11" cy="11" r="7"/> <line x1="16.5" y1="16.5" x2="21" y2="21"/> </svg> </span> <!-- Ícone decorativo ao lado de texto (aria-hidden) --> <button className="peppe-button peppe-button--secondary"> <span className="peppe-icon peppe-icon--sm" aria-hidden="true"> <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"> <polyline points="3,8 6,12 13,4"/> </svg> </span> <span className="peppe-button__label">Confirmar</span> </button> <!-- Tamanhos: peppe-icon--sm | --md | --lg --> <!-- Cores: herda currentColor do contexto. Funcionais via: .peppe-icon--success / --alert / --error / --info --> /* ── CSS relevante (componente-icon.css) ─────────────── */ .peppe-icon {display: inline-flex; align-items: center; justify-content: center; color: var(--color-ink-secondary); flex-shrink: 0;}.peppe-icon--sm { width: var(--icon-size-sm); height: var(--icon-size-sm); }.peppe-icon--md { width: var(--icon-size-md); height: var(--icon-size-md); }.peppe-icon--lg { width: var(--icon-size-lg); height: var(--icon-size-lg); }.peppe-icon--active  { color: var(--color-ink-primary); }.peppe-icon--success { color: var(--color-functional-success); }.peppe-icon--alert   { color: var(--color-functional-alert); }.peppe-icon--error   { color: var(--color-functional-error); }.peppe-icon--info    { color: var(--color-functional-info); }