AppShell
Estrutura do app — a moldura de uma tela. Um cabeçalho, a área principal da página e um rodapé opcional, numa coluna da altura da tela, com um link para pular o cabeçalho.
Instalação
Configure o Camaleo uma vez (Instalação) e importe o que precisar. Ele não tem estado, então também renderiza no servidor.
import { AppShell, AppShellHeader, AppShellBody, AppShellContent, AppShellFooter, SkipLink } from "@camaleo/react";Anatomia
Uma coluna da altura da tela, com as áreas seguras dos celulares com entalhe como espaçamento. As partes são regiões comuns: o cabeçalho é o banner da página, o conteúdo é o main dela. Para ter uma barra lateral, ponha o AppShellBody abaixo do cabeçalho: uma linha com a Sidebar e o AppShellContent, em que o conteúdo ocupa o resto da largura, também ao lado de um trilho.
Exemplos
Cada exemplo é um arquivo de verdade que você pode copiar, encolhido para caber no quadro. A página da documentação em volta já tem um main, então o AppShellContent de cada quadro recebe render={<div />} e um id do useId; no seu app, tire os dois.
Painel com uma faixa lateral
O AppShellBody põe a barra lateral numa linha embaixo do cabeçalho. Aperte o botão no pé da faixa para mostrar os rótulos; o conteúdo ocupa o resto da largura.
Breadcrumb e busca no cabeçalho
O cabeçalho diz onde você está e oferece um jeito de ir a qualquer lugar. Aperte Buscar: a paleta de comandos abre e leva a uma página.
Só a lista rola
Dê overflow-y: auto à área de conteúdo e uma altura fixa à moldura. A busca e as caixas de e-mail ficam à vista enquanto as mensagens rolam.
Links das seções ao lado do formulário
Um SidebarNav dentro do conteúdo lista as seções de uma página. Quando a moldura fica estreita, ele sobe para cima do formulário em vez de espremê-lo.
Link para pular primeiro
Clique acima da moldura e aperte Tab. O SkipLink aparece, e o Enter leva o foco direto ao conteúdo, para quem usa teclado não passar por todos os links em toda página.
Barra, faixa ou gaveta conforme a largura
A moldura não muda sozinha: você escolhe um layout para cada largura. Estreite esta janela para ver a barra inteira virar uma faixa e depois um botão de menu com gaveta.
Em contexto
Telas do tamanho de um celular que você pode copiar, no estilo que escolheu. Cabeçalho e rodapé ficam parados; o meio rola.
Boas práticas
Role a lista: o cabeçalho, com a busca e a conta, fica sempre a um clique.
Role esta. Quando a moldura inteira rola, a pessoa precisa voltar ao topo para chegar ao menu.
O nome do app, a busca, as notificações e a conta. As ações de uma página ficam na própria página.
Botões que só funcionam numa página viram ruído em todas as outras e quebram linha em telas pequenas.
Props
id do elemento para onde ele pula, normalmente o AppShellContent.AppShell, AppShellHeader e AppShellFooter aceitam as props de div, header e footer. O AppShellBody aceita as props de div. O AppShellContent aceita as props de main, e o id dele é "main-content" por padrão, o mesmo alvo que o SkipLink usa quando você não passa targetId. Mude os dois juntos e mantenha o id único. O render troca o main por outro elemento, como render={<div />} quando a página já tem um main; o id continua, então o link para pular segue funcionando.
Styling hooks
Mude o visual sem copiar o componente: use os slots ou defina os tokens num elemento pai, num estilo ou na própria moldura.
Tokens que ele lê
Cor
Forma e tamanho
Tipografia e movimento
Só deste componente
/* um cabeçalho mais alto e um conteúdo que rola sozinho */
.app [data-slot="app-shell"] {
--cml-app-shell-header-height: 4rem;
height: 100dvh;
}
.app [data-slot="app-shell-content"] {
overflow-y: auto;
}Acessibilidade
- Tenha uma região de cada por página: um header como banner, um AppShellContent como main, um footer. Dentro de outras regiões eles viram caixas comuns, então não ponha a moldura dentro de um main.
- Dê nome às regiões de navegação ("Principal", "Seções das configurações") quando houver mais de uma, para que dê para diferenciá-las na lista de regiões do leitor de tela.
- Traduza o texto do link para pular. Dê tabIndex={-1} ao alvo se ele não for um main, para o foco conseguir chegar lá.
- Quando só o conteúdo rola, ele precisa ter algo focável ou receber tabIndex={0}, para quem usa teclado conseguir rolar.