npm package: @foxbit-group/caelum
Description: Foxbit UI component library built on shadcn/ui
Latest version: 0.5.0

# Caelum

Biblioteca de componentes UI da Foxbit construida sobre [shadcn/ui](https://ui.shadcn.com/). Serve como **fonte unica da verdade** para todos os componentes de interface nos projetos da Foxbit.

## Por que o Caelum existe?

```mermaid
graph LR
    subgraph ANTES["Antes"]
        A1[Projeto A] -->|shadcn local| C1[components/ui/button]
        A1 -->|shadcn local| C2[components/ui/dialog]
        B1[Projeto B] -->|shadcn local| C3[components/ui/button]
        B1 -->|shadcn local| C4[components/ui/dialog]
        D1[Projeto C] -->|shadcn local| C5[components/ui/button]
        D1 -->|shadcn local| C6[components/ui/dialog]
    end

    subgraph DEPOIS["Depois"]
        A2[Projeto A] -->|import| PKG["@foxbit-group/caelum"]
        B2[Projeto B] -->|import| PKG
        D2[Projeto C] -->|import| PKG
    end

    style ANTES fill:#1b1b1b,stroke:#f23a46,color:#f2f2f2
    style DEPOIS fill:#1b1b1b,stroke:#02c070,color:#f2f2f2
    style PKG fill:#ff6e00,stroke:#ff6e00,color:#ffffff
```

**Problemas que resolve:**

- Componentes shadcn duplicados e divergentes entre projetos
- Estilos inconsistentes entre diferentes aplicacoes
- Dificuldade para atualizar ou trocar a lib de componentes
- Dependencia do shadcn espalhada em multiplos repositorios

**Beneficios:**

- Uma unica fonte da verdade para componentes UI
- Tema Foxbit (light/dark) pre-configurado com tokens Norma
- Troca de lib facilitada: altera internals do Caelum, mantem assinaturas
- Versionamento: consumers pinnam versao e atualizam quando quiserem

---

## Instalacao

```bash
pnpm add @foxbit-group/caelum
```

---

## Setup no projeto consumer

```mermaid
flowchart TD
    A["pnpm add @foxbit-group/caelum"] --> B{Qual framework?}
    B -->|Next.js| C["Importar CSS no layout.tsx"]
    B -->|Vite + React| D["Importar CSS no main.tsx"]
    C --> E["import '@foxbit-group/caelum/styles.css'"]
    D --> E
    E --> F["Usar componentes"]
    F --> G["import { Button } from '@foxbit-group/caelum'"]

    style A fill:#ff6e00,stroke:#ff6e00,color:#fff
    style G fill:#02c070,stroke:#02c070,color:#fff
```

### Next.js

```tsx
// app/layout.tsx
import '@foxbit-group/caelum/styles.css'
import './globals.css' // seus estilos locais (se houver)

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="pt-BR">
      <body>{children}</body>
    </html>
  )
}
```

### Vite + React

```tsx
// src/main.tsx
import '@foxbit-group/caelum/styles.css'
import './index.css' // seus estilos locais (se houver)

import { createRoot } from 'react-dom/client'
import { App } from './App'

createRoot(document.getElementById('root')!).render(<App />)
```

### Usar componentes

```tsx
import { Button, Card, CardHeader, CardTitle, CardContent, Input, Dialog } from '@foxbit-group/caelum'

export function LoginForm() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Entrar</CardTitle>
      </CardHeader>
      <CardContent className="space-y-4">
        <Input placeholder="Email" type="email" />
        <Input placeholder="Senha" type="password" />
        <Button className="w-full">Entrar</Button>
      </CardContent>
    </Card>
  )
}
```

---

## Tema e Dark Mode

O Caelum vem com o tema Foxbit pre-configurado, mapeado a partir dos tokens do design system Norma.

```mermaid
flowchart LR
    subgraph Norma["Design System Norma"]
        NT1["foxbit-exchange-light.css"]
        NT2["foxbit-exchange-dark.css"]
    end

    subgraph Caelum["Caelum Theme Layer"]
        CT["theme.css"]
    end

    subgraph ShadcnVars["Variaveis shadcn/ui"]
        V1["--color-primary"]
        V2["--color-background"]
        V3["--color-destructive"]
        V4["..."]
    end

    NT1 --> CT
    NT2 --> CT
    CT --> V1
    CT --> V2
    CT --> V3
    CT --> V4

    style Norma fill:#303030,stroke:#9c9c9c,color:#f2f2f2
    style Caelum fill:#ff6e00,stroke:#ff6e00,color:#fff
    style ShadcnVars fill:#252525,stroke:#464646,color:#f2f2f2
```

### Ativar dark mode

O tema dark e ativado pela classe `.dark` no `<html>` ou pelo atributo `[data-theme="dark"]` (compativel com o padrao existente da plataforma).

**Com next-themes (Next.js):**

```tsx
import { ThemeProvider } from 'next-themes'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="pt-BR" suppressHydrationWarning>
      <body>
        <ThemeProvider attribute="class" defaultTheme="dark">
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
```

**Com data-theme (compativel com plataforma existente):**

```html
<html data-theme="dark">
```

### Paleta de cores

| Token | Light | Dark | Uso |
|-------|-------|------|-----|
| `primary` | `#ff6e00` | `#ff6e00` | Botoes principais, links, foco |
| `background` | `#ffffff` | `#1b1b1b` | Fundo da pagina |
| `foreground` | `#212529` | `#f2f2f2` | Texto principal |
| `card` | `#f7f7f7` | `#252525` | Fundo de cards |
| `muted` | `#f7f7f7` | `#303030` | Fundos secundarios |
| `muted-foreground` | `#737e88` | `#9c9c9c` | Texto secundario |
| `destructive` | `#ff4747` | `#f23a46` | Erros, acoes destrutivas |
| `border` | `#ececec` | `#303030` | Bordas |
| `input` | `#d9d9d9` | `#464646` | Borda de inputs |
| `ring` | `#ff6e00` | `#ff6e00` | Anel de foco |

### Sobrescrever tokens

Voce pode sobrescrever qualquer token no CSS do projeto consumer:

```css
:root {
  --caelum-primary: #your-color;
  --caelum-radius: 0.75rem;
}
```

---

## Componentes disponiveis

Todos os 37 componentes do shadcn/ui estao incluidos:

| Categoria | Componentes |
|-----------|-------------|
| **Layout** | AspectRatio, Card, Resizable, ScrollArea, Separator |
| **Formularios** | Button, Checkbox, Form, Input, InputOTP, Label, RadioGroup, Select, Slider, Switch, Textarea |
| **Data Display** | Avatar, Badge, Calendar, Table, Progress, Skeleton |
| **Feedback** | Alert, AlertDialog, Dialog, Drawer, Sheet, Toast, Sonner, Tooltip |
| **Navegacao** | Breadcrumb, Command, ContextMenu, DropdownMenu, HoverCard, Menubar, NavigationMenu, Pagination, Popover, Tabs |
| **Outros** | Accordion, Carousel, Collapsible, Toggle, ToggleGroup |

### Hooks

| Hook | Descricao |
|------|-----------|
| `useToast` | Gerenciar toasts programaticamente |
| `useIsMobile` | Detectar breakpoint mobile (< 768px) |

### Utilitarios

| Utilitario | Descricao |
|------------|-----------|
| `cn()` | Merge de classes Tailwind (clsx + tailwind-merge) |

---

## Arquitetura

```mermaid
graph TD
    subgraph Caelum["@foxbit-group/caelum"]
        direction TB
        INDEX["src/index.ts<br/>Barrel export"] --> COMPONENTS
        INDEX --> HOOKS
        INDEX --> UTILS

        subgraph COMPONENTS["components/ui/"]
            B["Button"]
            D["Dialog"]
            I["Input"]
            MORE["... +34 componentes"]
        end

        subgraph HOOKS["hooks/"]
            UT["useToast"]
            UM["useIsMobile"]
        end

        subgraph UTILS["lib/"]
            CN["cn()"]
        end

        STYLES["styles/globals.css"] --> THEME["styles/theme.css"]
        THEME --> LIGHT[":root (light)"]
        THEME --> DARK[".dark (dark)"]
    end

    subgraph BUILD["Build Output (dist/)"]
        JS["index.js (ESM)"]
        CJS["index.cjs (CJS)"]
        DTS["index.d.ts"]
        CSS["styles.css"]
    end

    INDEX -->|tsup| JS
    INDEX -->|tsup| CJS
    INDEX -->|tsup| DTS
    STYLES -->|tailwindcss| CSS

    subgraph CONSUMERS["Projetos Consumer"]
        NEXT["Next.js App"]
        VITE["Vite App"]
    end

    JS --> NEXT
    JS --> VITE
    CSS --> NEXT
    CSS --> VITE

    style Caelum fill:#1b1b1b,stroke:#ff6e00,color:#f2f2f2
    style BUILD fill:#252525,stroke:#464646,color:#f2f2f2
    style CONSUMERS fill:#252525,stroke:#02c070,color:#f2f2f2
```

### Estrutura de arquivos

```
caelum/
├── src/
│   ├── components/
│   │   └── ui/                # 37 componentes shadcn/ui
│   │       ├── accordion.tsx
│   │       ├── alert.tsx
│   │       ├── alert-dialog.tsx
│   │       ├── button.tsx
│   │       ├── ...
│   │       └── tooltip.tsx
│   ├── hooks/
│   │   ├── use-toast.ts
│   │   └── use-mobile.ts
│   ├── lib/
│   │   └── utils.ts           # cn()
│   ├── styles/
│   │   ├── globals.css        # Entry CSS (Tailwind v4)
│   │   └── theme.css          # Tokens Foxbit light/dark
│   └── index.ts               # Barrel export
├── dist/                      # Build output
│   ├── index.js               # ESM (~103KB)
│   ├── index.cjs              # CJS (~121KB)
│   ├── index.d.ts             # TypeScript types
│   └── styles.css             # CSS compilado (~47KB)
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── .npmrc
├── .nvmrc
└── .gitignore
```

---

## Desenvolvimento

### Pre-requisitos

- Node.js >= 20 (ver `.nvmrc`)
- pnpm

### Comandos

```bash
# Instalar dependencias
pnpm install

# Build completo (JS + Types)
pnpm build

# Build CSS
pnpm build:css

# Watch mode (JS apenas)
pnpm dev

# Type check
pnpm typecheck
```

### Adicionar um novo componente

```mermaid
flowchart TD
    A["Criar arquivo em<br/>src/components/ui/novo.tsx"] --> B["Implementar componente<br/>seguindo padrao shadcn"]
    B --> C["Exportar em<br/>src/index.ts"]
    C --> D["pnpm build && pnpm build:css"]
    D --> E["Publicar nova versao"]

    style A fill:#303030,stroke:#9c9c9c,color:#f2f2f2
    style E fill:#02c070,stroke:#02c070,color:#fff
```

1. Crie o componente em `src/components/ui/novo-componente.tsx`
2. Adicione o export em `src/index.ts`
3. Rode `pnpm build` para validar
4. Publique uma nova versao

---

## Publicacao

### npmjs.com (CI automatizado)

A publicacao e feita automaticamente via GitHub Actions quando uma tag `v*` e criada.

```mermaid
sequenceDiagram
    participant Dev as Desenvolvedor
    participant GH as GitHub
    participant CI as GitHub Actions
    participant NPM as npmjs.com

    Dev->>Dev: pnpm version patch/minor/major
    Dev->>GH: git push --follow-tags
    GH->>CI: Tag v* dispara workflow
    CI->>CI: pnpm install
    CI->>CI: pnpm typecheck && pnpm lint
    CI->>CI: pnpm build && pnpm build:css
    CI->>NPM: pnpm publish
    NPM-->>Dev: Pacote publicado

    Note over Dev,NPM: Consumers atualizam com<br/>pnpm update @foxbit-group/caelum
```

```bash
# Bump de versao (cria tag automaticamente)
# patch: 0.1.0 -> 0.1.1 (bugfix)
# minor: 0.1.0 -> 0.2.0 (novo componente)
# major: 0.1.0 -> 1.0.0 (breaking change)
pnpm version patch  # ou minor, major

# Push com a tag — CI publica automaticamente
git push --follow-tags
```

---

## Fluxo de migracao de um projeto existente

Para projetos que ja usam shadcn/ui localmente:

```mermaid
flowchart TD
    A["1. Instalar @foxbit-group/caelum"] --> B["2. Importar styles.css no root"]
    B --> C["3. Trocar imports locais"]
    C --> D["4. Remover components/ui/ local"]
    D --> E["5. Remover dependencias shadcn<br/>do package.json"]
    E --> F["6. Testar tudo"]

    C -.->|Antes| C1["import { Button } from '@/components/ui/button'"]
    C -.->|Depois| C2["import { Button } from '@foxbit-group/caelum'"]

    style A fill:#ff6e00,stroke:#ff6e00,color:#fff
    style F fill:#02c070,stroke:#02c070,color:#fff
    style C1 fill:#493a3c,stroke:#f23a46,color:#f2f2f2
    style C2 fill:#354743,stroke:#02c070,color:#f2f2f2
```

### Checklist de migracao

- [ ] Instalar `@foxbit-group/caelum`
- [ ] Adicionar `import '@foxbit-group/caelum/styles.css'` no entry point
- [ ] Buscar e substituir todos os imports de `@/components/ui/` para `@foxbit-group/caelum`
- [ ] Remover pasta `components/ui/` local
- [ ] Remover `@radix-ui/*`, `class-variance-authority`, `cmdk`, `vaul`, etc. do `package.json`
- [ ] Remover `components.json` (config do shadcn CLI)
- [ ] Rodar testes e validar visualmente

---

## Stack tecnica

| Tecnologia | Versao | Uso |
|------------|--------|-----|
| [Tailwind CSS](https://tailwindcss.com/) | v4 | Estilizacao |
| [shadcn/ui](https://ui.shadcn.com/) | latest | Base dos componentes |
| [Radix UI](https://www.radix-ui.com/) | latest | Primitivos acessiveis |
| [tsup](https://tsup.egoist.dev/) | v8 | Bundler (ESM + CJS + DTS) |
| [TypeScript](https://www.typescriptlang.org/) | v5 | Tipagem |
| [class-variance-authority](https://cva.style/) | v0.7 | Variantes de componentes |
| [tailwind-merge](https://github.com/dcastil/tailwind-merge) | v3 | Merge inteligente de classes |
| [Lucide](https://lucide.dev/) | latest | Icones |

---

## FAQ

**Posso usar classes Tailwind nos componentes do Caelum?**

Sim. Todos os componentes aceitam `className` e o merge e feito via `cn()` (tailwind-merge). O CSS ja vem compilado no `styles.css`, entao as classes dos componentes funcionam sem configuracao extra no consumer. Para classes Tailwind customizadas no seu projeto, voce ainda precisa do seu proprio setup de Tailwind.

**E se eu precisar de um componente que nao existe no Caelum?**

Crie-o localmente no seu projeto. Quando fizer sentido compartilhar, abra um PR no Caelum para adiciona-lo.

**O Caelum funciona com Server Components (RSC)?**

Sim. Componentes que usam hooks ou event handlers tem a diretiva `"use client"` incluida automaticamente no bundle. Componentes puramente visuais (Card, Badge, Table, etc.) funcionam como Server Components.

**Como atualizar o Caelum no meu projeto?**

```bash
pnpm update @foxbit-group/caelum
```

**Posso customizar um componente especifico sem mexer no Caelum?**

Sim. Use `className` para sobrescrever estilos, ou encapsule o componente do Caelum em um wrapper local com a customizacao necessaria.