Commitment Card

Compromisso futuro — boleto, parcela, agendamento. Coração dos UCs de obrigação fixa e proxy.

Abrir no Storybook ↗

Quando usar

  • Quando o produto precisa representar um compromisso financeiro ou temporal — conta a pagar, parcela de cartão, boleto com vencimento, agendamento de transferência.
  • Obrigação fixa recorrente (ex.: condomínio mensal, fatura de serviço, parcela de financiamento) — UC-01: compromisso fixo.
  • Obrigação proxy — compromisso que o usuário gerencia em nome de terceiro (ex.: condomínio da mãe, conta compartilhada com parceiro) — UC-07: proxy de obrigação. Nesse caso o slot owner é obrigatório.
  • Aviso de vencimento próximo ou vencido — aplicação derivada de UC-01 (compromisso fixo em janela de atenção). O status (Chip com tone) carrega o sinal; a superfície permanece V-A puro, sem acento V-B.
  • Listagem de compromissos do mês dentro de um Card Grid — cada Commitment Card representa um item distinto.

Quando não usar

  • Para agrupar múltiplos compromissos — usar Card Grid. O Commitment Card representa um comprometimento por vez; a grade gerencia a coleção.
  • Para dívida em risco alto — quando o compromisso ultrapassar 15 dias de vencimento ou acumular juros significativos, a cena escala para o surface template DebtState (v2). O Commitment Card cobre alertas; crise financeira exige superfície dedicada em V-A puro, tom A estrito.
  • Para transações já liquidadas no extrato — lançamentos passados vivem na listagem de transações, não em Commitment Card. O card é prospectivo: aponta pro futuro ou para o presente imediato.
  • Como card-mãe do dashboard — o Commitment Card tem o mesmo peso de card-filho. Não use peppe-card--mother nele; o Balance Card é o card-mãe.

Anatomia

Seis slots, dois obrigatórios (kicker e title). Os slots meta, owner, status e action são opcionais — mas meta e status são altamente recomendados porque, sem data e valor, o card perde o dado que justifica sua presença.

Decisão de markup: composição de classes. O Commitment Card usaclassName="peppe-card peppe-commitment-card" — compõe a classe base do Card com o modificador semântico do Commitment Card. A superfície raised (gradiente, border gradient, sombra, overflow hidden, raio) é herdada do Card primitivo. O Commitment Card adiciona apenas o layout interno, os papéis tipográficos dos slots e a faixa de rodapé com status + action.

Raio padrão: --radius-lg (24px). O Commitment Card tem peso de card-filho — portanto usa um raio um degrau abaixo do --radius-xl do Balance Card, sinalizando hierarquia. Pode receber peppe-card--hero quando for o card de destaque de um alerta de vencimento urgente (superfície isolada, não numa grade).

Variantes

Uma estrutura, diferenciação por combinação. O Commitment Card v1 tem estrutura única — os seis slots, com owner como opcional de presença discreta. A diferenciação visual vem da combinação de status (tone do Chip) e da presença ou ausência de owner. Não há variantes de layout separadas.

COMPROMISSO

Condomínio de maio

vence 10/mai · R$ 380

Variantes por canal. app: card visual com todos os slots (default). voz: locução linear ("Condomínio de maio vence em dez de maio por trezentos e oitenta reais"). whatsapp: kicker em caps + title + meta em 1 linha + status em keyword (VENCE EM 3 DIAS). sms: ultra-compacto — "COND MAIO: R$ 380 | vence 10/mai". Em todos os canais, owner é incluído quando o compromisso é proxy: "cond. mãe" no SMS, "condomínio da sua mãe" na voz.

Estados

pending

COMPROMISSO

Condomínio de maio

vence 10/mai · R$ 380

Estado padrão. Chip tone=info (sem urgência). Action tertiary. Tom A — Registro profissional, sem acento.

due-soon

CONTA

Fatura Nubank

vence 13/mai · R$ 1.240

Vencimento iminente (≤ 5 dias). Chip tone=alert. Action tertiary — sobe pra secondary em urgência máxima (≤ 1 dia). Registro A com ponte curta pra B (voice-and-tone.md §3.1).

overdue

CONTA

Água de abril

vencido 05/mai · R$ 127

Vencido há até 14 dias. Chip tone=error. Se ultrapassar 15 dias ou acumular juros expressivos, escalar para DebtState (v2). V-A puro, sem humor, sem acento.

paid

COMPROMISSO

Condomínio de maio

pago em 05/mai · R$ 380

Liquidado. Chip tone=success. O slot action é removido — a transação fechou, não há ação possível. Tom A seco: "Pago em 05/mai · R$ 380".

scheduled

