cosmemilton-ui/clientLayout & chrome

CmAppShell

Use como estrutura raiz de sistemas administrativos quando a navegacao lateral, o topo, o drawer mobile e a area rolavel precisam se coordenar.

Import

tsx
import { CmAppShell } from "cosmemilton-ui/client";

Shell administrativo completo

Exemplo com CmSidebar standalone, CmTopbar, acoes, metricas e conteudo rolavel.

Painel operacional

Hoje, 31/05

Online
18 em aberto3 urgentes

Pedidos

Acompanhe a fila, priorize pendencias e mantenha o time alinhado.

Receita hoje
R$ 42,8k
12%vs. ontem
Pedidos
12818 aguardando acao
SLA
94%
3%ultimas 24h

Fila de atendimento

Tempo medio 14min
Pedido #1048Acme Ltda. - aguardando separacao
09:42
Pedido #1049Aurora Foods - pagamento confirmado
10:08
Pedido #1050Nimbus Tech - revisar endereco
10:31

Checklist do turno

Separacao conferida12 pedidos liberados para expedicao
ok
Pendencias fiscais3 notas exigem revisao antes do envio
acao
Equipe de suporte5 conversas aguardam resposta
5
tsx
"use client";

import { CmAppShell, CmButton, CmSidebar, type CmSidebarGroup } from "cosmemilton-ui/client";
import {
  CmBadge,
  CmCard,
  CmGrid,
  CmGridContainer,
  CmItem,
  CmMetricCard,
  CmPage,
  CmPageHeader,
  CmRow,
  CmStack,
  CmText,
  CmTopbar,
} from "cosmemilton-ui/server";

const groups: CmSidebarGroup[] = [
  {
    id: "operacao",
    label: "Operacao",
    defaultOpen: true,
    items: [
      { id: "overview", label: "Visao geral", href: "/dashboard" },
      { id: "orders", label: "Pedidos", href: "/pedidos", badge: "18" },
      { id: "clients", label: "Clientes", href: "/clientes" },
    ],
  },
  {
    id: "gestao",
    label: "Gestao",
    items: [
      { id: "team", label: "Equipe", href: "/equipe" },
      { id: "settings", label: "Configuracoes", href: "/configuracoes" },
    ],
  },
];

const queue = [
  { title: "Pedido #1048", description: "Acme Ltda. - aguardando separacao", meta: "09:42" },
  { title: "Pedido #1049", description: "Aurora Foods - pagamento confirmado", meta: "10:08" },
  { title: "Pedido #1050", description: "Nimbus Tech - revisar endereco", meta: "10:31" },
];

export default function Example() {
  return (
    <CmAppShell
      height={620}
      sidebarWidth={260}
      sidebar={
        <CmSidebar
          standalone
          groups={groups}
          activePathname="/pedidos"
          brand={{ title: "Acme Admin", subtitle: "Operacao" }}
          footer={<CmBadge tone="success">Online</CmBadge>}
        />
      }
      topbar={(controls) => (
        <CmTopbar
          mobileLayout="inline"
          layout="start"
          start={
            <CmRow gap="sm" align="center">
              {controls.mobileMenuButton}
              <CmStack gap="none">
                <CmText weight="semibold">Painel operacional</CmText>
                <CmText size="xs" tone="muted">Hoje, 31/05</CmText>
              </CmStack>
            </CmRow>
          }
          end={
            <CmRow gap="sm" align="center" wrap>
              <CmBadge tone="success">Online</CmBadge>
              <CmButton size="sm" variant="outline">Exportar</CmButton>
              <CmButton size="sm" tone="primary">Novo pedido</CmButton>
            </CmRow>
          }
        />
      )}
    >
      <CmPage fullWidth padding="lg" gap="lg">
        <CmPageHeader
          title="Pedidos"
          description="Acompanhe a fila, priorize pendencias e mantenha o time alinhado."
          meta={
            <CmRow gap="xs" wrap>
              <CmBadge tone="info">18 em aberto</CmBadge>
              <CmBadge tone="warning">3 urgentes</CmBadge>
            </CmRow>
          }
          actions={<CmButton tone="primary">Criar pedido</CmButton>}
        />

        <CmGridContainer columns={{ base: 1, md: 3 }} gap="md">
          <CmGrid>
            <CmMetricCard title="Receita hoje" value="R$ 42,8k" trend={{ value: 12, label: "vs. ontem" }} tone="success" accent="top" />
          </CmGrid>
          <CmGrid>
            <CmMetricCard title="Pedidos" value="128" description="18 aguardando acao" tone="info" accent="top" />
          </CmGrid>
          <CmGrid>
            <CmMetricCard title="SLA" value="94%" trend={{ value: -3, label: "ultimas 24h" }} tone="warning" accent="top" />
          </CmGrid>
        </CmGridContainer>

        <CmGridContainer columns={{ base: 1, lg: 2 }} gap="md">
          <CmGrid>
            <CmCard padding="lg">
              <CmStack gap="md">
                <CmRow justify="between" align="center" wrap>
                  <CmText weight="semibold">Fila de atendimento</CmText>
                  <CmBadge>Tempo medio 14min</CmBadge>
                </CmRow>
                <CmStack gap="sm">
                  {queue.map((item) => (
                    <CmItem key={item.title} title={item.title} description={item.description} meta={item.meta} />
                  ))}
                </CmStack>
              </CmStack>
            </CmCard>
          </CmGrid>

          <CmGrid>
            <CmCard padding="lg" tone="primary" accent="left">
              <CmStack gap="sm">
                <CmText weight="semibold">Checklist do turno</CmText>
                <CmItem title="Separacao conferida" description="12 pedidos liberados para expedicao" meta={<CmBadge tone="success">ok</CmBadge>} />
                <CmItem title="Pendencias fiscais" description="3 notas exigem revisao antes do envio" meta={<CmBadge tone="warning">acao</CmBadge>} />
                <CmItem title="Equipe de suporte" description="5 conversas aguardam resposta" meta="5" />
              </CmStack>
            </CmCard>
          </CmGrid>
        </CmGridContainer>
      </CmPage>
    </CmAppShell>
  );
}

API rapida

CmAppShell

sidebartopbarchromedensitysidebarWidthcollapsedSidebarWidthheightcontentClassNamemainClassName

Notas

Para uma navegacao lateral pronta, passe CmSidebar com standalone no slot sidebar.

Se usar topbar customizada, passe uma funcao e renderize controls.mobileMenuButton para manter o drawer acessivel no mobile.

CmAppShell controla altura e scroll interno. Use height quando estiver dentro de uma area demonstrativa; em apps reais o padrao ocupa a viewport.