mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:35:20 +00:00
Merge pull request #134 from fsolla/cursor/plan-b101-b105-drawer-polish
docs: planos B101–B105 — polish mobile drawer/strip
This commit is contained in:
commit
da7c813a55
5 changed files with 566 additions and 0 deletions
137
docs/plans/bottom-drawer-handle-scroll-peek.md
Normal file
137
docs/plans/bottom-drawer-handle-scroll-peek.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# Bottom drawer — handle, gesto, scroll, peek discreto, labels 2 linhas
|
||||
|
||||
Status: registrado
|
||||
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):**
|
||||
|
||||
```text
|
||||
┌─ página ───────────────────────────────────────┐
|
||||
│ conteúdo │
|
||||
├─ drawer ───────────────────────────────────────┤
|
||||
│ ═ handle (TOPO) │
|
||||
│ [○][○][○]… labels em 2 linhas visíveis │
|
||||
│ ┌ Buscar na campanha (placeholder ok) ───────┐ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Collapsed (fechado / após scroll ↓):**
|
||||
|
||||
```text
|
||||
┌─ 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 do `a056616d`); 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 ou `scrollTop` caindo / direção) → dock. Não reabrir se busca `uiFocused` _(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_DOCK` e/ou `overflow-y-auto` na região de ações; tirar clip que come `line-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 exigir `padding-bottom` Base 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 `scrollTop` caindo 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). _(assumido)_
|
||||
- **Focus no input collapsed:** expande para dock automaticamente? **Opções:** A) sim | B) só digitar. **Recomendação:** **A**. _(assumido)_
|
||||
|
||||
## Abordagem proposta
|
||||
|
||||
```mermaid
|
||||
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 mostra `CampaignHomeSearch` (ou slot) sem placeholder; dock mostra strip + search completa; overflow/altura.
|
||||
- **`CampaignQuickActionsHost.tsx` / snap context:** listener de scroll com direção (↑/↓); respeitar `uiFocused`.
|
||||
- **`campaignQuickActionSnap.ts`:** recalibrar `QUICK_ACTIONS_SNAP_COLLAPSED` / `DOCK` para caber handle+busca (collapsed) e strip 2 linhas+busca (dock).
|
||||
- **`CampaignHomeSearch` / `CampaignSearchInput`:** prop opcional `placeholder` / `discreet` para 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: fixed` caseiro 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
|
||||
117
docs/plans/crash-busca-bottom-drawer.md
Normal file
117
docs/plans/crash-busca-bottom-drawer.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Crash — busca no bottom drawer (focus / digitação)
|
||||
|
||||
Status: registrado
|
||||
Atualizado em: 2026-08-01
|
||||
Issue: #129 (file-miss #133)
|
||||
Priority: P0
|
||||
Model: cursor-grok-4.5-medium
|
||||
Impeccable: B — `CampaignQuickActionsDrawer` + `CampaignGlobalSearchBody`
|
||||
Appetite: ~0,5–1d eng; root-cause + fix + pin focus/type; sem migration
|
||||
Responsável: —
|
||||
|
||||
## Design (Impeccable)
|
||||
|
||||
Âncoras: `PRODUCT.md` (Feel the action) · B91/B100 drawer search · tema `campaign`.
|
||||
|
||||
Na implementação: reproduzir → fix mínimo → pin (unit + e2e mobile se estável). Sem craft visual além do necessário para o ritual de busca voltar.
|
||||
|
||||
Brief:
|
||||
|
||||
- **Persona:** staff no detalhe de município (mobile); toca “Buscar na campanha” no drawer.
|
||||
- **Job principal:** focar e digitar **sem** a página cair; ver suggest/hits.
|
||||
- **Anti-goals:** redesenhar o drawer (→ **B105**); silenciar o throw com try/catch cosmético.
|
||||
|
||||
### Wireframe (texto)
|
||||
|
||||
```text
|
||||
┌─ /campanha/municipios/foo (mobile) ────────────┐
|
||||
│ conteúdo │
|
||||
├─ drawer dock ──────────────────────────────────┤
|
||||
│ ═ handle │
|
||||
│ [ações…] │
|
||||
│ ┌ Buscar na campanha ──── focus/type OK ─────┐ │
|
||||
│ │ Sugestões / hits (sem crash) │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Dados → decisão → apresentação
|
||||
|
||||
Dados: N/A neste item (hits já existem via B48/B68/B91); só estabilidade do chrome.
|
||||
|
||||
## Contexto
|
||||
|
||||
Fora do Início, o drawer (**B79–B91**, **B100 ✓**) embute `CampaignGlobalSearchBody` sob `CampaignGlobalSearchProvider` em `CampaignAppScrollChrome`. Produto (2026-08-01): **ao clicar ou começar a escrever na barra de busca, a página crasha**.
|
||||
|
||||
Diagnóstico preliminar (código em `main`):
|
||||
|
||||
1. Unit do drawer (`campaignQuickActionsDrawer.unit.spec.tsx`) cobre `change` → POST `mode: 'search'`, **não** `focus` → `setInputFocused(true)` → `mode: 'suggest'`.
|
||||
2. `useHomeSearchResultsState` entra em `suggestMode` quando `uiFocused && !query.isActive` e monta os grupos B48 dentro do snap (`overflow-hidden`, dock `12rem`).
|
||||
3. `CampaignContentScrollWithPeek` chama `useHomeSearch()` — correto só dentro do provider; árvore atual amarra provider + peek. Hipótese secundária: interação Base UI Drawer non-modal + focus/teclado / nested `Drawer` dos action buttons.
|
||||
4. Runtime Vercel (server) **não** mostra o digest do crash (erro de client).
|
||||
|
||||
**Miss de agente:** B100 / follow-up `a056616d` shipparam sem pin de focus+type no drawer. Registrar via `pnpm agent:file-miss` (`kind:defect` ou `agent-miss`) **neste delivery**, depois o fix.
|
||||
|
||||
## Objetivos
|
||||
|
||||
- Reproduzir o crash (mobile real ou Playwright viewport mobile em `/campanha/municipios/[slug]`).
|
||||
- Eliminar a causa raiz (não engolir o erro).
|
||||
- Pins: unit **focus** dispara suggest sem throw; unit/e2e **type** mantém search; regressão no caminho provider/`uiFocused`.
|
||||
- Guardrails: sem migration; leader lockdown; Início intacto.
|
||||
- Tracer: focus no input do drawer → região de resultados monta; digitar “ca” → POST search; zero uncaught.
|
||||
|
||||
## Decisões travadas
|
||||
|
||||
- **Issue própria P0 + file-miss, não absorver em B105.** Crash bloqueia o ritual. **Rejeitado:** “conserta no polish do drawer”.
|
||||
- **Fix mínimo no caminho focus→suggest→render; não redesenhar snap.** Geometria/gesto → **B105**. **Rejeitado:** reescrever busca só para o drawer.
|
||||
- **File-miss obrigatório** com causa + PR culpado quando conhecido. **Rejeitado:** só Issue de feature sem harvest.
|
||||
- **i18n:** ids existentes; sem copy nova.
|
||||
|
||||
## Questões em aberto
|
||||
|
||||
- **Causa raiz exata antes do claim?** **Opções:** A) fechar no `work-issue` com repro primeiro | B) bipartir plan/exec. **Recomendação:** **A** — appetite cabe; hypothese já estreita. _(assumido)_
|
||||
|
||||
## Abordagem proposta
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Focus["input onFocus"] --> Ui["uiFocused"]
|
||||
Ui --> Suggest["POST mode:suggest"]
|
||||
Suggest --> Groups["HomeSearch*Group"]
|
||||
Groups -->|crash?| Fix["fix root"]
|
||||
Type["onChange"] --> Search["POST mode:search"]
|
||||
```
|
||||
|
||||
Componentes:
|
||||
|
||||
- **Repro:** Playwright mobile ou unit com `fireEvent.focus` + wait suggest; ler stack.
|
||||
- **Provável superfície:** `CampaignStaffGlobalSearch` / `HomeSearchResultsLayout` / `Drawer` + focus; eventualmente provider tree se achar caminho sem `HomeSearchProvider`.
|
||||
- **Pins em** `tests/unit/campaignQuickActionsDrawer.unit.spec.tsx` (+ e2e `campaignMunicipalities` se estável).
|
||||
- **Migration:** Sem migration.
|
||||
- **File-miss:** `pnpm agent:file-miss -- --title "…" --kind defect` com body apontando B100/`a056616d` e ausência de pin focus.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Soft: B91 ✓, B100 ✓. Nenhuma dura. **B105** pode pousar depois (gesto/handle); não bloqueia o fix.
|
||||
|
||||
## Não escopo
|
||||
|
||||
- Handle no topo / scroll abre / placeholder collapsed → **B105**.
|
||||
- Remover título “Sugestões” → **B103** (pode coincidir visualmente no empty, mas é copy).
|
||||
- Strip bleed → **B101**.
|
||||
|
||||
## Rabbit holes
|
||||
|
||||
- **Trocar Base UI Drawer por sheet caseiro.** Mitigação: só se a root cause for o primitivo e não houver escape hatch documentado.
|
||||
- **Duplicar `CampaignHomeSearch` “safe” só para drawer.** Mitigação: consertar o shared.
|
||||
|
||||
## Adiado com gatilho
|
||||
|
||||
- 3º snap alto só para resultados. Revisitar se, após o fix, critique de **B105** mostrar hits cortados no dock.
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue #129 (B102) · file-miss #133
|
||||
- `CampaignQuickActionsDrawer.tsx` · `CampaignAppScrollChrome.tsx` · `CampaignQuickActionsHost.tsx` · `HomeSearchResultsContext.tsx` · `CampaignStaffGlobalSearch.tsx`
|
||||
- `tests/unit/campaignQuickActionsDrawer.unit.spec.tsx`
|
||||
- AGENTS.md — Feel the action; client boundary
|
||||
100
docs/plans/remover-titulo-sugestoes-busca.md
Normal file
100
docs/plans/remover-titulo-sugestoes-busca.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Remover título “Sugestões” no empty state da busca
|
||||
|
||||
Status: registrado
|
||||
Atualizado em: 2026-08-01
|
||||
Issue: #130
|
||||
Priority: P2
|
||||
Model: composer-2.5
|
||||
Impeccable: B — `HomeSearchMunicipalityGroup` (modo suggest)
|
||||
Appetite: ~0,25d eng; copy/CSS; sem migration
|
||||
Responsável: —
|
||||
|
||||
## Design (Impeccable)
|
||||
|
||||
Âncoras: `PRODUCT.md` (Clarity under pressure) · B68 suggest · tema `campaign`.
|
||||
|
||||
Na implementação: craft mínimo → critique → polish (Início focus vazio).
|
||||
|
||||
Brief:
|
||||
|
||||
- **Persona:** staff foca a busca no Início; já vê a lista curada.
|
||||
- **Job principal:** ir aos hits sem cabeçalho decorativo.
|
||||
- **Anti-goals:** remover o grupo “Municípios” no modo search; esconder `aria-label` acessível.
|
||||
|
||||
### Wireframe (texto)
|
||||
|
||||
```text
|
||||
Antes (focus, query vazia):
|
||||
Sugestões ← h2 + linha/espaço
|
||||
────────────────
|
||||
Cairu …
|
||||
…
|
||||
|
||||
Depois:
|
||||
Cairu …
|
||||
…
|
||||
```
|
||||
|
||||
## Dados → decisão → apresentação
|
||||
|
||||
Dados: N/A — só chrome do empty; ranking B68 intacto.
|
||||
|
||||
## Contexto
|
||||
|
||||
**B68 ✓** mostra seção com `sectionTitle = resultKind === 'suggest' ? 'Sugestões' : 'Municípios'` e `h2` via `HOME_SEARCH_GROUP_HEADING_CLASS` em `HomeSearchMunicipalityGroup`. Produto (2026-08-01): no empty/suggest do Início, o título **“Sugestões”** e a linha/espaço abaixo **não adicionam valor** — só ocupam thumb zone.
|
||||
|
||||
## Objetivos
|
||||
|
||||
- No `resultKind === 'suggest'`: **não renderizar** o `h2` “Sugestões” (nem regra visual equivalente).
|
||||
- Manter `aria-label` no `<section>` (ou no list) para leitores de tela — “Sugestões” pode ficar só no accessible name.
|
||||
- Modo `search`: título **“Municípios”** permanece _(assumido — pedido só citou suggest)_.
|
||||
- Atualizar unit `homeSearchUi` / group spec se pinarem o heading.
|
||||
- Sem migration.
|
||||
|
||||
## Decisões travadas
|
||||
|
||||
- **Só sumir o heading visual no suggest; hits B68 ficam.** **Rejeitado:** matar o empty state inteiro; renomear para outro título.
|
||||
- **A11y: nome acessível sem `h2` visível.** **Rejeitado:** section muda sem nome.
|
||||
- **i18n:** string “Sugestões” some da UI visível; id `sectionTitle` / `aria-label` ok.
|
||||
|
||||
## Questões em aberto
|
||||
|
||||
- **Modo search também perde “Municípios”?** **Opções:** A) não — só suggest | B) sim, todos os grupos sem h2. **Recomendação:** **A** (pedido explícito). _(assumido)_
|
||||
|
||||
## Abordagem proposta
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Group["HomeSearchMunicipalityGroup"] --> Kind{"resultKind"}
|
||||
Kind -->|suggest| NoH2["section aria-label only"]
|
||||
Kind -->|search| H2["h2 Municípios"]
|
||||
```
|
||||
|
||||
Componentes:
|
||||
|
||||
- **`HomeSearchMunicipalityGroup.tsx`**: condicional no `h2`; `aria-label` sempre.
|
||||
- **Tests** que assertam o texto “Sugestões” visível → ajustar.
|
||||
- **Migration:** Sem migration.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Soft: B68 ✓. Nenhuma dura.
|
||||
|
||||
## Não escopo
|
||||
|
||||
- Outros group headings (Lideranças, …) no modo search.
|
||||
- Crash drawer → **B102**.
|
||||
|
||||
## Rabbit holes
|
||||
|
||||
- **Restyling de todos os group headings da busca.** Mitigação: um `if` no suggest.
|
||||
|
||||
## Adiado com gatilho
|
||||
|
||||
- Remover headings em todos os grupos no mobile. Revisitar se critique da busca pedir lista “flat”.
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue #130 (B103)
|
||||
- `HomeSearchMunicipalityGroup.tsx` · `src/lib/homeSearchUi.ts` · `docs/plans/sugestoes-busca-vazia-inicio.md` (B68)
|
||||
- `PRODUCT.md` — Clarity under pressure
|
||||
109
docs/plans/strip-acoes-bleed-hit-area.md
Normal file
109
docs/plans/strip-acoes-bleed-hit-area.md
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# Strip de ações — bleed sem faixa branca + hit area via padding
|
||||
|
||||
Status: registrado
|
||||
Atualizado em: 2026-08-01
|
||||
Issue: #128
|
||||
Priority: P1
|
||||
Model: composer-2.5
|
||||
Impeccable: B — `CampaignHomeActionStrip` / `CampaignHomeActionButton` (Início + drawer)
|
||||
Appetite: ~0,5d eng; CSS + pin de classes; sem migration
|
||||
Responsável: —
|
||||
|
||||
## Design (Impeccable)
|
||||
|
||||
Âncoras: `PRODUCT.md` / `DESIGN.md` · B44/B67/B99 strip · tema `campaign`.
|
||||
|
||||
Na implementação (`work-issue`): craft compacto → critique → polish (iPhone estreito; Início **e** drawer).
|
||||
|
||||
Brief:
|
||||
|
||||
- **Persona / contexto:** assessor/CG no mobile; polegar na strip.
|
||||
- **Job principal:** strip visualmente edge-to-edge (sem “trilho” branco lateral), primeiro botão **não** colado na borda, espaçamento entre ações apertado com área clicável generosa.
|
||||
- **Estratégia de cor:** Restrained.
|
||||
- **Edit where you see:** não — launchers.
|
||||
- **Anti-goals:** encolher hit <44 px; quebrar pan B67; `p-0` global na página; segundo componente de strip.
|
||||
|
||||
### Wireframe (texto)
|
||||
|
||||
```text
|
||||
┌─ viewport ─────────────────────────────────────┐
|
||||
│████ strip full-bleed (bg até a borda) ████████│
|
||||
│ ┌ px interno ┐ ○ ○ ○ ○ →→ │
|
||||
│ │ │ labels │
|
||||
│ └────────────┘ (gap ul = 0; espaço = padding │
|
||||
│ horizontal do botão) │
|
||||
└────────────────────────────────────────────────┘
|
||||
Mesmo contrato no Início e no drawer (B105).
|
||||
```
|
||||
|
||||
## Dados → decisão → apresentação
|
||||
|
||||
Dados: N/A — chrome de launcher.
|
||||
|
||||
## Contexto
|
||||
|
||||
**B99 ✓** (#107) entregou `-mx-4` no slot `home-actions` + `gap-2` no `<ul>`. Feedback 2026-08-01: ainda há faixa branca lateral (pai `p-4` / `px-4` do drawer); primeiro botão cortado ou mal nascido; gap ainda folgado. Pedido explícito: **tirar o gap**; se o botão tiver margin, virar **padding** — a faixa transparente continua clicável (hit area maior). O fix é **geral** (Início + `CampaignQuickActionsDrawer`).
|
||||
|
||||
## Objetivos
|
||||
|
||||
- Strip full-bleed no mobile: sem gutter branco entre borda da tela e o scroller; **padding-inline interno** no scroller/`ul` para o primeiro/último botão não colar na curved edge.
|
||||
- `gap-2` → **`gap-0`**; espaçamento horizontal só via `padding-inline` (ou `px-*`) no `CampaignHomeActionButton` / `li` — hit target cresce sem afastar os círculos visualmente demais.
|
||||
- Manter: pan touch + drag fine (B67), scrollbar oculta, `line-clamp-2`, largura do círculo B58.
|
||||
- Drawer: remover/`compensar` o `px-4` do `#quickActionContext` **só em torno da strip** (busca pode manter gutter) — ou bleed da strip com `-mx-4` + `px-4` interno, espelhando o Início.
|
||||
- Guardrails: sem migration / Consent / action; pin unit das classes se já houver spec de layout.
|
||||
- Tracer: screenshot/e2e leve Início + drawer — strip cola na borda; primeiro botão tem inset >0.
|
||||
|
||||
## Decisões travadas
|
||||
|
||||
- **Item novo (B101), não reabrir B99.** Continuação do aperto + hit area. **Rejeitado:** editar só o as-built B99 sem Issue.
|
||||
- **Espaço entre ações = padding do controle, não `gap`/`margin` no `ul`.** Fonte: produto 2026-08-01. **Rejeitado:** só baixar `gap-2`→`gap-1` (não resolve hit area transparente); margin no `li` (mata a área morta clicável).
|
||||
- **Bleed da strip, não `p-0` no scroll da página / drawer inteiro.** Busca e conteúdo mantêm gutter. **Rejeitado:** zerar padding do `#quickActionContext` inteiro.
|
||||
- **i18n:** ids `CampaignHomeActionStrip` / `actionControlClassName`; copy intacta.
|
||||
|
||||
## Questões em aberto
|
||||
|
||||
- **Quanto de `padding-inline` no botão?** **Opções:** A) `px-1.5` (~6 px) | B) `px-2` (8 px) | C) só `pl/pr` no primeiro/último via pseudo. **Recomendação:** **B** no craft; critique se os círculos parecerem colados. _(assumido)_
|
||||
|
||||
## Abordagem proposta
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Home["home-actions -mx-4"] --> Strip["CampaignHomeActionStrip"]
|
||||
Drawer["quickActionContext"] -->|"-mx-4 na strip"| Strip
|
||||
Strip --> Ul["ul gap-0 + px-4 interno"]
|
||||
Ul --> Btn["ActionButton px-* (hit)"]
|
||||
```
|
||||
|
||||
Componentes:
|
||||
|
||||
- **`CampaignHomeActionStrip.tsx`**: `gap-2` → `gap-0`; padding horizontal no scroller ou `ul` (compensar bleed).
|
||||
- **`CampaignHomeActionButton.tsx`**: acrescentar `px-*` em `actionControlClassName` (não margin).
|
||||
- **`CampaignHomeLayout` / drawer**: garantir bleed + inset interno nos dois call sites; drawer deixa de “prender” a strip com `px-4` sem bleed.
|
||||
- **Unit:** atualizar pin de classes se existir; caso contrário assert mínimo no strip spec.
|
||||
- **Migration:** Sem migration.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Soft: B99 ✓, B67 ✓. Soft com **B105** (altura do dock / 2ª linha do label — geometria do drawer, não spacing).
|
||||
- Nenhuma dura.
|
||||
|
||||
## Não escopo
|
||||
|
||||
- Ritual scroll/handle/placeholder do drawer → **B105**.
|
||||
- Copy “Pular” → **B104**.
|
||||
- Crash da busca → **B102**.
|
||||
- Remover título “Sugestões” → **B103**.
|
||||
|
||||
## Rabbit holes
|
||||
|
||||
- **Reescrever strip com CSS scroll-padding / snap complexos.** Mitigação: só gap/padding/bleed.
|
||||
- **Componente `DrawerActionStrip` paralelo.** Mitigação: um strip, dois call sites.
|
||||
|
||||
## Adiado com gatilho
|
||||
|
||||
- Fade edges nas pontas do pan. Revisitar se critique mostrar que o bleed “corta” o último círculo sem affordance de overflow.
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue #128 (B101) · #107 (B99 ✓) · `CampaignHomeActionStrip.tsx` · `CampaignHomeActionButton.tsx` · `CampaignHomeLayout.tsx` · `CampaignQuickActionsDrawer.tsx`
|
||||
- `PRODUCT.md` / `DESIGN.md` — thumb zone / Clarity under pressure
|
||||
103
docs/plans/wizard-pular-curto-encadeadas.md
Normal file
103
docs/plans/wizard-pular-curto-encadeadas.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Wizard — “Pular” curto nas ações encadeadas
|
||||
|
||||
Status: registrado
|
||||
Atualizado em: 2026-08-01
|
||||
Issue: #131
|
||||
Priority: P1
|
||||
Model: composer-2.5
|
||||
Impeccable: B — slot direito do header mobile do wizard
|
||||
Appetite: ~0,25–0,5d eng; constantes de skip + pins; sem migration
|
||||
Responsável: —
|
||||
|
||||
## Design (Impeccable)
|
||||
|
||||
Âncoras: `PRODUCT.md` · B75/B96 header · tema `campaign` (Mandate Red).
|
||||
|
||||
Na implementação: craft compacto → critique → polish (header estreito).
|
||||
|
||||
Brief:
|
||||
|
||||
- **Persona:** staff no meio da cadeia pós-ação principal (B98).
|
||||
- **Job principal:** pular o ajuste opcional com um verbo curto; na ação principal, **X** continua.
|
||||
- **Anti-goals:** X+Pular juntos; “Pular …” longo no header.
|
||||
|
||||
### Wireframe (texto)
|
||||
|
||||
```text
|
||||
Principal (standalone / 1ª config):
|
||||
┌─ header ──────────────────────────────┐
|
||||
│ [Voltar?] Ajustar votos · Cairu [X] │
|
||||
└───────────────────────────────────────┘
|
||||
|
||||
Encadeada (ex. tendência após votos):
|
||||
┌─ header ──────────────────────────────┐
|
||||
│ [Voltar] Mudar tendência · Cairu [Pular] │
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Dados → decisão → apresentação
|
||||
|
||||
Dados: N/A — chrome de fluxo.
|
||||
|
||||
## Contexto
|
||||
|
||||
**B96 ✓** (#104) alinhou: skip só quando o passo é subfluxo encadeado; label **específica** (“Pular mudança de tendência →”, etc.) — B75 pedia o nome do fluxo. **B98 ✓** encadeia os ajustes. Produto (2026-08-01): nas encadeadas, o direito deve ser só **“Pular”**; a ação principal mantém **X**.
|
||||
|
||||
Constantes atuais: `WIZARD_*_SKIP_LABEL` em `campaignWizardCopy.ts`, `wizardSignalUi.ts`, `politicalTrendWizardUi.ts`.
|
||||
|
||||
## Objetivos
|
||||
|
||||
- Toda label de skip encadeada → **`"Pular"`** (constante única compartilhada, idealmente).
|
||||
- Resolvers (`resolveWizard*Skip`) intactos na **condição** (quando há skip); só a string muda.
|
||||
- Ação principal / standalone: `skip` undefined → header mostra **X** (B96).
|
||||
- Unit: labels === `'Pular'`; standalone tendência/sinal sem skip.
|
||||
- Sem migration.
|
||||
|
||||
## Decisões travadas
|
||||
|
||||
- **Supersede B96 na copy: label genérica “Pular”.** Fonte: produto 2026-08-01. **Rejeitado:** manter nome do fluxo (B96/B75 — supersedido neste ponto); “Pular →”.
|
||||
- **Uma constante compartilhada** (`WIZARD_CHAIN_SKIP_LABEL = 'Pular'`) reusada pelos quatro fluxos. **Rejeitado:** quatro strings iguais espalhadas.
|
||||
- **Destino do skip / cadeia = B98 (já entregue); este item é só copy.** **Rejeitado:** reabrir matriz de encadeamento.
|
||||
- **i18n:** id `WIZARD_CHAIN_SKIP_LABEL`; copy pt-BR “Pular”.
|
||||
|
||||
## Questões em aberto
|
||||
|
||||
- **Seta “→” some?** **Opções:** A) sim, só “Pular” | B) “Pular →”. **Recomendação:** **A**. _(assumido)_
|
||||
|
||||
## Abordagem proposta
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Resolve["resolveWizard*Skip"] -->|encadeado| Label["Pular"]
|
||||
Resolve -->|standalone| X["skip undefined → X"]
|
||||
```
|
||||
|
||||
Componentes:
|
||||
|
||||
- **`src/lib/campaignWizardCopy.ts`** (ou módulo de contrato): export `WIZARD_CHAIN_SKIP_LABEL`.
|
||||
- **`wizardSignalUi.ts` / `politicalTrendWizardUi.ts` / votes / leadership:** apontar label para a constante; remover strings longas se knip reclamar.
|
||||
- **Unit** dos resolvers + qualquer snapshot de header.
|
||||
- **Migration:** Sem migration.
|
||||
|
||||
## Dependências
|
||||
|
||||
- Soft: B96 ✓, B98 ✓. Nenhuma dura.
|
||||
|
||||
## Não escopo
|
||||
|
||||
- Mudar quando o skip aparece (já B96/B98).
|
||||
- Desktop copy fora do header mobile.
|
||||
|
||||
## Rabbit holes
|
||||
|
||||
- **Renomear todo o chrome B75.** Mitigação: só as quatro labels de skip.
|
||||
|
||||
## Adiado com gatilho
|
||||
|
||||
- Tooltip no “Pular” com o nome do subfluxo. Revisitar se a mesa achar o verbo ambíguo na cadeia longa.
|
||||
|
||||
## Referências
|
||||
|
||||
- GitHub Issue #131 (B104)
|
||||
- `docs/plans/wizard-header-x-vs-pular.md` (B96) · `campaignWizardCopy.ts` · `wizardSignalUi.ts` · `politicalTrendWizardUi.ts` · `wizardLeadershipContract.ts`
|
||||
- AGENTS.md — naming / pt-BR copy
|
||||
Loading…
Reference in a new issue