Skip to content

Design System

Cards

IMPORTANTE: Cards não possuem bordas no sistema. Use apenas background e border-radius.

Errado:

tsx
<View className="bg-card rounded-lg border border-border p-4">

Correto:

tsx
<View className="bg-card rounded-[6px] p-4">

O componente components/ui/Card já segue isso (bg-card, rounded-[6px], shadow-sm).


Tokens semânticos (não usar cor crua)

Os componentes consomem classes semânticas mapeadas para CSS variables HSL (ver styling.md). Nunca hardcode hex/neutral-* para superfícies e texto — use o token, que já troca entre light/dark e segue o tema paper.

ElementoClasseLight (paper)Dark (preto neutro)
Fundo da telabg-background#f5efde#0A0A0A
Card / superfíciebg-card#fefcf6#1A1A1A
Sheet / popoverbg-popover#fefcf6#1F1F1F
Superfície sutilbg-muted#f0e8d6#242424
Campo de formuláriobg-input#ece5cf#333333
Texto primáriotext-foreground#342d23#F5F5F5
Texto secundáriotext-muted-foreground#70634c#A8A8A8
Borda/divisorborder-border#ece5cf#3D3D3D
Ação primáriabg-primaryazul da marcaazul da marca
Destaquebg-secondarylaranjalaranja

No dark o tema é preto neutro (saturação 0). Como o card não tem borda, a separação em relação ao fundo vem só do degrau de lightness. Ver a tabela de elevação em styling.md.

O mesmo token resolve automaticamente para o valor light ou dark conforme a classe .dark (alternada pelo useColorScheme/setColorScheme). Não escreva variantes dark:bg-... manuais para essas superfícies — o token já cuida disso.

Cor em prop (ícones)

Para cor passada como prop (ex.: ícones Lucide), use o objeto THEME:

tsx
const { colorScheme } = useColorScheme()
const theme = THEME[colorScheme ?? 'light']

<SlidersHorizontal size={18} color={theme.mutedForeground} />

Campos de formulário

Campos que aparecem juntos numa mesma tela (input de texto, seletor de data, SelectField) devem compartilhar altura, raio, borda e superfície. Divergir em h-9 vs h-11 ou em bg-muted/20 vs bg-muted/30 deixa a tela desalinhada e, no dark, dissolve o campo no card.

O padrão é extraído numa constante do módulo e reaproveitado por todos os campos da tela, ex. modules/contracts/constants/contract-setup-field-layout.ts:

ts
export const CONTRACT_SETUP_FIELD_CLASS_NAME =
  'h-11 flex-row items-center rounded-xl border border-border bg-muted/40 px-3 dark:bg-input'
tsx
<Input className={cn(CONTRACT_SETUP_FIELD_CLASS_NAME, CONTRACT_SETUP_FIELD_TEXT_CLASS_NAME)} />
<Pressable className={cn(CONTRACT_SETUP_FIELD_CLASS_NAME, 'min-w-0 flex-1 gap-2')} />
<SelectField className={CONTRACT_SETUP_FIELD_CLASS_NAME} />

No dark o preenchimento é sempre dark:bg-input sólido: opacidades (/20, /30) não geram contraste suficiente contra bg-card.

Checkbox de campo (ex.: vigência indeterminada) usa components/ui/Checkbox numa linha própria, nunca espremido ao lado dos campos.


Status (badges)

As cores de status (success, warning, destructive, info) são mantidas em ambos os temas. O components/ui/StatusBadge mapeia o tom para as classes correspondentes. Ex.: template publicado → success; rascunho → warning.


Tipografia

Fonte nativa do sistema (sem fonte customizada no mobile). Hierarquia via components/ui/Text com variantes (h1h4, p, small, muted, ...) e classes Tailwind de tamanho/peso. Não usar Noto Serif/serif aqui — isso é exclusivo da web.


Componentes de UI

  • Primitivos em components/ui/ (Button, Card, Text, StatusBadge, Toast, ...).
  • Variantes com class-variance-authority (cva) e composição de classes com cn().
  • Ícones: lucide-react-native.

Ações em telas com SidebarLayout

Telas com abas inferiores (SidebarLayout) e mais de 2 ações usam ExpandableActionsFab (FAB flutuante expansível com pills e labels), posicionado acima da tab bar.

tsx
const fabBottomOffset = useSidebarEditorFabOffset(compact)
const fabActions = mapEditorHeaderActionsToFab(headerActions)

<ExpandableActionsFab actions={fabActions} bottomOffset={fabBottomOffset} disabled={isSaving} />

Referência: Feature Map — FAB.

Listagens com uma ação primária (criar) usam BorrowerFab. Editores com ≤ 2 ações podem manter ícones no header via EditorHeaderActions.