Shell

Shell compõe navegação, conteúdo principal e trilhos opcionais de contexto. Escolha primeiro o modelo de scroll: page mantém o documento rolando com trilhos sticky; content faz a região principal rolar.

Exemplos

Um site de documentação

Esta é a receita de scroll da página usada pelo site de docs: um Container limita a moldura, a navegação e o conteúdo são trilhos nomeados, e top={84} os mantém sob o cabeçalho sticky.

Um workspace de aplicação

Use scroll="content" para uma moldura de aplicação que controla a altura do viewport. A região principal rola enquanto a navegação e a barra superior ficam no lugar.

Estas prévias renderizam em uma largura de layout fixa de 1200px e se ajustam a esta coluna, para mostrar a configuração ampla de Shell sem overflow horizontal da página.

Quando usar

Use Shell quando uma página precisa de navegação ou contexto persistente ao lado da tarefa principal. scroll não é uma variante visual: ele escolhe entre dois motores de layout, então uma prop variant esconderia uma decisão de comportamento que afeta scroll, posição sticky e percurso de foco.

PropriedadePadrãoO que define
--shell-sidebar220pxLargura do trilho lateral
--shell-aside200pxLargura do trilho complementar
--shell-top0pxOffset do trilho sticky

Defina top (ou --shell-top) com a altura de um cabeçalho sticky. Sem isso, um trilho de scroll da página pode ficar escondido sob o cabeçalho. Em 1100px o aside desaparece; em 900px o sidebar passa então a ficar acima do documento. Esses breakpoints são fixos porque media queries não leem propriedades customizadas.

sidebarWidth controla conteúdo comum de barra lateral e trilhos de Shell com scroll de página. Em um Shell com scroll de conteúdo, um AppSidebar filho direto é dono do trilho com AppSidebar.width ou --appsidebar-width, portanto os dois controles de largura não competem.

Prefira outro componente quando:

  • A página só precisa de uma medida de conteúdo centralizada — use Container.
  • O conteúdo é uma sequência linear sem trilhos persistentes — use Stack.
  • A identidade e as ações da página precisam de um cabeçalho — use PageHeader dentro do conteúdo.

Acessibilidade

  • Shell renderiza um único <main> nativo por padrão. Para uma Shell aninhada ou incorporada, use mainAs="div"; a página ainda deve ter exatamente um landmark <main> em algum lugar.
  • Use banner para o contexto da página acima da navegação e fora de <main>. Ele renderiza em <header>; topbar continua dentro da região principal para controles locais.
  • Defina sidebarAs="div" quando o conteúdo lateral já renderiza um <nav>, como AppSidebar. Assim há um único landmark de navegação, sem um landmark complementar envolvendo-o.
  • Defina skipLink={{ label: 'Ir para o conteúdo' }} para exibir um link ao receber foco pelo teclado. Shell gera um id para a região principal; use mainId para fornecer um id estável. Defina href em skipLink somente se o destino for outro elemento.
  • sidebarAs e asideAs escolhem nav ou aside. Dê a cada trilho um sidebarLabel ou asideLabel distinto; um trilho de navegação deve usar sidebarAs="nav", como na receita de docs.
  • Shell não adiciona atalhos de teclado nem armadilha de foco. Links e controles nos trilhos preservam o comportamento nativo, e sua ordem no DOM continua sidebar, main, aside em todo breakpoint.
  • Em scroll="content", garanta que o conteúdo principal tenha controles focalizáveis ou um alvo de foco gerenciado para que usuários de teclado entrem e descubram a região rolável.
tsx
<Shell
  banner="Organização: Acme · Sandbox"
  sidebar={<AppSidebar aria-label="Navegação principal" groups={groups} />}
  sidebarAs="div"
  skipLink={{ label: 'Ir para o conteúdo' }}
  mainId="eventos"
>
  <h1>Eventos</h1>
</Shell>

API e código

NomeTipoObrigatóriaDescrição
sidebarReactNode—Optional navigation or complementary rail content.
sidebarAs'aside' | 'nav' | 'div'—Semantic element for the sidebar rail. Use `"nav"` when it contains primary navigation.
sidebarLabelstring—Accessible name for the sidebar landmark.
topbarReactNode—Optional top region placed before the main content.
bannerReactNode—Page-level banner rendered before the navigation and outside the main landmark.
skipLink{ label: string; href?: string; }—Optional keyboard skip link. Its href defaults to the main region's id.
mainIdstring—Id of the main region; generated when a skip link is provided without one.
mainAs'main' | 'div'—Semantic element for the main content. Use `"div"` when the shell is nested or embedded inside a page that already owns the `<main>` landmark.
asideReactNode—Optional complementary context rail content.
asideAs'aside' | 'nav'—Semantic element for the aside rail. Use `"nav"` when it contains navigation.
asideLabelstring—Accessible name for the aside landmark.
scroll'page' | 'content'—Whether the document or the main region is the scroll container. Default: `"page"`.
sidebarWidthnumber—Sidebar rail width in pixels. Sets `--shell-sidebar` for ordinary rails and page-scroll Shells; a direct AppSidebar in a content-scroll rail owns its width instead.
asideWidthnumber—Complementary aside rail width in pixels. Sets `--shell-aside`.
topnumber—Sticky rail offset in pixels. Sets `--shell-top`.

As classes expressam o modelo de scroll da página. Nomeie os dois landmarks de navegação e defina o offset sticky quando houver um cabeçalho fixo acima da moldura:

html
<div
  class="lyra-shell lyra-shell--page lyra-shell--has-sidebar lyra-shell--has-aside"
  style="--shell-sidebar: 220px; --shell-aside: 200px; --shell-top: 84px"
>
  <nav class="lyra-shell__sidebar" aria-label="Navegação da documentação">
    <a href="/components/container">Container</a>
  </nav>
  <main class="lyra-shell__main">
    <div class="lyra-shell__content">Conteúdo da documentação</div>
  </main>
  <nav class="lyra-shell__aside" aria-label="Nesta página">
    <a href="#accessibility">Acessibilidade</a>
  </nav>
</div>

<lyra:shell> Gerado do lyra-ds/blade v0.10.0.

PropPadrãoObrigatóriaValores de exemplo
sidebarAs'aside'——
asideAs'aside'——
sidebarLabelnull——
asideLabelnull——
mainAs'main'——
scroll'page'—content
sidebarWidthnull——
asideWidthnull——
topnull——
blade
<lyra:shell sidebar-label="Workspace navigation" main-as="main" scroll="page">
    <x-slot:topbar>
        <lyra:navbar>
            <lyra:nav-link href="/overview" active>Overview</lyra:nav-link>
            <lyra:nav-link href="/projects">Projects</lyra:nav-link>
        </lyra:navbar>
    </x-slot:topbar>
    <x-slot:sidebar>
        <lyra:nav-link href="/overview" active>Overview</lyra:nav-link>
        <lyra:nav-link href="/projects">Projects</lyra:nav-link>
    </x-slot:sidebar>
    <lyra:page-header title="Overview" />
</lyra:shell>