- feat(025): favoritos locais com FavoritesContext, HeartButton, PublicFavoritesPage
- feat(026): central de contatos admin (leads/contatos unificados)
- feat(027): configuração da página de contato via admin
- feat(028): trabalhe conosco - candidaturas com upload e admin
- feat(029): UX área do cliente - visitas, comparação, perfil
- feat(030): navbar UX - menu mobile, ThemeToggle, useFavorites
- feat(031): hero light/dark - imagens separadas por tema, upload, preview, seed
- feat(032): performance homepage - Promise.all parallel fetches, sessionStorage cache,
preload hero image, loading=lazy nos cards, useInView hook, will-change carrossel,
keyframes em index.css, AgentsCarousel e HomeScrollScene via props
- fix: light mode HomeScrollScene - gradiente, cores de texto, scroll hint
migrations: g1h2i3j4k5l6 (source em leads), h1i2j3k4l5m6 (contact_config),
i1j2k3l4m5n6 (job_applications), j2k3l4m5n6o7 (hero theme images)
5.2 KiB
5.2 KiB
Data Model — 030-navbar-topo-ux
Esta feature não cria entidades de banco nem migrations. O modelo abaixo descreve dados de sessão já existentes e o estado de UI necessário para a navbar.
1. Entidades Existentes Consumidas
AuthSession
Fonte: frontend/src/contexts/AuthContext.tsx
| Campo | Tipo | Origem | Uso na navbar |
|---|---|---|---|
user |
`User | null` | contexto de autenticação |
token |
`string | null` | localStorage + contexto |
isAuthenticated |
boolean |
derivado do contexto | Liga/desliga ações de visitante vs cliente/admin |
isLoading |
boolean |
bootstrap da sessão | Evita flicker de ações incorretas durante hidratação |
logout() |
() => void |
contexto | Encerra sessão e força retorno visual ao estado visitante |
UserProfile
Fonte: tipo User retornado pelo fluxo de auth atual.
| Campo | Tipo | Regra | Uso na navbar |
|---|---|---|---|
name |
string |
obrigatório quando user != null |
Exibe inicial e primeiro nome truncado |
role |
string |
valor relevante nesta feature: admin ou não-admin |
Controla presença do menu Admin e do menu Minha Conta |
Invariantes:
user === nullimplica navbar de visitante.user.role === 'admin'implica ausência do menu de cliente padrão.- Nome longo nunca deve quebrar layout; deve ser truncado no gatilho.
2. Entidades de Navegação
NavItem
Representa um item navegável exibido em um dos grupos da navbar.
interface NavItem {
label: string
to: string
end?: boolean
visibility: 'public' | 'client' | 'admin'
group: 'primary' | 'contextual' | 'cta'
}
Regras:
- Itens
publicaparecem para todos, salvo ajustes de prioridade visual. - Itens
clientaparecem apenas quandoisAuthenticated === trueerole !== 'admin'. - Itens
adminaparecem apenas quandorole === 'admin'. group='cta'não substitui o grupo público; ele complementa a hierarquia do topo.
ProfileSection
Agrupa ações contextuais por perfil no mobile e no desktop.
interface ProfileSection {
id: 'admin' | 'client'
title: string
items: NavItem[]
includesLogout: boolean
}
Regras:
- No mobile, cada seção deve aparecer com cabeçalho próprio.
- Logout deve permanecer visualmente separado das ações de navegação.
3. Estado Transitório de UI
NavUIState
Modelo recomendado para governar interações mutuamente exclusivas.
type ActiveOverlay = 'closed' | 'mobile' | 'admin' | 'client'
interface NavUIState {
activeOverlay: ActiveOverlay
isDesktop: boolean
}
Regras de transição:
| Evento | Estado atual | Próximo estado | Observação |
|---|---|---|---|
| Clique no hambúrguer | closed |
mobile |
Só em mobile |
| Clique no hambúrguer | mobile |
closed |
Toggle padrão |
| Clique no gatilho Admin | closed ou client |
admin |
Fecha qualquer outro overlay |
| Clique no gatilho Cliente | closed ou admin |
client |
Fecha qualquer outro overlay |
| Clique fora | mobile / admin / client |
closed |
Requisito FR-012 |
| Mudança de rota | qualquer | closed |
Requisito FR-013 |
| Logout confirmado | qualquer | closed |
Navbar volta ao estado visitante |
| Escape | mobile / admin / client |
closed |
Recomendado para previsibilidade |
Invariantes:
- Apenas um contexto pode permanecer aberto por vez.
mobilenão pode coexistir comadminouclient.admineclientsão mutuamente exclusivos.
4. Estados Derivados de Exibição
NavbarVariant
type NavbarVariant = 'visitor' | 'client' | 'admin'
Derivação:
visitor:!isLoading && !isAuthenticatedclient:isAuthenticated && user?.role !== 'admin'admin:isAuthenticated && user?.role === 'admin'
ActiveLinkState
Estado derivado de NavLink/rota atual.
Regras:
- Links públicos devem refletir estado ativo em desktop e mobile.
- Rotas com query string, como
/imoveis?listing_type=venda, devem manter coerência visual com a intenção do link. - Itens contextuais devem fechar o menu após navegação bem-sucedida.
5. Regras de Validação de UX/A11y
| Regra | Aplicação |
|---|---|
aria-expanded coerente |
gatilhos do menu mobile e dropdowns |
aria-controls presente |
menu hambúrguer e, se aplicável, painéis contextuais |
| foco visível | todos os links e botões interativos |
alvo mínimo 44x44 |
hambúrguer, CTA, itens tocáveis em mobile |
| truncamento elegante | nome do usuário e gatilhos de perfil |
6. Relações Entre Entidades
AuthSession
└── UserProfile
├── role ──────────────┐
└── name ───────┐ │
│ │
NavbarVariant <─────────┘ │
│
NavItem.visibility ────────────┘
NavUIState.activeOverlay
├── controls mobile menu visibility
├── controls admin dropdown visibility
└── controls client dropdown visibility