Merge pull request #277 from fsolla/cursor/pool-i271-cbcf1835-00b9
B130 — Sidebar /campanha sem logo nem chip de escopo no topo
This commit is contained in:
commit
f176412e2b
4 changed files with 66 additions and 29 deletions
65
docs/plans/sidebar-sem-logo-escopo-impl.md
Normal file
65
docs/plans/sidebar-sem-logo-escopo-impl.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# 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)
|
||||
|
|
@ -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 (
|
||||
<Sidebar collapsible="offcanvas" className="print:hidden">
|
||||
<SidebarHeader className="border-b border-sidebar-border">
|
||||
<Link
|
||||
href="/campanha"
|
||||
className="block w-full rounded-md outline-none focus-visible:ring-2 focus-visible:ring-sidebar-ring"
|
||||
>
|
||||
<CampaignLogo />
|
||||
</Link>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<CampaignScopeBadge className="mb-3 w-fit">
|
||||
{campaignRoleLabels[user.role]}
|
||||
</CampaignScopeBadge>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{getCampaignNav(user.role).map((item) => (
|
||||
|
|
|
|||
|
|
@ -282,15 +282,6 @@ const SidebarInset = ({ className, ...props }: React.ComponentProps<'main'>) =>
|
|||
/>
|
||||
)
|
||||
|
||||
const SidebarHeader = ({ className, ...props }: React.ComponentProps<'div'>) => (
|
||||
<div
|
||||
data-slot="sidebar-header"
|
||||
data-sidebar="header"
|
||||
className={cn('flex flex-col gap-2 p-2', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
|
||||
const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) => (
|
||||
<div
|
||||
data-slot="sidebar-footer"
|
||||
|
|
@ -513,7 +504,6 @@ export {
|
|||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarMenu,
|
||||
SidebarMenuAction,
|
||||
|
|
|
|||
|
|
@ -428,8 +428,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)
|
||||
|
|
@ -480,7 +478,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')
|
||||
|
|
|
|||
Loading…
Reference in a new issue