AGENDADO

Aluguel de maio

agendado pra 10/mai · R$ 1.500

Pagamento já agendado. Chip tone=info. Kicker "AGENDADO" em vez de "COMPROMISSO". Action "Revisar" — só cancela ou altera, não paga.

loading

Skeleton preservando as dimensões dos slots reais. aria-busy="true" no container — leitores de tela não anunciam os placeholders.

erro

Bloco funcional com ícone de erro, texto canônico e ação de retry. role="alert" para anúncio imediato pelo leitor de tela.

com owner (proxy)

COMPROMISSO

Condomínio de maio

vence 10/mai · R$ 380

SUA MÃE

Proxy UC-07: condomínio gerenciado em nome de terceiro. Slot owner aparece entre meta e footer — caps xs tertiary, discreto. Não aparece em compromissos do próprio usuário.

Tokens

O Commitment Card herda os tokens de superfície do Card (raised) e define papéis tipográficos para cada slot. A tabela abaixo registra também o desvio de spec documentado.

TokenValorPapel
Herdados do Card
--color-surface-raised-top/bottom#F7F7F7 → #FBFBFBGradiente de fundo raised
--border-raised-top/bottom#FCFCFC → #F8F8F8Border gradient direcional
--shadow-raisedSombra direcional canto sup-esq
--radius-lg24pxRaio card-filho (padrão do Commitment Card)
--space-2424pxPadding interno
Slots do Commitment Card
--type-family-sansInstrument Sanstodos os slots — kicker, title, meta, owner
--type-size-lg20pxtitle — sans mediumdesvio de spec documentado abaixo
--type-size-xs12pxkicker, owner — caps medium tracking-loose
--type-size-sm14pxmeta — regular
--type-weight-medium500title, kicker, owner
--type-weight-regular400meta
--type-tracking-loose0.08emkicker, owner (uppercase)
--type-tracking-normal0title, meta
--color-ink-primary#171717title
--color-ink-secondary#6B6B6Bmeta
--color-ink-tertiary#A1A1A1kicker, owner
--space-44pxgap óptico kicker → title
--space-88pxgap title → meta, gap meta → owner
--space-1616pxgap owner → divider, gap divider → footer
Status (Chip herdado) e Action
--color-functional-info / -tint#3875B0 / #E2EAF2status: pending, scheduled
--color-functional-alert / -tint#D4A017 / #F6EEDAstatus: due-soon
--color-functional-error / -tint#C43D3D / #F3E2E1status: overdue
--color-functional-success / -tint#37A35A / #E8F2ECstatus: paid

Flag para o product-designer — desvio de spec §6.3.10

A spec prompt-v1.md §6.3.10 indicou --type-family-serif no slot title. Esse uso está em conflito direto com visual-language.md §4.4 (limiar de uso da serif: tamanhos ≥ 32px). O title do Commitment Card é --type-size-lg (20px), bem abaixo do limiar. Abaixo de 32px, a Fraunces tem métrica apertada que prejudica leitura e perde a função de voz/personagem que justifica o pareamento. Decisão aplicada: title em --type-family-sans medium, 20px — papel de "destaque de UI" (visual-language.md §4.4). A hierarquia do card (kicker caps → title sans medium → meta sans regular) permanece legível e consistente com a escala. Próximo passo: product-designer avalia se o limiar de uso da serif deve ser revisado, ou se a spec §6.3.10 é atualizada para refletir sans no title.

Conteúdo

kicker é a etiqueta de tipo: "COMPROMISSO", "CONTA", "AGENDADO". Caps, máximo 1–2 palavras. Zero pontuação final. Nunca descreve o conteúdo específico ("CONDOMÍNIO RESIDENCIAL MAIO") — o kicker posiciona a categoria, não nomeia o item.

title é a descrição concreta do compromisso: "Condomínio de maio", "Fatura Nubank", "Água de abril", "Aluguel de maio". Específica, não genérica — "Pagamento" sozinho não serve; "Parcela 3/6 — Samsung" serve. Máximo 1 linha; sem pontuação final. Referência: content-design/examples.md §9"Luz vence em 5 dias, R$ 380." — a clareza de dado específico é a régua.

meta combina data e valor em 1 linha com interponto: "vence 10/mai · R$ 380", "vencido 05/mai · R$ 127", "pago em 05/mai · R$ 380", "agendado pra 10/mai · R$ 1.500". Data em formato curto PT-BR. Valor em BRL locale PT-BR. Ponto como separador de milhar; vírgula como decimal — "R$ 1.240" (sem decimais quando arredondado) ou "R$ 1.240,50" (quando precisão é relevante).

