teqo-backup/docs/plans/busca-global-layout-resultados.md
Francisco Solla 142b0963e0 B54 — Busca global: layout responsivo dos resultados (#60)
* feat(campanha): responsive grid and viewport cap for home search results (B54)

Adds HomeSearchResultsLayout with 1/2/3-column breakpoints and allocateHitBudget so Municípios keep priority while total hits stay within per-viewport limits.

Closes #8

* fix(campanha): un-export knip-unused home search budget helpers
2026-07-30 18:45:44 -03:00

3.6 KiB
Raw Permalink Blame History

Busca global — layout dos resultados (grid + cap de viewport)

Status: entregue (2026-07-30) Atualizado em: 2026-07-30 — as-built: HomeSearchResultsLayout (grid 1/2/3 col + HomeSearchHitBudgetContext); cap v1 constante por breakpoint (HOME_SEARCH_HIT_BUDGET 8/12/15) via allocateHitBudget com prioridade Municípios; grupos B48–B53 fatiam via useHomeSearchHitLimit. Item do roadmap: docs/roadmap.md (Trilha B, item B54 — busca global) Impeccable: B — layout responsivo da região de resultados B47 Appetite: ~0,5–0,75 dia eng; CSS grid + política de cap; sem provider novo Responsável: —

Design (Impeccable)

Âncoras: PRODUCT.md (Clarity under pressure) / DESIGN.md · chrome B47 · tema campaign.

Na implementação: craft compacto → critique → polish.

Brief compacto:

  • Persona: staff no tablet/notebook com vários grupos; no mobile empilha.
  • Job principal: ver grupos lado a lado sem scroll infinito de hits.
  • Anti-goals: masonry irregular; virtualização prematura; cap por grupo fixo que esconde Municípios (grupo principal).

Dados → decisão → apresentação

Dados: N/A — só layout/quantidade de linhas renderizadas; números vêm dos grupos.

Contexto

Pedido (2026-07-29): mobile = grupos empilhados; tablet = 2 colunas; desktop = 3 colunas; total de resultados limitado ao preenchimento da tela pelo conjunto dos grupos. Conteúdo das linhas = B48–B53; este item só organiza e corta.

Objetivos

  • Container de resultados: flex flex-col (<md) → md:grid md:grid-cols-2 → lg:grid-cols-3 (breakpoints alinhados ao shell da campanha).
  • Cap de viewport: limitar o número total de hits renderizados (soma dos grupos) ao que cabe na área útil sob o input — medir via ResizeObserver / estimativa de row height, ou política simples documentada (ex. max 12–18 hits totais redistribuídos com prioridade ao grupo Municípios).
  • Grupo Municípios (B48) tem prioridade de slots no cap; demais grupos compartilham o resto.
  • Grupos vazios continuam não montados (regra dos providers).
  • Sem migration.

Decisões travadas

  • Grid por viewport, não por pointer. Rejeitado: 1 coluna em touch tablet paisagem.
  • Cap no conjunto, não scroll infinito. Rejeitado: “mostrar todos” com página interna.
  • Prioridade de slots: Municípios primeiro. Rejeitado: round-robin que deixa Cairu fora e enche de demandas.
  • i18n: HomeSearchResultsLayout.

Questões em aberto

  • Cap: medir DOM vs constante? Opções: A ResizeObserver + row estimate | B constante por breakpoint (ex. 8/12/15). Recomendação: B no v1 (barato, testável); A se critique achar corte cego. (assumido)

Abordagem proposta

flowchart TB
  Slot["B47 results region"] --> Layout["HomeSearchResultsLayout"]
  Layout --> G1["Municípios"]
  Layout --> G2["outros grupos"]
  • Componente de layout envolvendo os grupos já registrados; API allocateHitBudget(groups, budget).
  • Migration: nenhuma.

Dependências

  • Dura: B47. Soft: B48 (precisa ≥1 grupo para validar cap); melhor após 2+ grupos.

Não escopo

Conteúdo das linhas → B48–B53. Ações → B55.

Rabbit holes

Virtualização (react-virtual). Mitigação: cap pequeno; virtualizar só se budget > 50.

Adiado com gatilho

  • “Ver todos em /municipios?q=” por grupo. Revisitar se cap gerar reclamação na sessão.

Referências