Ir ao conteúdo
SEED engenhariaDesign System

Componentes

62. Seletor de pessoa

estávelseed-componentes.md v1.43 · §62seção 68 de 9862-seletor-de-pessoa-estavel-f7-5-promovida-em.md · MD5 25ea53b3

Título completo no canon: Seletor de pessoa — estável (F7.5 · promovida em 2026-08-17 por gate declarado, verbatim "aprovo. siga" · GATE OBSERVADO em 2026-08-17: a PS-P4 FECHA — insumo nomeado, ver §64.10.1) · PS1–PS16 · fecha C4 · C5 e C8 com bloqueio nomeado (PS-P2, que segue ABERTA) · bancada banco-pessoa.html v0.1 (errata corrigida: este cabeçalho declarava v0.2, versão que nem o artefato, nem o gerador, nem o MANIFESTO, nem o mapa de cobertura têm — §64.10.3) · suite-pessoa.mjs 44 · 0 · 1 [n/a] · BT7 consertado em 2026-08-17

Rodada zero: NÃO VISITADO. O §13 tinha lido o avatar renderizado (C85) e o cartão de pessoa (C115), mas nenhum seletor tinha sido aberto. Navegação autorizada, modo somente leitura: menus abertos, lidos e fechados; nenhuma atribuição feita. Seis dispositivos, C125–C130, no §16 do estudo-clickup-completo.md. LGPD: a lista traz nomes reais de colaboradores; nenhum foi transcrito.

E o achado principal é o mesmo da volta anterior, noutro componente. Na árvore de acessibilidade, cada pessoa da lista é genericsem role="listbox", sem role="option", sem aria-selected em quem já está escolhido —, e o campo de busca é um textbox simples, sem role="combobox", sem aria-expanded, sem aria-controls. Na tela a lista é exemplar: agrupada, com avatares, com o escolhido destacado. Na árvore é um bloco de nomes soltos.

Dois de dois seletores auditados repetem o padrão (C122 no calendário, C130 aqui). A regra da quinta volta — onde o dispositivo é de ESCOLHA, leia a ÁRVORE junto com a TELA — deixou de ser precaução e virou expectativa.

Base (3 rodadas, 2026-08-16). R1 · ARIA APG (combobox): o campo é role="combobox" com aria-controls apontando o popup e aria-expanded; o foco do DOM permanece no campo e o foco da tecnologia assistiva anda por aria-activedescendant; a opção escolhida leva aria-selected="true"; teclado ↓/↑ para andar, Esc para fechar sem alterar, Enter para aceitar. Para grupos, o APG traz o exemplo de listbox com opções agrupadasrole="group" com nome próprio. R2 · mercado: o produto de referência agrupa em "Responsáveis" e "Pessoas", põe "Eu" no topo, e usa o mesmo campo para buscar e convidar. R3 · normas: SC 4.1.2 (nome, papel e valor) é o que o C130 viola; SC 2.4.3 (ordem de foco) é o que o aria-activedescendant preserva.

62.1 A régua: quem escolhe pessoa está escolhendo RESPONSABILIDADE#

Um seletor de pessoa num ERP de engenharia não é um select bonito: atribuir é transferir responsabilidade técnica. Isso muda três coisas em relação a um seletor genérico — quem pode aparecer na lista, o que acontece quando a pessoa sai da empresa, e o fato de que a escolha precisa ser desfazível e visível a quem audita.

62.2 Os contratos#

