Pular para o conteúdo principal

Cookie Consent — Site Público Abracaf

O site público da Abracaf tem seu próprio banner de consentimento de cookies, separado do componente do MakerKit (@kit/ui/cookie-banner). A lógica de consentimento foi extraída para um hook reutilizável, useCookieConsent.

Por que um banner próprio?

O banner do MakerKit é genérico (Dialog, cores bg-background, i18n via Trans, semântica accepted/rejected). O da Abracaf usa o design system próprio, links de Política/Termos e a semântica de LGPD accepted / essential. Avaliou-se substituir um pelo outro; concluiu-se que o do MakerKit não era melhor para este caso (seria regressão visual e de semântica). Em vez disso, portou-se a parte boa do MakerKit — um hook reutilizável — para dentro do componente da Abracaf.

Estrutura de arquivos

apps/web/app/[locale]/(extranet_public)/abracaf/
├── _components/
│ └── cookie-banner.tsx # 'use client' — UI do banner (visual + links)
└── _hooks/
└── use-cookie-consent.ts # 'use client' — estado e persistência do consentimento

O CookieBanner é montado uma vez no abracaf/layout.tsx, junto com ScrollToTopButton.

Hook useCookieConsent

import { useCookieConsent } from '../_hooks/use-cookie-consent';

const { status, hydrated, accept, reject, clear } = useCookieConsent();

API

CampoTipoDescrição
status'accepted' | 'essential' | 'unknown'Decisão atual do usuário
hydratedbooleantrue após o valor ser lido do localStorage no cliente
accept()() => voidGrava 'accepted' (aceita todos os cookies)
reject()() => voidGrava 'essential' (somente essenciais)
clear()() => voidReseta para 'unknown' (remove do storage)

Semântica dos status

StatusSignificado
acceptedUsuário aceitou todos os cookies
essentialUsuário optou por somente os essenciais (botão "Somente essenciais")
unknownAinda não decidiu — o banner deve aparecer

A chave de localStorage é abracaf_cookie_consent.

A flag hydrated

O hook começa sempre como status: 'unknown' no servidor e na primeira render do cliente, e só lê o localStorage dentro de um useEffect (marcando hydrated = true). Isso evita mismatch de hidratação — o HTML do servidor nunca diverge da primeira render do cliente.

Por isso o banner só deve renderizar quando já hidratou e o usuário não decidiu:

export function CookieBanner() {
const { status, hydrated, accept, reject } = useCookieConsent();

if (!hydrated || status !== 'unknown') return null;

// ...UI do banner
}
Diferença vs. MakerKit

O hook do MakerKit lê o localStorage no useState inicial, o que pode divergir do HTML do servidor. A versão da Abracaf usa a flag hydrated justamente para não ter esse risco.

Gating de analytics (futuro)

Hoje nem o banner da Abracaf nem o do MakerKit bloqueiam scripts de fato — ambos apenas registram a preferência. O hook foi desenhado para permitir esse gating quando necessário:

const { status } = useCookieConsent();

useEffect(() => {
if (status === 'accepted') {
// inicializar analytics / scripts dependentes de cookies
}
}, [status]);

Esse é o principal ganho de ter extraído a lógica para um hook reutilizável: qualquer parte do site pode ler a decisão do usuário sem reimplementar a persistência.