From a4eadd80aa66430b5d11e654d7f42521e7b6ce20 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 2 Aug 2026 19:16:20 +0000 Subject: [PATCH 1/4] =?UTF-8?q?B130=20=E2=80=94=20remove=20logo=20and=20sc?= =?UTF-8?q?ope=20badge=20from=20campaign=20sidebar=20top?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Francisco Solla --- docs/plans/sidebar-sem-logo-escopo-impl.md | 64 +++++++++++++++++++ .../campaign/shell/CampaignSidebar.tsx | 16 ----- 2 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 docs/plans/sidebar-sem-logo-escopo-impl.md diff --git a/docs/plans/sidebar-sem-logo-escopo-impl.md b/docs/plans/sidebar-sem-logo-escopo-impl.md new file mode 100644 index 00000000..18f257e8 --- /dev/null +++ b/docs/plans/sidebar-sem-logo-escopo-impl.md @@ -0,0 +1,64 @@ +# Impl: Sidebar /campanha — sem logo nem chip de escopo no topo + +Status: aprovado +Atualizado em: 2026-08-02 +Issue: #271 +Intenção: docs/plans/sidebar-sem-logo-escopo.md +Appetite restante: ~0,5 dia (herdado) + +## Leitura da intenção + +- **Outcome:** O topo da sidebar (desktop e Sheet mobile) não exibe logo nem badge de papel; a lista de navegação começa no topo, alinhada com o header da área principal. Login mantém logo; chips de escopo em páginas permanecem. +- **O que NÃO negociar:** `CampaignScopeBadge` e `CampaignLogo` seguem vivos fora da sidebar; leader lockdown e nav por role intactos; auth shell inalterado. +- **O que reavaliar:** A hipótese de editar só `CampaignSidebar.tsx` confirma-se — não há outro call site de logo/badge na sidebar. + +## Abordagem recomendada + +```mermaid +flowchart LR + A[CampaignSidebar] --> B[Remove SidebarHeader + logo] + A --> C[Remove CampaignScopeBadge do grupo nav] + D[CampaignAuthPageShell] --> E[logo intacto] + F[páginas de lista] --> G[CampaignScopeBadge intacto] +``` + +**Opções consideradas:** +- A — Remover `SidebarHeader` inteiro e o badge do primeiro `SidebarGroup` em `CampaignSidebar.tsx` +- B — Esconder via CSS (`hidden`) mantendo DOM +- C — Mover logo para o rodapé + +**Recomendação:** A — remoção direta no dono; menos DOM, sem degrau vertical, sem código morto. +**Rejeitadas:** B (DOM fantasma, testes frágeis); C (fora do escopo de produto). + +### Componentes / mudanças + +- **`CampaignSidebar`** (`src/components/campaign/shell/CampaignSidebar.tsx`): remover `SidebarHeader` (logo link), `CampaignScopeBadge` e imports órfãos (`CampaignLogo`, `CampaignScopeBadge`, `SidebarHeader`, `campaignRoleLabels`). +- **Migration:** sem migration +- **Access / Consent:** N/A +- **UI:** Impeccable B — encaixe no shell; nav cola no topo do `SidebarContent`; footer com avatar/perfil inalterado. + +### Dados → forma + +N/A — chrome estrutural. + +## Fases verificáveis + +1. **UI** — editar `CampaignSidebar.tsx`; limpar imports +2. **Gates** — `pnpm gate:fast`; push via `pnpm push` + +## Rabbit holes / Não escopo (engenharia) + +- Não tocar `CampaignScopeBadge` em páginas de conteúdo +- Não alterar `CampaignAuthPageShell` nem `campaign-logo.tsx` +- Não redesenhar padding do `SidebarGroup` além do que a remoção naturalmente resolve + +## Riscos e mitigação + +- **Teste de convenção que pinne logo na sidebar:** `campaignComponents.unit.spec.ts` lê o source — verificar que pins de shell (`collapsible`, `print:hidden`, tokens) permanecem válidos. +- **Alinhamento vertical:** remover `SidebarHeader` com `border-b` elimina o degrau; header principal já é `min-h-11` — aceite visual coberto pela remoção, sem padding compensatório artificial. + +## Aceite de engenharia + +- [x] Aceite de produto da intenção ainda coberto +- [x] Invariantes AGENTS/engineering-standards +- [x] Testes de domínio previstos (unit source pins existentes; sem access/write) diff --git a/src/components/campaign/shell/CampaignSidebar.tsx b/src/components/campaign/shell/CampaignSidebar.tsx index eb961b85..503cda8b 100644 --- a/src/components/campaign/shell/CampaignSidebar.tsx +++ b/src/components/campaign/shell/CampaignSidebar.tsx @@ -5,9 +5,7 @@ import { usePathname } from 'next/navigation' import { useState, type FormEvent, type ReactNode } from 'react' import { logoutCampaign } from '@/app/(campaign)/campanha/actions/auth' -import { CampaignScopeBadge } from '@/components/campaign/shared/CampaignScopeBadge' import { CampaignUserAvatar } from '@/components/campaign/shared/CampaignUserAvatar' -import { CampaignLogo } from '@/components/campaign/shell/campaign-logo' import { MunicipalityNavSavedFilters } from '@/components/campaign/shell/MunicipalityNavSavedFilters' import { getCampaignNav, @@ -23,7 +21,6 @@ import { SidebarFooter, SidebarGroup, SidebarGroupContent, - SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, @@ -33,7 +30,6 @@ import { Spinner } from '@/components/ui/Spinner' import { clearLastActedMunicipality } from '@/lib/campaignLastActedMunicipality' import { clearCampaignPwaCaches } from '@/utilities/campaignPwaClient' import type { CampaignUserShellView } from '@/utilities/campaignUserProfile' -import { campaignRoleLabels } from '@/utilities/campaignUserProfile' import { clearMunicipalitySavedFilters } from '@/utilities/municipality/municipalitySavedFilters' import { clearRecentVisits } from '@/utilities/recentVisits' @@ -86,20 +82,8 @@ export const CampaignSidebar = ({ user }: { user: CampaignSidebarUser }) => { return ( - - - - - - - - {campaignRoleLabels[user.role]} - {getCampaignNav(user.role).map((item) => ( From da32b39b4704f339087e9ab847f134c48a0d3e12 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 2 Aug 2026 19:17:14 +0000 Subject: [PATCH 2/4] Format impl plan --- docs/plans/sidebar-sem-logo-escopo-impl.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/plans/sidebar-sem-logo-escopo-impl.md b/docs/plans/sidebar-sem-logo-escopo-impl.md index 18f257e8..73f5d7ed 100644 --- a/docs/plans/sidebar-sem-logo-escopo-impl.md +++ b/docs/plans/sidebar-sem-logo-escopo-impl.md @@ -23,6 +23,7 @@ flowchart LR ``` **Opções consideradas:** + - A — Remover `SidebarHeader` inteiro e o badge do primeiro `SidebarGroup` em `CampaignSidebar.tsx` - B — Esconder via CSS (`hidden`) mantendo DOM - C — Mover logo para o rodapé From 4bb3d65c709098ad44bd3874e4f355f90776c919 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 2 Aug 2026 19:18:00 +0000 Subject: [PATCH 3/4] Remove unused SidebarHeader export after B130 sidebar cleanup --- src/components/ui/Sidebar.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/ui/Sidebar.tsx b/src/components/ui/Sidebar.tsx index d99d82dd..b0e95f08 100644 --- a/src/components/ui/Sidebar.tsx +++ b/src/components/ui/Sidebar.tsx @@ -282,15 +282,6 @@ const SidebarInset = ({ className, ...props }: React.ComponentProps<'main'>) => /> ) -const SidebarHeader = ({ className, ...props }: React.ComponentProps<'div'>) => ( -
-) - const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) => (
Date: Sun, 2 Aug 2026 19:50:40 +0000 Subject: [PATCH 4/4] Harden B126 FAB e2e waits for layout chrome instead of page h1 --- tests/e2e/campaignMunicipalities.e2e.spec.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/e2e/campaignMunicipalities.e2e.spec.ts b/tests/e2e/campaignMunicipalities.e2e.spec.ts index 972d1611..756eace2 100644 --- a/tests/e2e/campaignMunicipalities.e2e.spec.ts +++ b/tests/e2e/campaignMunicipalities.e2e.spec.ts @@ -427,8 +427,6 @@ test.describe('Municípios — FAB ações rápidas mobile (B126)', () => { await page.goto( `${campaign.baseURL}/campanha/municipios?q=${encodeURIComponent(municipality.name)}`, ) - await expect(page.getByRole('heading', { name: 'Municípios' })).toBeVisible() - const fab = page.getByRole('button', { name: 'Ações rápidas' }) await expect(fab).toBeVisible() await expect(page.getByLabel('Buscar na campanha')).toHaveCount(0) @@ -479,7 +477,7 @@ test.describe('Municípios — FAB overlay polish (B126)', () => { await campaign.login(page, coordinator.email!, coordinator.password) await page.goto(`${campaign.baseURL}/campanha/municipios`) - await expect(page.getByRole('heading', { name: 'Municípios' })).toBeVisible() + await expect(page.getByRole('button', { name: 'Ações rápidas' })).toBeVisible() await page.getByRole('button', { name: 'Ações rápidas' }).click() const overlay = page.locator('#CampaignQuickActionsOverlay')