# Contrato O que ele descarta, e por quê
PS1 O campo é role="combobox" com aria-expanded e aria-controls apontando a lista textbox solto ao lado de uma lista sem vínculo. É o C130 medido: sem o vínculo, quem não vê não sabe que existe lista
PS2 A lista é listbox; cada item é option com aria-selected Itens generic. Sem papel, o leitor de tela anuncia nomes soltos em vez de "lista de 8, 1 selecionada"
PS3 O foco do DOM fica no campo; a AT anda por aria-activedescendant Mover o foco real para dentro da lista. Isso quebra a digitação contínua, que é o modo natural de filtrar
PS4 Grupos são role="group" com nome próprio ("Já atribuídos", "Equipe") Cabeçalho só visual. O agrupamento é informação; sem papel ele é decoração
PS5 Multi-select produz CHIPS removíveis — herda SG9–SG13 do §60, inclusive o teto e o "+N" Reinventar. A família de chips já é canon
PS6 Teclado: ↓/↑ anda · Enter escolhe · Esc fecha SEM alterar · Backspace no campo vazio remove o último chip Fechar aplicando. Esc que confirma é a armadilha clássica de picker
PS7 O avatar é aria-hidden; quem informa é o NOME Concatenar. Herda o SG8 e o defeito real do ✋ Mover
PS8 Avatar sem foto cai para INICIAIS sobre fundo derivado do nome — determinístico, nunca aleatório Cor sorteada. A mesma pessoa mudaria de cor entre telas
PS9 O indicador de presença, quando existe, tem rótulo textual Bolinha muda. Cor sozinha não diz "disponível"
PS10 "Eu" aparece primeiro, e é rotulado como tal Só o nome próprio. C127: o atalho para si mesmo é o caso mais frequente
PS11 Buscar e CONVIDAR são ações distintas, ainda que no mesmo campo: convidar exige confirmação explícita Convidar por Enter. C126 mostra os dois no mesmo campo; num ERP, convidar cria acesso — não pode ser efeito colateral de digitar
PS12 Pessoa INATIVA continua exibível onde já foi atribuída, marcada como inativa; e não é oferecida para novas atribuições Sumir com quem saiu. O histórico de quem assinou o quê é registro técnico — herda o VD16: ausência e vazio não são a mesma coisa
PS13 A lista carrega em página, com estado de carregando declarado; nunca corta em silêncio Cortar em N sem dizer. Herda a regra do teto declarado (SG11)
PS14 Vazio de busca diz o que fazer ("Ninguém com esse nome. Digite um e-mail para convidar.") "Nenhum resultado"
PS15 Remover uma pessoa anuncia quem saiu e quantos restam Remoção silenciosa. Herda o SG12
PS16 Alvo de 44px por linha da lista, e a linha inteira é clicável Alvo só no nome

62.3 A fronteira, e os dois bloqueios nomeados#

  • C5 · seletor de entidade colorida (espaço/lista com glifo) — o seletor vive atrás da ação mover, que é escrita. A entidade renderizada foi vista; o seletor não. Bloqueio nomeado: só se alcança escrevendo.
  • C8 · campo de menção @ — abrir a lista de menção exige digitar no compositor de comentário, e o produto persiste rascunho. Mesmo bloqueio.

Achado negativo é achado. Os dois não são "não deu tempo": são inalcançáveis no modo autorizado, e ficam assim registrados. Quando a spec deles for escrita, ou o modo muda, ou a base é canon + norma sem leitura — declarado, como o DH12.

Também fora: permissão (quem pode ser atribuído é regra de produto) · notificação ao atribuir · carga de trabalho (A15, bloqueado por ambiente desde a quarta volta).

62.4 Números — a MEDIR na bancada#

Altura da linha · diâmetro do avatar e sua escala de tipo para as iniciais · alvo do X do chip (herda os 44px do SG10) · contraste das iniciais sobre os fundos derivados, em todos os fundos que a derivação puder gerar · altura máxima da lista antes de rolar. Nenhuma medida é afirmada aqui.

62.5 Pendências — a lista de origem (2026-08-16, manhã)#

# Pendência Por que nasceu
PS-P1 Bancada banco-pessoa.html, com gerador, molde e suíte Nível de prova ao escrever a spec: nenhum — não havia consumidor no acervo
PS-P2 C5 e C8 sem leitura Bloqueio nomeado: só se alcançam escrevendo
PS-P3 A derivação de cor das iniciais O contraste tem de passar em todas as cores que a função puder gerar, não numa amostra. É medição de classe, não de caso

O estado ATUAL de cada uma está em §62.7, abaixo — esta tabela fica como registro de origem.

62.6 A bancada banco-pessoa.html — e a decisão que torna a PS-P3 DEMONSTRÁVEL#

A bancada nasceu em 2026-08-16 com 44 PASS · 0 FAIL · 1 [n/a] em suite-pessoa.mjs, cobrindo PS1–PS16 mais sete guardas de operabilidade (PS-OP1…PS-OP7), duas de forced-colors e a guarda transversal GI2/BT3 do §64.

Por que sete guardas de operabilidade, e não só as de estrutura. Em 2026-08-16 a banco-data.html v0.1 passou em 25 PASS · 0 FAIL com o calendário inoperante — nenhuma data clicável. Quem reprovou foi o olho do Rafael, não o placar. Desde então, guarda de componente de escolha clica, digita e tecla antes de aprovar: aqui, ↓ move o cursor, o clique na extremidade da linha escolhe, Esc fecha, Backspace remove, o filtro filtra, o "+N" abre e a carga em página carrega.

