UI Kit (Core*)

Os componentes de interface do OonCore — status com vocabulário único, KPIs, tabela de dados responsiva, drawer de detalhe, confirmação, seções de formulário, estados e mais.

Os componentes ficam em @oondemand/oon-core-front e @oondemand/oon-core-front/ui. Use-os em páginas próprias para manter a experiência padrão da Plataforma. Veja-os ao vivo na vitrine de componentes.

import {
  CorePageHeader, CoreKpiGrid, CoreDataTable, CoreStatusBadge, CoreDetailDrawer,
  CoreConfirmDialog, CoreEmpty, CoreFormSection, CoreTechnicalDetails,
} from "@oondemand/oon-core-front/ui";

Status

<CoreStatusBadge kind="contract" status="vigente" />   {/* "Ativo" · success */}
<CoreStatusBadge kind="charge" status="overdue" />     {/* "Vencida" · danger */}
<CoreStatusBadge label="Personalizado" tone="info" />

coreStatus(kind, status) traduz um estado interno para { label, tone }. Estados internos nunca aparecem como rótulo; desconhecidos ficam neutros.

kind Estados reconhecidos → rótulo
contract vigente/ativa → Ativo · pendente → Pendente de ativação · suspensa/bloqueado → Bloqueado · encerrada/expirada/cancelada/revogada → Encerrado
charge aberta → Em aberto · vencida → Vencida · paga → Paga · cancelada → Cancelada
publication publicada → Publicada · cancelada → Cancelada · recovery_required → Em recuperação
environment active → Ativo · provisioning → Em andamento · never_published → Não utilizado · deleted → Excluído
entity ativo → Ativo · pendente/rascunho → Pendente · inativo/arquivado → Inativo

Tons: success, warning, danger, info, neutral.

KPIs

<CoreKpiGrid
  loading={isLoading}
  items={[
    { id: "pedidos", label: "Pedidos", value: 128, hint: "últimos 30 dias" },
    { id: "atraso", label: "Em atraso", value: 4, tone: "danger", href: "/pedidos?status=atrasado" },
  ]}
/>

Tabela de dados

<CoreDataTable<Pedido>
  label="Pedidos"
  rows={rows}
  rowKey={(row) => row._id}
  columns={[
    { key: "numero", header: "Número" },
    { key: "fornecedor", header: "Fornecedor", hideOnMobile: true },
    { key: "status", header: "Status", render: (row) => <CoreStatusBadge kind="entity" status={row.status} /> },
  ]}
  search={{ value: busca, onChange: setBusca, placeholder: "Buscar pedido" }}
  paging={{ page, pageSize: 20, total, onPage: setPage }}
  onRowClick={(row) => setSelecionado(row)}
  selectedKey={selecionado?._id}
  loading={isLoading}
  error={error ? "Não foi possível carregar." : undefined}
  empty={<CoreEmpty title="Nenhum pedido" description="Crie o primeiro pedido." />}
/>

Busca, filtros, paginação, linha clicável por mouse e teclado, cartões no celular e estados vazio/carregando/erro.

Drawer de detalhe

<CoreDetailDrawer
  open={Boolean(selecionado)}
  onClose={() => setSelecionado(null)}
  title={selecionado?.numero}
  status={<CoreStatusBadge kind="entity" status={selecionado?.status} />}
  tabs={[
    { id: "resumo", label: "Resumo", content: <Resumo pedido={selecionado} /> },
    { id: "historico", label: "Histórico", content: <CoreTimeline items={historico} /> },
  ]}
  actions={<OonButton onClick={aprovar}>Aprovar</OonButton>}
/>

Confirmação

<CoreConfirmDialog
  open={confirmando}
  title="Cancelar pedido?"
  effect="O fornecedor será notificado e o pedido não poderá ser reaberto."
  confirmLabel="Cancelar pedido"
  tone="danger"
  busy={salvando}
  onConfirm={cancelar}
  onClose={() => setConfirmando(false)}
/>

Escreva em effect o efeito real da ação.

Formulário em seções

<CoreFormSection title="Dados de faturamento" description="Usados na emissão da nota." onSave={salvar} saving={salvando}>
  <CoreField label="CNPJ"><OonInput value={cnpj} onChange={(e) => setCnpj(e.target.value)} /></CoreField>
</CoreFormSection>

Abas

// Não controlado: o componente guarda a aba selecionada
<CoreTabs items={[
  { id: "geral", label: "Geral", content: <Geral /> },
  { id: "parcelas", label: "Parcelas", content: <Parcelas /> },
]} />

// Controlado: a aba exibida segue `value`
<CoreTabs items={items} value={aba} onChange={setAba} />

Desde a 0.7.36, a aba ativa é marcada por sublinhado brand.solid (só tokens semânticos, legível no tema escuro), o componente funciona sem value/onChange e expõe tablist/tab/tabpanel com navegação por setas, Home e End.

Detalhes técnicos

<CoreTechnicalDetails items={[{ label: "Código", value: error.code }, { label: "Protocolo", value: error.requestId }]} />

Recolhido por padrão, com botão de copiar — ideal para erros com requestId.

Catálogo completo

Componente Uso
CorePageHeader Título, descrição e ações da página
CoreToolbar, CoreActions Barras de ação
CoreKpiGrid Grade de indicadores
CoreSummaryCards Cards de resumo com tom
CoreStatusPanel Painel de status com título e ações
CoreStatusBadge, coreStatus Vocabulário único de status
CoreDataTable Tabela responsiva para dados próprios
CoreDataGrid, CoreCards Grid/cards de uma model (via CoreCollection)
CoreDetailDrawer Painel lateral com abas e ações
CoreConfirmDialog, CoreConfirmAction Confirmação de ação
CoreTabs, CoreStepper, CoreTimeline, CoreActivityLog Navegação e histórico
CoreForm, CoreField, CoreRelationField, CoreFormSection Formulários próprios
CoreEmpty, CoreEmptyState, CoreLoadingState, CoreErrorState Estados
CoreTechnicalDetails Detalhes técnicos recolhidos
CoreOrganizationSwitcher, coreInitials Cabeçalho
OonButton, OonInput, OonSelect, OonCard, OonBadge, OonGrid, OonStack, OonModal, OonDrawer Primitives (Chakra UI v3)