Pular para o conteúdo principal

Layout

O layout do front-web-base é baseado em um sistema de composição de variantes. Cada brand escolhe quais componentes de slot (header, sidebar, footer, etc.) quer usar via app/config/layout/composition.ts, sem precisar reescrever o DefaultLayout.tsx.

Sistema de Composição

Camadas

CamadaArquivoResponsabilidade
Config brand-editávelapp/config/layout/composition.tsDefine slots e estrutura para a brand
Defaults + helperapp/layouts/layout.defaults.tsValores default do base + defineLayoutConfig() (deep merge)
Catálogo centralapp/layouts/layout-registry.tsMapa string key → componente
Variantesapp/layouts/variants/<slot>/Componentes de variante reutilizáveis
Tiposapp/types/layout.tsLayoutConfig, ColumnLayout, *VariantKey

Estrutura do LayoutConfig

// app/types/layout.ts
export type ColumnLayout = "left-main" | "left-main-right";

export type HeaderVariantKey = "header-default" | "header-vera";
export type SidebarVariantKey = "sidebar-narrow" | "sidebar-wide";
export type RightPanelVariantKey = "right-panel-winners";
export type FooterVariantKey = "footer-default";

export interface LayoutConfig {
structure: {
columns: ColumnLayout;
};
slots: {
header: HeaderVariantKey;
sidebar: SidebarVariantKey;
rightPanel?: RightPanelVariantKey;
footer: FooterVariantKey;
};
componentVariants?: {
// variantes de sub-componentes (ex: bannerHeight)
[key: string]: string;
};
}

Provider Chain

Os providers são aninhados nesta ordem (dentro do DefaultLayout.tsx):

EnvProvider → BrandProvider → CountryProvider → TranslationProvider

Após os providers, três initializers executam side-effects:

InitializerFunção
AuthInitializerRestaura sessão, refresh token, polling de profile
WalletInitializerCarrega saldo e configura polling
SmarticoInitializerInicializa SDK Smartico (gamificação) se smarticoHash existir

Estrutura visual (layout padrão)

┌────────────────────────────────────────────────────────────┐
│ Header (h-14, bg-header-bg) │
│ [☰ mobile] [Logo] [Casino|Sports] [🔍 Ctrl+K] [Auth] │
├──────────────┬─────────────────────────────────────────────┤
│ Sidebar │ main (flex-1, overflow-y-auto) │
│ 280px exp. │ │
│ 70px col. │ {children} │
│ │ │
│ Promo │ <Suspense> │
│ Casino │ <LazyFooter /> │
│ Sports │ </Suspense> │
│ Extras │ │
├──────────────┴─────────────────────────────────────────────┤
│ MobileBottomNav (mobile only) │
└────────────────────────────────────────────────────────────┘

Variantes disponíveis

ChaveComponenteDescrição
header-defaultHeaderDefault.tsxHeader padrão com logo, tabs casino/sports, search, auth
header-veraHeaderVera.tsxPlaceholder para vera-bet (smoke test)
ChaveComponenteDescrição
sidebar-narrowSidebarNarrow.tsxSidebar colapsável 280px/70px (padrão)
sidebar-wideSidebarWide.tsxSidebar larga (para layouts com mais espaço)
ChaveComponenteDescrição
footer-defaultFooterDefault.tsxFooter padrão com sponsors, links, badges, legal

Right Panel (opcional)

ChaveComponenteDescrição
right-panel-winnersRightPanelWinners.tsxColuna direita com lista de vencedores

Widgets opcionais

Além dos slots estruturais, o template tem widgets opcionais que cada brand liga/desliga via app/config/widgets/<nome>.ts. Cada widget mora em app/widgets/<nome>/ e segue o pattern { variant: VariantKey | null, items: Item[] }.

WidgetConfigComponenteFunção
Sidebar Buttonswidgets/sidebar-buttons.tsapp/widgets/sidebar-buttons/CTAs no rail da sidebar (referral, tournaments, missions, etc.) — 3 visual variants (colored, gradient, grid) + 8 catalog intents typed + custom items + specials (sponsor-cta)
Topbar Notificationswidgets/topbar-notifications.tsapp/widgets/topbar-notifications/Barra rotativa no topo (download app, telegram, push)
Bottom Notificationswidgets/bottom-notifications.tsapp/widgets/bottom-notifications/CTA flutuante mobile no fundo da tela
Campaign Widgetwidgets/campaign-widget.tsapp/widgets/campaign-widget/Presentinho flutuante de campanha sazonal
Home Leagueswidgets/home-leagues.tsapp/widgets/home-leagues/Row de ligas esportivas curadas na home

Brand controla cada item via gradient/color/lucide-icon/image. Cores se ajustam ao tema da brand automaticamente quando não há override:

// overrides/<brand>/app/config/widgets/sidebar-buttons.ts
import { Trophy, Target, Users } from "lucide-react";
import type { SidebarButtonsConfig } from "~/types/sidebar-buttons";

export const sidebarButtonsConfig: SidebarButtonsConfig = {
variant: "gradient",
items: [
{
intent: "referral",
iconType: "lucide",
icon: Users,
// Brand-primary green com fade-out alpha (a1cd3d f2 → a1cd3d 36).
gradient: ["#a1cd3df2", "#a1cd3d36"],
},
{ intent: "tournaments", iconType: "lucide", icon: Trophy },
{ intent: "missions", iconType: "lucide", icon: Target },
],
};

Detalhes completos em Layout Composition — Widgets.

Lazy Modals

Modais carregados sob demanda (code-split) — montados pelo DefaultLayout.tsx:

ModalTrigger
LazyValidationBlockerOverlayUsuário sem validação completa tenta ação protegida
LazyAuthModalsLogin, registro, esqueci senha
LazyValidationStepsModalSteps de validação (email, SMS, docs, endereço)
LazyPasswordValidationModalConfirmação de senha para ações sensíveis
LazyKycModalVerificação KYC
LazyPaymentModalsDepósito, saque, PIX
SearchKeyboardShortcutCtrl/Cmd+K abre busca

BackToTop

Botão flutuante que aparece após scroll. Usa contentRef para rolar o main de volta ao topo.

MobileBottomNav

Barra de navegação fixa no rodapé em mobile. Mostra ícones para Home, Casino, Sports, Depositar, Perfil.


layout.config.ts (fork override)

O arquivo app/config/layout/composition.ts é o ponto de entrada brand-editável para o sistema de composição. O helper defineLayoutConfig faz deep merge com os defaults do base — o brand só precisa especificar o que muda.

// app/config/layout/composition.ts (base — layout padrão)
import { defineLayoutConfig } from "~/layouts/layout.defaults";

export const layoutConfig = defineLayoutConfig({});
// overrides/vera-bet/app/config/layout/composition.ts (exemplo de brand)
import { defineLayoutConfig } from "~/layouts/layout.defaults";

export const layoutConfig = defineLayoutConfig({
structure: { columns: "left-main-right" },
slots: {
header: "header-vera",
sidebar: "sidebar-wide",
rightPanel: "right-panel-winners",
},
});

Para criar uma variante completamente custom:

  1. Criar componente em app/layouts/variants/<slot>/<NomeVariante>.tsx
  2. Adicionar a chave em app/types/layout.ts (ex: "header-custom" no HeaderVariantKey)
  3. Registrar em app/layouts/layout-registry.ts
  4. Usar a nova chave no layout.config.ts do fork

Veja a documentação completa do sistema de composição em Layout Composition System.