owner só aparece quando o compromisso não é exclusivo do usuário. Formatos aceitos: "SUA MÃE" (proxy UC-07), "COMPARTILHADO COM JOÃO" (obrigação compartilhada), "PROXY" (rótulo genérico quando o terceiro não tem nome). Caps, discreta, abaixo da meta. Nunca inclua owner em compromissos próprios — vira ruído onde não há informação nova.

status é o Chip com tone coerente com o estado real. O tone não é decorativo — é sinal funcional. Exemplos de texto: "Pendente", "Vence em 3 dias", "Vencido há 2 dias", "Pago em 05/mai", "Agendado pra 10/mai". Tom A puro — sem ponto de exclamação, sem emoji, sem adjetivo emocional.

action usa verbo direto: "Pagar agora", "Pagar", "Revisar", "Confirmar". Sem "Clique aqui", sem "Ver detalhes" genérico. Em estado paid, o action some — a transação fechou.

Fallback SMS: colapsa em 1 linha — "COND MAIO: R$ 380 | vence 10/mai". Action some; status vira keyword inline. Máximo 160 caracteres.

Acessibilidade

  • aria-label composto no container. O <article> recebe aria-label que sumariza todos os slots presentes: "COMPROMISSO: Condomínio de maio. vence 10/mai · R$ 380. Gerenciado para: sua mãe. Status: pendente." — o leitor de tela lê o bloco inteiro sem precisar navegar pelos filhos individualmente.
  • Card inteiro focável quando action é o comportamento principal. Quando o Commitment Card é o único elemento interativo da cena (ex.: alerta hero isolado), o <article> pode receber tabIndex=0 e o foco ativa a action principal. Em Card Grid com múltiplos cards, o foco navega pelo botão interno.
  • Tones de Chip passam AA sobre raised. Pares de cor das funcionais sobre o fundo tint garantem contraste mínimo 4.5:1 em tamanho xs (12px). Pares canônicos (ver tokens.css §Color/Functional): success #37A35A / #E8F2EC, alert #D4A017 / #F6EEDA, error #C43D3D / #F3E2E1, info #3875B0 / #E2EAF2.
  • Estado loading: aria-busy="true" no container. Os blocos skeleton não têm texto — leitores de tela não anunciam placeholders. Dimensões preservadas para evitar layout shift.
  • Estado erro: role="alert" no .peppe-card__error-block para anúncio imediato pelo leitor de tela.
  • Chip de status: aria-label explícito quando o texto é abreviado (ex.: "Vence em 3 dias" é autoexplicativo; "ALERT" não é — nesse caso, aria-label="Vence em 3 dias").
  • Fallback SMS: colapsa action em keyword. O canal SMS não entrega interatividade — a ação é implicada pelo texto.
  • Owner em proxy: o aria-label do container inclui "Gerenciado para: [nome]" para que o leitor de tela comunique o contexto de proxy sem depender de cor ou posição visual.

Do / Don't

Do

COMPROMISSO

Condomínio de maio

vence 10/mai · R$ 380

Title descritivo e concreto — "Condomínio de maio" identifica o item sem precisar abrir o detalhe. O usuário sabe o que está pagando antes de qualquer interação.

Don't

COMPROMISSO

Pagamento

vence 10/mai · R$ 380

Title genérico — "Pagamento" não identifica o item. O usuário precisa abrir o detalhe pra saber o que está pagando. Filler no slot mais importante do card.

Do

COMPROMISSO

Condomínio de maio

vence 10/mai · R$ 380

SUA MÃE

Owner presente apenas quando é proxy ou compartilhado — "SUA MÃE" informa contexto que o usuário não deduziria só do title. A informação nova justifica o slot.

Don't

CONTA

Fatura Nubank

vence 13/mai · R$ 1.240

VOCÊ

Owner em compromisso próprio — "VOCÊ" não acrescenta informação. Ruído no card. O owner só entra quando o compromisso é de ou com outra pessoa.

Do

15+ dias vencido ou juros acumulados

DebtState (v2)

V-A puro · tom A estrito · sem action leve

Dívida em risco alto escala para o surface template DebtState — superfície dedicada, V-A puro, tom A estrito. O Commitment Card cobre alertas; crise exige outra cena.

Don't

CONTA

Cartão Itaú

vencido 10/mar · R$ 3.400

Commitment Card com dívida de 43 dias e R$ 3.400 — a superfície não foi projetada para esse grau de gravidade. O componente minimiza o que é urgente. Escalar para DebtState.

