Pular para o conteúdo

Shell da Operação

A moldura do Admin: trilho, painel de destinos, barra superior, e o estado neutro enquanto a sessão carrega.

Toda rota autenticada do Admin vive dentro de um shell. O OperationShell é a moldura da loja: trilho de áreas, painel de destinos, barra superior e conteúdo flutuando sobre uma moldura mais escura. O PlatformShell é a moldura da área da plataforma, com a sidebar agrupada. ShellPending e ShellUnavailable são os estados neutros que aparecem antes de o shell existir, enquanto a guarda de sessão decide. Os componentes ocupam a janela inteira, então esta página mostra os esquemas, as propriedades e os estados neutros; veja o Admin para o shell vivo.

import {
  OperationShell,
  PlatformShell,
  ShellPending,
  ShellUnavailable,
} from "@rastreio-x/ui";

OperationShell

Trilho de áreas (56 px, sempre visível), painel de destinos (240 px, recolhível), barra superior (48 px) e, abaixo de 768 px, uma gaveta no lugar do trilho e do painel. As medidas vêm dos tokens --rx-shell-* (veja Grid e Layout).

Esquema do Shell em escala de 50%: moldura (chrome), trilho, painel e o conteúdo flutuando com margem e raio.

O shell só existe no cliente: o layout autenticado do Admin usa ssr: false, e o servidor entrega apenas o estado neutro. Por isso a preferência de painel aberto ou recolhido é lida do cookie antes do primeiro quadro.

<OperationShell
  activeHref="/orders"
  areas={areas}
  context={{ label: "Loja Aurora" }}
  navigate={navigate}
  onSignOut={signOut}
  user={{ label: "Marina Souza", detail: "marina@lojaaurora.com.br", accountHref: "/account" }}
>
  <Outlet />
</OperationShell>

Áreas e destinos

O Admin passa areas, cada uma com destinations reais já existentes em rota; o shell nunca inventa destinos. Um destino pode levar um selo de aviso (por exemplo, saldo baixo em Créditos), com o significado também em texto para leitor de tela.

TipoCampos
ShellAreaid, label, icon (compass, settings, user ou work), destinations
ShellDestinationid, label, href, badge?
ShellBadgetext, description (frase para tecnologia assistiva)
ShellContextlabel, description?
ShellUserlabel, detail, accountHref

Dentro do shell, useShellUser() devolve o usuário como a barra o exibe e useShellSignOut() devolve { signOut, signingOut }, a mesma saída usada pelo menu do usuário e pelo ⌘K. SHELL_CONTENT_ID é o id do contêiner de conteúdo (alvo do "Pular para o conteúdo") e SHELL_NAV_COOKIE guarda a preferência do painel.

PlatformShell

A moldura da plataforma (domínios, integrações, contas). Reaproveita a geometria e os tokens do shell da loja, mas é um componente à parte: a sidebar vem agrupada em groups, itens sem href aparecem desabilitados com o selo "Em breve", e no celular há uma barra inferior (tabIds) com o restante agrupado em "Mais" (moreIds). ⌘K ou Ctrl+K abre a busca de páginas.

<PlatformShell
  activeHref="/platform/domains"
  backHref="/orders"
  brand={<BrandMark />}
  groups={groups}
  moreIds={["health", "audit"]}
  navigate={navigate}
  onSignOut={signOut}
  tabIds={["overview", "carriers", "domains"]}
  user={{ label: "Equipe PrivateLab", detail: "plataforma" }}
>
  <Outlet />
</PlatformShell>

ShellPending

O estado enquanto a sessão é verificada. Não mostra Conta, Operação nem navegação: existe só para não renderizar conteúdo protegido antes da guarda. O contêiner fica aria-busy e a frase é um status.

ShellUnavailable

A falha de rede ou de servidor na guarda. Mostra um aviso de erro e o botão "Tentar novamente", sem inferir a Conta nem a Operação. message troca o texto; retrying desabilita o botão e mostra "Tentando novamente…".

Anatomia

PeçaPapel
TrilhoMarca e uma entrada por área; sempre visível a partir de 769 px.
PainelDestinos da área aberta; recolhe com ⌘B ou Ctrl+B.
Barra superiorMigalhas, busca (⌘K), selo do contexto e menu do usuário.
ConteúdoPainel flutuante com margem e raio; recebe o foco ao navegar.
GavetaAbaixo de 768 px, no lugar do trilho e do painel.
MolduraFundo mais escuro com gradiente ambiente; pode ficar parado.

Propriedades

Shell da loja (OperationShell):

Shell da plataforma (PlatformShell):

Estado de sessão (ShellUnavailable):

ShellPending não recebe props.

Animações

O shell em si não define transições próprias: o recolher do painel e a gaveta do celular (um Sheet) vêm do AppLayout e do Sheet do Pro, com o movimento deles. O único movimento do projeto é o gradiente ambiente da moldura, renderizado por shader, que a pessoa pode deixar parado nas preferências (ambientStatic) e que também para com prefers-reduced-motion. ShellPending e ShellUnavailable não animam.

Acessibilidade

  • O primeiro item da ordem de foco é "Pular para o conteúdo", que leva ao contêiner de conteúdo (tabIndex={-1}).
  • Cada destino ativo leva aria-current="page"; os selos têm descrição em texto para leitor de tela.
  • Ao recolher o painel com o foco dentro dele, o foco volta ao botão de recolher: nunca se perde.
  • Sair mostra um alerta se falhar, e a falha vale só para a rota em que ocorreu.
  • No PlatformShell, itens "Em breve" são aria-disabled e têm o motivo no nome acessível; o rótulo curto da barra inferior está contido no nome completo (WCAG 2.5.3).
  • ShellPending anuncia "Verificando sua sessão…" e ShellUnavailable usa role="alert" no erro.

Boas práticas

Faça

Passar só destinos reais, com href existente, e mostrar um selo quando algo precisa de atenção.

Evite

Inventar destinos que ainda não existem, ou deixar o estado de sessão aparecer como conteúdo.
  • Renderize o shell só no cliente (ssr: false no layout autenticado) e use ShellPending no servidor.
  • O selo de aviso é para algo que precisa de ação, como saldo baixo, não para contagem de itens.
  • Use useShellUser e useShellSignOut em vez de reimplementar o menu de Conta.
  • Não importe o roteador no shell: passe navigate.

Relacionados

  • Widget para os painéis dentro do conteúdo.
  • Sheet para a gaveta do celular.
  • Breadcrumbs para a trilha da barra superior.
  • Alert sobre o qual o erro de ShellUnavailable é montado.