A paleta das iniciais é FECHADA — e é isso que fecha a PS-P3#

O PS8 manda que o avatar sem foto caia para iniciais sobre fundo derivado do nome, determinístico. A PS-P3 exigia mais: o contraste tem de passar em todas as cores que a função puder gerar, não numa amostra.

Alternativa descartada — e é a que a maioria dos produtos usa: hash do nome → matiz livre (HSL). Ela gera uma classe infinita de cores. Contraste de classe infinita não se mede: se torce para dar certo, e no dia em que um nome cair num amarelo claro com tinta clara ninguém vai saber por quê.

Decisão (2026-08-16): o hash indexa um conjunto FECHADO de oito pares (fundo, tinta), com os dois lados na mesma família da rampa. Duas consequências que se ganham juntas:

  1. A PS-P3 vira demonstrável por ENUMERAÇÃO — oito pares se medem; classe infinita, não.
  2. O par não se rompe na inversão de tema (contrato BT3 do §64), porque fundo e tinta são do mesmo par fixo. É o caso que o BT4 tolera de propósito — primitiva em superfície de identidade —, com o número impresso no placar em vez de tolerado em silêncio.
Par Fundo Tinta Contraste medido
turquesa claro --seed-turquesa-100 --seed-turquesa-900 11,37
turquesa médio --seed-turquesa-200 --seed-turquesa-900 9,35
amarelo claro --seed-amarelo-100 --seed-amarelo-900 11,54
amarelo médio --seed-amarelo-200 --seed-amarelo-900 9,73
azul claro --seed-azul-100 --seed-azul-900 11,50
azul médio --seed-azul-200 --seed-azul-900 9,38
cinza claro --seed-cinza-100 --seed-cinza-900 11,49
cinza médio --seed-cinza-200 --seed-cinza-900 9,33 (o pior)

Piso do projeto para texto: 4,50. Medido nos dois temas — os valores não mudam, e é essa estabilidade que o BT4 exige que seja impressa.

Detalhe de implementação que é contrato, não gosto: a derivação não pode usar o hash() do Python — ele é randomizado por processo (PYTHONHASHSEED), então a mesma pessoa mudaria de cor entre duas gerações do mesmo arquivo, que é exatamente o defeito que o PS8 proíbe. A derivação usa soma de códigos de ponto: estável, reproduzível em JS, e portanto igual no gerador e em produção.

O estado ABERTO é impresso EM FLUXO — e isso é decisão de bancada#

A primeira versão da página imprimia os quatro seletores abertos com o popup em position:absolute — que é o comportamento real do componente. Resultado observado no render: cada popup cobriu o cartão vizinho e as duas seções seguintes, e a bancada ficou ilegível justamente nos estados que ela existe para mostrar.

Regra que fica: bancada é catálogo de estados lado a lado (CP31); sobreposição é comportamento de tela. Os estados impressos abertos vão em fluxo (.sel--fluxo), e a sobreposição real continua exercida pelo Estado 1, que abre no clique.

Décimo quinto defeito de instrumento — coordenada de elemento recortado#

A guarda PS-OP2 (a linha inteira é clicável) pegava o retângulo da última opção e clicava em right − 6 sem rolar antes. A lista tem max-height:264px; overflow:auto, e a última opção estava em y=865, fora da área visível do popup, que termina em y=782. O clique caiu na página, não no controle, e a guarda reprovou um artefato correto com "o alvo é só o texto".

Regra nova: coordenada de elemento recortado por contêiner rolável não é a coordenada do controle. Rola-se primeiro, mede-se depois — e a guarda agora verifica que o ponto medido cai sobre a opção antes de emitir veredito.

62.7 Pendências — atualizadas em 2026-08-16#

Aviso de supersede (2026-08-17): a linha PS-P4 desta tabela está SUPERSEDIDA pelo §64.10.4 — ela FECHOU com o gate observado da banco-pessoa v0.1. A PS-P2 segue ABERTA e não foi tocada. A tabela abaixo fica como histórico; o estado vigente é o do §64.10.4.

