8.3 KiB
Bottom drawer — handle, gesto, scroll, peek discreto, labels 2 linhas
Status: implementado (PR)
Atualizado em: 2026-08-01
Issue: #132
Priority: P1
Model: cursor-grok-4.5-medium
Impeccable: C — chrome CampaignQuickActionsDrawer (comportamento + geometria)
Appetite: ~1–1,5d eng; snap/gesto/scroll + peek busca + altura labels; sem migration
Responsável: —
Design (Impeccable)
Âncoras: PRODUCT.md (thumb zone; Feel the action) / DESIGN.md · B79/B91/B100 · Base UI Drawer snap · tema campaign.
Na implementação (work-issue): craft compacto → critique → polish (viewport ~390; detalhe município; scroll real).
Brief compacto:
- Persona / contexto: CG/assessor no celular fora do Início; uma mão; alterna ler a página e disparar ação/busca.
- Job principal: (1) handle no topo do sheet; (2) puxar para baixo fecha/recolhe; (3) scroll página ↓ fecha, ↑ abre; (4) collapsed ainda mostra busca sem placeholder; (5) títulos das ações com 2 linhas visíveis.
- Estratégia de cor: Restrained.
- Edit where you see: não — launchers.
- Anti-goals: scrim modal; FAB; bottom nav; redesenhar catálogos B80–B90; absorver crash da busca (→ B102 primeiro ou em paralelo sem bloquear geometria).
Wireframe (texto)
Dock (aberto):
┌─ página ───────────────────────────────────────┐
│ conteúdo │
├─ drawer ───────────────────────────────────────┤
│ ═ handle (TOPO) │
│ [○][○][○]… labels em 2 linhas visíveis │
│ ┌ Buscar na campanha (placeholder ok) ───────┐ │
│ └────────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
Collapsed (fechado / após scroll ↓):
┌─ página (mais conteúdo) ───────────────────────┐
│ … │
├────────────────────────────────────────────────┤
│ ═ handle │
│ ┌ (input sem placeholder — discreto) ────────┐ │
│ └────────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
Gesto: drag handle/sheet ↓ → collapsed; scroll content ↓ → collapsed; scroll content ↑ → dock.
Dados → decisão → apresentação
Dados: N/A — chrome; hits = B48+ via provider existente.
Contexto
B100 ✓ (#114) definiu dock no load + collapse no scroll para baixo + reopen só tap/pull (explicitamente sem reopen no scroll-up). Follow-up a056616d reordenou o DOM para o handle ficar em baixo (“snap shows bottom band”) — produto agora rejeita: handle deve voltar ao topo; puxar ↓ deve recolher; scroll ↑ deve abrir. Collapsed deve manter a barra de busca visível sem placeholder. Labels line-clamp-2 existem no botão, mas dock 12rem + overflow-hidden + handle embaixo cortam a 2ª linha.
Objetivos
- Handle no topo do
DrawerContent(reverter ordem doa056616d); banda visível do snap mostra handle → ações → busca. - Swipe/drag para baixo no drawer recolhe para collapsed (Base UI
swipeDirection="down"+ snap; validar que não fica “só tap”). - Scroll do
campaign-content-scroll: ↓ além do limiar → collapsed; ↑ (delta ouscrollTopcaindo / direção) → dock. Não reabrir se buscauiFocused(assumido). - Collapsed: renderiza input de busca visível,
placeholder=""(ou omitido); sem strip de ações (ou strip hidden). Tap no input / focus → dock + focus. - Altura do dock / overflow: 2ª linha dos labels visível (subir
QUICK_ACTIONS_SNAP_DOCKe/ouoverflow-y-autona região de ações; tirar clip que comeline-clamp-2). - Load / navegação: estado inicial = dock (B100).
- Pins: unit direção scroll; e2e mobile handle no topo + collapse swipe se estável.
- Sem migration / Consent.
- Tracer: load dock → scroll ↓ collapsed (busca sem placeholder) → scroll ↑ dock → labels 2 linhas no viewport.
Decisões travadas
- Supersede B100 no reopen por scroll-up e no collapsed “só handle”. Fonte: produto 2026-08-01. Rejeitado: manter “reopen só tap” (B100); collapsed só handle sem busca.
- Handle no topo — reverter o DOM order do
a056616d. Se a geometria do snap exigirpadding-bottomBase UI, aplicar sem mover o handle para baixo. Rejeitado: handle embaixo como “fix” de banda visível. - Collapsed = handle + busca discreta (sem placeholder); ações hidden. Rejeitado: collapsed = só handle (B100); esconder busca no collapsed.
- Scroll-up reabre com limiar de direção (delta ↑ ≥ N px) ou
scrollTopcaindo abaixo do limiar — craft escolhe o mais estável; pin no unit. Rejeitado: hysteresis multi-eixo complexa neste item. - i18n: ids
dock/collapsed; aria pt-BR; placeholder vazio no collapsed (label sr-only permanece).
Questões em aberto
- Limiar scroll-up para abrir? Opções: A) espelhar 24 px de delta ↑ | B)
scrollTop < 24(só perto do topo). Recomendação: A (simétrico ao collapse). ✅ travado em craft (quickActionsScrollDirection). - Focus no input collapsed: expande para dock automaticamente? Opções: A) sim | B) só digitar. Recomendação: A. ✅ travado em craft (
uiFocused→ dock).
Abordagem proposta
flowchart TB
Scroll["campaign-content-scroll"] -->|delta down| Collapsed
Scroll -->|delta up| Dock
Handle["handle TOP"] -->|swipe down| Collapsed
Collapsed --> SearchPeek["search no placeholder"]
Dock --> Strip["actions 2-line labels"]
Dock --> SearchFull["search + placeholder"]
Componentes:
CampaignQuickActionsDrawer.tsx: ordem handle → context; collapsed mostraCampaignHomeSearch(ou slot) sem placeholder; dock mostra strip + search completa; overflow/altura.CampaignQuickActionsHost.tsx/ snap context: listener de scroll com direção (↑/↓); respeitaruiFocused.campaignQuickActionSnap.ts: recalibrarQUICK_ACTIONS_SNAP_COLLAPSED/DOCKpara caber handle+busca (collapsed) e strip 2 linhas+busca (dock).CampaignHomeSearch/CampaignSearchInput: prop opcionalplaceholder/discreetpara collapsed.- E2e / unit atualizar expectativas B100 (scroll-up agora reabre; collapsed tem busca).
- Migration: Sem migration.
Dependências
- Soft: B100 ✓, B91 ✓. Soft: B101 (bleed/gap da strip — pode pousar junto). Soft: B102 (crash) — se o crash bloquear teste manual da busca no drawer, priorizar B102.
- Nenhuma dura de Issue aberta.
Não escopo
- Crash focus/type → B102.
- Gap/padding dos botões → B101.
- Título “Sugestões” → B103.
- Catálogos de ações por rota.
Rabbit holes
- Terceiro snap “expanded” para resultados. Mitigação: Adiado; resultados rolam no dock ou a página.
position: fixedcaseiro no lugar do Base UI. Mitigação: só se swipe+snap forem irrecuperáveis após handle no topo + padding-bottom correto.- Persistir snap em sessionStorage. Mitigação: fora; reset no pathname (B100).
Adiado com gatilho
- Animação spring custom além do Base UI. Revisitar se critique pedir motion.
- Peek de 1 ícone de ação no collapsed. Revisitar se a mesa achar busca-só pobre.
Referências
- GitHub Issue #132 (B105)
CampaignQuickActionsDrawer.tsx·CampaignQuickActionsHost.tsx·campaignQuickActionSnap.ts·Drawer.tsx·docs/plans/bottom-drawer-peek-acoes-busca.md(B100 — supersedido em parte)- Commit
a056616d(handle bottom — reverter ordem) PRODUCT.md/DESIGN.md— Field Desk chrome