Componentes relacionados

  • Card — scaffold do Commitment Card. O Commitment Card é instância nomeada de Card; herda superfície raised, sombra, border gradient e raio.
  • Chip — usado no slot status com tone variável conforme o estado: info (pending, scheduled), alert (due-soon), error (overdue), success (paid).
  • Button — usado no slot action. Emphasis tertiary no default; pode subir para secondary em urgência máxima (≤ 1 dia pro vencimento). Some em estado paid.
  • Card Grid — container para múltiplos Commitment Cards. O Card Grid gerencia a coleção; o Commitment Card representa um item por vez.
  • Balance Card — composition irmã. O saldo projetado (Balance Card) contextualiza o conjunto de compromissos (Commitment Cards). No dashboard, Balance Card vem primeiro; Commitment Cards vêm na sequência.

Markup de referência

HTML namespaced copiável. Slots opcionais (owner, status, action) podem ser omitidos sem quebrar o componente — apenas kicker e title são obrigatórios.

Decisão de arquitetura: o Commitment Card usa composição de classes — peppe-card peppe-commitment-card. A classe peppe-card entrega a superfície raised; a classe peppe-commitment-card entrega o layout interno e os papéis tipográficos. O slot footer é a faixa inferior que agrupa status + action em linha.

<!-- Commitment Card — variante completa com owner (proxy UC-07) --> <article className="peppe-card peppe-commitment-card" aria-label="COMPROMISSO: Condomínio de maio. vence 10/mai · R$ 380. Gerenciado para: sua mãe. Status: pendente."> <!-- kicker: obrigatório — COMPROMISSO, CONTA ou AGENDADO --> <span className="peppe-commitment-card__kicker">COMPROMISSO</span> <!-- title: obrigatório — descrição concreta, não categoria genérica --> <p className="peppe-commitment-card__title">Condomínio de maio</p> <!-- meta: opcional mas recomendado — data + valor em 1 linha --> <p className="peppe-commitment-card__meta">vence 10/mai · R$ 380</p> <!-- owner: opcional — só quando é proxy ou compartilhado --> <p className="peppe-commitment-card__owner">SUA MÃE</p> <!-- footer: agrupa status (Chip) + action (Button) --> <div className="peppe-commitment-card__footer"> <div className="peppe-commitment-card__status"> <span className="peppe-chip peppe-chip--info" aria-label="Pendente">Pendente</span> </div> <div className="peppe-commitment-card__action"> <button className="peppe-button peppe-button--tertiary" type="button"> <span className="peppe-button__label">Pagar</span> </button> </div> </div> </article> <!-- Commitment Card — due-soon (Chip alert) --> <article className="peppe-card peppe-commitment-card" aria-label="CONTA: Fatura Nubank. vence 13/mai · R$ 1.240. Status: Vence em 3 dias."> <span className="peppe-commitment-card__kicker">CONTA</span> <p className="peppe-commitment-card__title">Fatura Nubank</p> <p className="peppe-commitment-card__meta">vence 13/mai · R$ 1.240</p> <div className="peppe-commitment-card__footer"> <div className="peppe-commitment-card__status"> <span className="peppe-chip peppe-chip--alert" aria-label="Vence em 3 dias">Vence em 3 dias</span> </div> <div className="peppe-commitment-card__action"> <button className="peppe-button peppe-button--tertiary" type="button"> <span className="peppe-button__label">Pagar agora</span> </button> </div> </div> </article> <!-- Commitment Card — paid (action some) --> <article className="peppe-card peppe-commitment-card peppe-commitment-card--paid" aria-label="COMPROMISSO: Condomínio de maio. pago em 05/mai · R$ 380. Status: pago."> <span className="peppe-commitment-card__kicker">COMPROMISSO</span> <p className="peppe-commitment-card__title">Condomínio de maio</p> <p className="peppe-commitment-card__meta">pago em 05/mai · R$ 380</p> <div className="peppe-commitment-card__footer"> <div className="peppe-commitment-card__status"> <span className="peppe-chip peppe-chip--success" aria-label="Pago em 05/mai">Pago em 05/mai</span> </div> <!-- action omitida em paid --> </div> </article> <!-- Commitment Card — loading (skeleton) --> <article className="peppe-card peppe-commitment-card peppe-commitment-card--loading" aria-busy="true" aria-label="Carregando compromisso"> <div className="peppe-card__skeleton-line peppe-card__skeleton-line--xs peppe-commitment-card__skeleton-kicker"></div> <div className="peppe-card__skeleton-line peppe-commitment-card__skeleton-title"></div> <div className="peppe-card__skeleton-line peppe-card__skeleton-line--sm peppe-commitment-card__skeleton-meta"></div> <div className="peppe-commitment-card__skeleton-footer"> <div className="peppe-commitment-card__skeleton-chip"></div> <div className="peppe-commitment-card__skeleton-action"></div> </div> </article>