App Shell
Estrutura a base de layout de uma tela do admin, integrando o menu de navegação, o header, o conteúdo principal e o painel de chat da Lumi.
- Como estrutura raiz de uma tela do admin: quando é necessário menu lateral de navegação, header fixo e área de conteúdo principal; é a base de layout sobre a qual se monta o Page e o restante do conteúdo da tela.
- Com painel de chat da Lumi: quando a tela precisa mostrar o chat junto ao conteúdo, com a possibilidade de expandi-lo em tela cheia sem perder o contexto do que estava sendo feito.
- Com menu recolhido: quando o menu lateral deve poder ser reduzido a um rail estreito (somente ícones) para liberar espaço horizontal, seja de forma fixa (menuBehavior="inline") ou como overlay ao passar o mouse ou clicar (menuBehavior="popover").
- Estruturar o conteúdo interno de uma tela: título, ações, tabs ou seções. Em vez disso, usar Page dentro do children do AppShell.
- Mostrar conteúdo flutuante que não faz parte do layout permanente da tela: como confirmações ou formulários curtos. Em vez disso, usar Side Modal.
- Renderizar mais de uma instância na mesma tela: AppShell é a estrutura raiz da aplicação, não um container reutilizável dentro da tela.
Estrutura base: menu, header e conteúdo
Com painel de chat da Lumi
- Menu: slot opcional (menu) que abriga a navegação principal da aplicação; expande para menuExpandedWidth ou recolhe para um rail de menuCollapsedWidth conforme menuExpanded.
- Header: faixa superior fixa (AppShell.Header) com slots leftSlot e rightSlot para ações globais, como voltar, notificações ou a conta do usuário.
- Content: área onde é montado o conteúdo da tela, normalmente Page; quando convive com o painel de chat, ambos são agrupados dentro de AppShell.Body.
- Chat (componente AppShell.Chat): painel opcional da Lumi ancorado à direita do conteúdo; pode ser expandido em tela cheia com a prop expanded, sem perder de vista o conteúdo principal.
menuExpanded={true} (default): o menu ocupa menuExpandedWidth (240px por padrão) e mostra a navegação completa, com label junto a cada ícone. É o estado recomendado para a maioria das telas no desktop.
menuExpanded={false}: o menu é recolhido para um rail de menuCollapsedWidth (48px por padrão) que mostra apenas ícones. Usar quando a tela precisa priorizar a largura do conteúdo, por exemplo com o chat da Lumi aberto ou em editores de tela cheia.
Determina o que acontece com o restante do layout quando o menu está em menuExpanded={false}.
menuBehavior="inline" (default): o rail ocupa sua largura real dentro do layout; o conteúdo se reorganiza para ocupar o espaço restante. Usar quando o recolhimento do menu deve ser uma mudança persistente de layout, com um toggle explícito no header, como no exemplo "Menu recolhível".
menuBehavior="popover": o rail parece igual em repouso, mas ao passar o mouse (menuFlyout={{ trigger: "hover" }}) ou clicar (menuFlyout={{ trigger: "manual" }}) o menu completo aparece como overlay flutuante sem deslocar o conteúdo, através de um FloatingPortal que se fecha com Escape ou ao clicar fora. Usar quando o menu precisa liberar espaço horizontal de forma permanente (por exemplo, com o chat da Lumi aberto) sem perder o acesso rápido à navegação completa; ver o exemplo "Menu recolhível com hover" para a interação completa.
Ancorado (default, expanded={false}): o chat ocupa uma coluna fixa junto ao conteúdo (entre 300px e 378px conforme o breakpoint), sem cobrir o restante da tela. Usar como estado inicial ao abrir o chat.
Expandido em tela cheia (expanded={true} ou defaultExpanded={true}): o painel passa a ocupar todo o espaço disponível à direita do menu e abaixo do header, com uma transição de largura. Usar quando o merchant precisa de mais espaço para ler uma resposta longa da Lumi ou interagir com conteúdo enriquecido, sem perder o conteúdo principal, que permanece montado e fica apenas oculto atrás. Por se tratar de um painel position: fixed calculado no cliente, essa variante é demonstrada ao vivo no exemplo "Chat (Lumi)" em vez de em uma cena estática.
- FloatingPortal (via @floating-ui/react) — o overlay de menuBehavior="popover" é renderizado através de um portal (id="nimbus-popover-floating") para poder se sobrepor ao restante do layout sem ficar recortado por containers com overflow: hidden.
AppShell define o layout raiz de toda tela do admin no desktop: o menu de navegação permanece visível (expandido ou em rail) junto ao header fixo e ao conteúdo principal, favorecendo o trabalho multitarefa. Ao abrir o chat da Lumi em telas médias, é uma boa prática levar o menu para menuBehavior="popover" com menuExpanded={false} para liberar o espaço horizontal que o chat precisa, em vez de mantê-lo expandido em largura total. Se além disso convive com um Modal ou SideModal que use ignoreAttributeName, marcar o conteúdo do chat com esse mesmo atributo (data-nimbus-outside-press-ignore é o valor padrão nos componentes do Nimbus) para que um clique dentro do chat não dispare o fechamento desse modal por "clique fora".
Abaixo do breakpoint md, menuProperties oculta o slot menu ({ display: { xs: "none", md: "block" } } é o valor padrão). A navegação é resolvida fora do AppShell, por exemplo com uma barra de navegação fixa na parte inferior da tela, de acordo com um uso mais reduzido e em movimento nesse dispositivo.
Envolver o conteúdo e o chat dentro de AppShell.Body para que compartilhem a linha flexível e ambos fiquem visíveis.
Adicionar AppShell.Chat como filho direto de AppShell, sem AppShell.Body: o conteúdo principal fica sem espaço próprio na grade.
Combinar menuBehavior="popover" com menuExpanded={false}, para que o rail fique recolhido no layout e o menu completo apareça apenas como overlay ao interagir.
Deixar menuBehavior="popover" junto com menuExpanded={true}: o menu já ocupa a largura total no layout e o modo popover nunca chega a ser ativado.
- Descarte do menu popover: quando menuBehavior="popover", o overlay se fecha com a tecla Escape ou ao clicar fora (useDismiss do @floating-ui/react), e pode ser ativado com foco de teclado além do mouse quando menuFlyout.trigger é "hover".
- Papel do overlay: o menu exibido em modo popover é renderizado com role="dialog", para que as tecnologias assistivas o identifiquem como um painel sobreposto e não como parte do fluxo normal do documento.
- Sem landmarks próprios: AppShell não aplica roles ARIA de navegação ou conteúdo (nav, main) aos seus slots; se a tela precisar dessa semântica, adicioná-la no conteúdo de menu e children (por exemplo, através do Menu, que já expõe essa estrutura).
- Conteúdo do chat sempre montado: ao recolher o AppShell.Chat, seu conteúdo não é desmontado, portanto o estado de foco dentro do chat é mantido entre o modo ancorado e o expandido em tela cheia.
Instale o componente via terminal.
npm install @nimbus-ds/app-shellEstrutura mínima com menu lateral, header e conteúdo.
import React from "react";
import { Box, Button, Icon, Text } from "@nimbus-ds/components";
import { ChevronLeftIcon, GiftBoxIcon, UserIcon } from "@nimbus-ds/icons";
import { AppShell } from "@nimbus-ds/patterns";
const Example: React.FC = () => {
const backButton = (
<Button appearance="transparent">
<Icon source={<ChevronLeftIcon />} />
Volver
</Button>
);
const buttonStack = (
<>
<Button appearance="transparent">
<Icon source={<GiftBoxIcon />} />
Novedades
</Button>
<Button appearance="transparent">
<Icon source={<UserIcon />} />
Mi cuenta
</Button>
</>
);
const sampleMenu = (
<Box
backgroundColor="primary-surface"
borderColor="primary-interactive"
borderStyle="dashed"
borderWidth="1"
borderRadius="2"
width="15rem"
height="100vh"
display="flex"
alignItems="center"
justifyContent="center"
>
<Text fontSize="base" color="primary-interactive">
Menu content
</Text>
</Box>
);
return (
<AppShell menu={sampleMenu}>
<AppShell.Header leftSlot={backButton} rightSlot={buttonStack} />
<Box
backgroundColor="primary-surface"
borderColor="primary-interactive"
borderStyle="dashed"
borderWidth="1"
borderRadius="2"
width="100%"
height="calc(100vh - 66px)"
display="flex"
alignItems="center"
justifyContent="center"
>
<Text fontSize="base" color="primary-interactive">
Children content
</Text>
</Box>
</AppShell>
);
};
export default Example;As propriedades adicionais são passadas ao elemento <AppShell>. Consulte a documentação para ver a lista de atributos aceitos pelo elemento <AppShell>.
- Page — Estrutura o conteúdo interno da tela que é montado dentro do AppShell.
- Menu — Navegação lateral que é passada como valor da prop menu.
- Side Modal — Painel flutuante para conteúdo que não faz parte do layout permanente; pode ser ancorado ao conteúdo do AppShell com a prop root.
- Chat Input — Campo de entrada de texto para montar a interface de conversação dentro do AppShell.Chat.
AppShell
| Name | Type | Default | Description |
|---|---|---|---|
children* | React.ReactNode | Content for the body of the application. | |
menu | React.ReactNode | Optional slot for left sidebar menu. | |
menuProperties | object | Can be used to control the responsive properties of the AppShell menu so you can change which breakpoint the menu hides under. | |
menuExpanded | boolean | Controls whether the left sidebar (menu) is expanded (true) or collapsed (false). Defaults to true. | |
menuExpandedWidth | string | Sidebar width when expanded. Defaults to "240px". This is a responsive property and you can have the options below available for you to use. '{ "focus": "value", "focusVisible": "value", "focusWithin": "value", "active": "value", "hover": "value", "disabled": "value", "xs": "value", "md": "value", "lg": "value", "xl": "value", "xxl": "value" }' | |
menuCollapsedWidth | string | Sidebar width when collapsed (rail). If provided, the sidebar will render in a compact rail while collapsed. Defaults to "48px". This is a responsive property and you can have the options below available for you to use. '{ "focus": "value", "focusVisible": "value", "focusWithin": "value", "active": "value", "hover": "value", "disabled": "value", "xs": "value", "md": "value", "lg": "value", "xl": "value", "xxl": "value" }' | |
menuBehavior | 'inline' | Determines how the left sidebar behaves when collapsed. - 'inline': current behavior; width changes affect layout. - 'popover': when collapsed, hovering or clicking the rail shows the expanded menu as an overlay without affecting layout. | |
menuFlyout | object | Configuration options for the AppShell flyout (popover) behavior when the menu is collapsed. This consolidates all popover-related props into a single object for simpler usage, while keeping individual top-level props for backward compatibility. | |
contentProperties | object | Consolidated configuration for the content container. |
AppShell.Header
| Name | Type | Default | Description |
|---|---|---|---|
leftSlot | React.ReactNode | Optional content for the left-hand-side slot. | |
rightSlot | React.ReactNode | Optional content for the right-hand-side slot. |
AppShell.Body
| Name | Type | Default | Description |
|---|
AppShell.Chat
| Name | Type | Default | Description |
|---|---|---|---|
defaultExpanded | boolean | Default expanded state for uncontrolled usage. | |
expanded | boolean | Whether the chat panel is expanded to overlay mode, filling the parent container area. The overlay auto-detects the parent bounds (respecting menu and header). |
Ajude-nos a melhorar a documentação
Encontrou um problema ou tem uma sugestão? Conte para a gente.