Componentes
shadcn/ui, shared components e Lucide icons
O frontend trabalha com três camadas de componentes:
src/components/ui/— primitivos do shadcn/ui (código próprio, editável)src/components/shared/— componentes compartilhados de alto nível, obrigatórios para padronizaçãosrc/components/layout/— shell do app (AppLayout,AppSidebar,AppHeader)
Shared Components
Localizados em src/components/shared/. Obrigatórios para qualquer nova página. Nunca construa esses padrões manualmente inline — use os componentes.
| Componente | Uso |
|---|---|
PageHeader | Cabeçalho de página (title, description, children = ação principal) |
KpiCard | Cartão de métrica (label, value, tooltip, delta) |
ChartCard | Wrapper de gráficos (title, description, action, legend, narrative) |
EmptyState | Estado vazio de página (icon, title, description, action) |
SectionOverline | Texto de rótulo de seção |
HubLayout | Layout de hub (sidebar + área principal) |
HubSidebarSection | Seção colapsável na sidebar do hub |
HubTimeline | Timeline de eventos do hub |
InlineEditField | Campo editável inline (click-to-edit) |
SearchableSelect | Combobox com busca accent-insensitive e opção "Criar X" |
LoadingState | Skeleton de carregamento de página |
RouteErrorBoundary | Error boundary global da rota raiz |
SuspenseWrapper | Wrapper para lazy loading com Suspense |
Nunca use <h1>, <h2> ou <h3> soltos como título de página — sempre PageHeader. Nunca envolva um gráfico em Card + CardHeader + CardTitle direto — use ChartCard. Nunca construa um cartão de KPI manualmente — use KpiCard.
Exemplo: PageHeader
import { PageHeader } from "@/components/shared/PageHeader";
<PageHeader title="Negócios" description="Gerencie seu pipeline de vendas.">
<Button>Novo negócio</Button>
</PageHeader>Exemplo: KpiCard
import { KpiCard } from "@/components/shared/KpiCard";
<KpiCard
label="Negócios ganhos"
value="R$ 42.000"
tooltip="Total de negócios marcados como ganhos no período"
delta={{ value: "+12%", direction: "up" }}
/>Exemplo: ChartCard
import { ChartCard } from "@/components/shared/ChartCard";
<ChartCard title="Negócios por semana" description="Criados vs ganhos">
{/* loading skeleton, error state, empty state ou o chart */}
</ChartCard>shadcn/ui
Style radix-nova. Configuração em apps/app/components.json, tokens (oklch) em src/index.css.
A lista atual de componentes instalados está em apps/app/src/components/ui/. Antes de adicionar, verifique se já existe.
Adicionar componentes
cd apps/app && bunx shadcn@latest add <component>Componentes recomendados
Antes de hand-buildar UI, veja se shadcn já tem:
- Tabelas com sorting/filtering →
table+ TanStack Table - Charts →
chart - Command palette →
command - Date picking →
calendar/date-picker - Drawers →
drawer - Toasts →
sonner(usetoast()desonner)
Imports
Importe diretamente — sem wrappers:
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";Customização
Os componentes em src/components/ui/ são código próprio. Edite o arquivo diretamente quando precisar customizar.
cn()
Utilitário para merge condicional de classes (clsx + tailwind-merge):
import { cn } from "@/lib/utils";
<div className={cn("px-4 py-2", isActive && "bg-primary text-white")} />Ícones
Apenas Lucide React:
import { Settings, Users, Kanban } from "lucide-react";
<Settings className="size-4" />Os outros componentes de shared/
Além dos obrigatórios, src/components/shared/ tem:
| Componente | Para quê |
|---|---|
EntityPreviewSheet | a gaveta lateral com o resumo de contato ou empresa, aberta de dentro do negócio |
DuplicateWarning | o aviso não-bloqueante de possível duplicata ao criar contato ou empresa |
UnauthorizedState | o estado de acesso negado por papel |
AutoSaveIndicator | o selo de "salvando / salvo" das telas com gravação automática |
CompanyAsyncCombobox | busca de empresa com carregamento sob demanda |
SegmentCombobox | seleção de segmento |
TruncationNotice | o aviso de "esta lista foi cortada" quando a consulta bate no teto |
Primitivos instalados que valem conhecer
Além dos usuais: combobox (busca com autocompletar), kanban (a base do quadro de negócios),
field e input-group (formulários), time-picker, e minimal-tiptap (o editor de texto rico
usado em e-mail e observações).
Não existe pagination instalado. Onde a lista é longa, o padrão da casa é carregamento
incremental por rolagem, não paginação numerada.