# Pendência Estado
PS-P1 Bancada banco-pessoa.html, com gerador, molde e suíte FECHADA — 44 · 0 · 1. Nível de prova: 2 (bancada). Continua sem consumidor em produção, e isso está dito: quem escreve o teste escreve o caso
PS-P3 A derivação de cor das iniciais FECHADA por DECISÃO + ENUMERAÇÃO — paleta fechada de 8 pares, medida nos dois temas, pior par 9,33 contra piso 4,50
PS-P2 C5 e C8 sem leitura ABERTA — bloqueio nomeado: os dois só se alcançam escrevendo no produto de referência, e o modo autorizado é somente leitura
PS-P4 Gate visual da banco-pessoa.html v0.1 NOVA, e ABERTA — quatro camadas verdes não substituem o olho. Foi o gate que reprovou a banco-data v0.1 com 25 PASS

62.8 PS-P5 — REVOGADA PELA MEDIÇÃO: o .mini-avatar não é avatar de pessoa#

Escrito em 2026-08-19, ao executar a PS-P5. Seção autossuficiente, e ela supersede formalmente a linha PS-P5 do §64.13.4 e do §69.6.

O que a pendência mandava fazer. A PS-P5 nasceu em 2026-08-17, da auditoria transversal do §69, com este enunciado: "o .mini-avatar, círculo de iniciais de PESSOA, pinta-se com a paleta de ENTIDADE, quando o §62 fechou paleta própria de 8 pares". A decisão do Rafael foi migrá-lo para a paleta de PESSOA, "não a de entidade do CP23".

O que a medição encontrou, em 2026-08-19, antes de tocar em qualquer coisa:

tela quantos .mini-avatar o que as iniciais são o que a cor é o que mais tem
tela-lista ZERO no DOM folha de estilo sem consumidor: .pessoa, .mini-avatar e cinco posições de cor, mantidas por cópia entre telas
tela-tabela 6, na coluna Cliente MA = Metalúrgica Andrade · FB = Fazenda Boa Vista · HS = Hospital Santa Rita posição de ENTIDADE (1 a 5) um ponto de presença (disponivel / ocupado / ausente)
tela-referencia 5, na coluna Cliente idem idem idem

Ou seja: ele NÃO é um avatar de pessoa. Ele carrega o CLIENTE, que é uma ENTIDADE, com as iniciais do cliente. A paleta que ele usa — a de entidade — é a paleta certa para o que ele representa. Migrar para a paleta de PESSOA seria pintar uma empresa com a cor de uma pessoa.

A PS-P5, como escrita, está REVOGADA. Não se executa uma decisão cuja premissa a medição derrubou. É o mesmo movimento de 2026-08-18, quando o RITO reprovou o conserto que a própria pendência CD-P9 mandava aplicar. O que a auditoria viu foi o NOME da classe — pessoa, mini-avatar —, e o nome mentia sobre o dado.

O que a medição achou de verdade, e vira pendência nova:

# Pendência que nasce O que está medido
PS-P6 Um CLIENTE está desenhado com a anatomia de uma PESSOA. Círculo de 26px com INICIAIS e ponto de presença, na coluna Cliente de duas telas estáveis. Três problemas, e os três são de PRODUTO: (a) o SI1 do §65 descartou explicitamente "inicial da palavra sobre cor" como identidade de entidade — "duas entidades com a mesma letra e cores próximas ficam idênticas, e a inicial não sobrevive a renome" —, e é exatamente o que está em uso; (b) o ponto de presença é estado de PESSOA: uma empresa não fica "ocupada"; (c) o elemento inteiro é aria-hidden, então a presença é comunicada só por cor e para ninguém — ela não está escrita em lugar nenhum da linha. Vai a gate com recorte, não se conserta por conta própria

O que FOI feito, e é inerte: o tela-lista teve o bloco .pessoa / .mini-avatar removido — eram zero elementos no DOM, zero em class="pessoa" e zero menções em script. Prova de inércia: 0 de 3.294.000 pixels em 4 comparações, duas execuções.

Regra que fica: REGRA DE ESTILO SEM ELEMENTO É DRIFT ESPERANDO DATA. Ela não pinta hoje e pintaria errado amanhã, e foi por cópia entre telas que ela chegou ali. Foi essa mesma folha morta que fez a auditoria contar o .mini-avatar em três telas quando ele existe em duas.

BancadaSEED Design System v2 · banco-pessoa (§62 · seletor de pessoa) — preview v0.1abrir em página própria ↗

Também cita o §62: banco-edicao-linha, banco-identidade, tela-lista.

Esc