npm package: @roax/ui
Description: Roax UI Component Library — componentes reutilizables para proyectos Roax
Latest version: 0.4.0

# @roax/ui

Librería de componentes UI de Roax — construida sobre React 18, CoreUI Pro y Recharts. Lista para consumir desde cualquier plataforma React/Next.js.

---

## Instalación

```bash
npm install @roax/ui
```

### Peer dependencies requeridas

```bash
npm install @coreui/react-pro @coreui/icons-react @coreui/icons @tippyjs/react lucide-react recharts react react-dom
```

---

## Uso

```jsx
import { SolidButton, GeneralCard, FunnelChart } from '@roax/ui'
```

---

## Storybook (documentación visual)

El Storybook del design system vive en este monorepo (no se publica dentro del paquete npm).

Scripts disponibles desde la raíz del proyecto:

```bash
npm run storybook
npm run build-storybook
```

Importante:
- El preview de Storybook ya incluye `@roax/ui/styles`.
- Ya está configurado con toolbar de tema `Light / Dark`.
- Al cambiar el tema, se aplica `data-coreui-theme="dark"` para validar estilos reales en modo oscuro.

Si consumes `@roax/ui` desde otro frontend, debes importar los estilos del paquete en tu app para tener el mismo comportamiento visual.

### Estilos (colores y tokens CSS)

Importa los design tokens en tu archivo SCSS global **después** de CoreUI:

```scss
@import '@coreui/coreui-pro/scss/coreui';
@import '@roax/ui/styles';
```

O directamente el archivo de colores:

```scss
@import '@roax/ui/styles/roax-colors';
```

Esto expone todas las variables CSS `--roax-*` en tu proyecto.

### Tokens de charts (dark/light)

El paquete expone tokens para mejorar contraste en gráficas según tema:

- `--roax-chart-axis-color`
- `--roax-chart-grid-color`
- `--roax-chart-series-primary`
- `--roax-chart-series-secondary`
- `--roax-chart-series-tertiary`

Puedes sobreescribirlos en tu app si necesitas branding específico.

---

## Componentes

### Buttons

| Componente | Descripción |
|---|---|
| `SolidButton` | Botón primario con soporte de loading, icono y colores CoreUI |
| `OutlineButton` | Botón con borde, mismas opciones que SolidButton |
| `TextButton` | Botón ghost sin fondo |
| `IconButton` | Botón de ícono circular con tooltip integrado |

```jsx
import { SolidButton, OutlineButton, TextButton, IconButton } from '@roax/ui'
import { cilTrash } from '@coreui/icons'

<SolidButton title="Guardar" onClick={handleSave} />
<OutlineButton title="Cancelar" color="secondary" />
<TextButton>Ver detalle</TextButton>
<IconButton icon={cilTrash} tooltip="Eliminar" color="danger" />
```

---

### Cards

| Componente | Descripción |
|---|---|
| `GeneralCard` | Tarjeta de métrica con valor actual, anterior, variación % y tooltip |
| `MetricCard` | Tarjeta glassmorphism para KPIs de alto nivel |

```jsx
import { GeneralCard } from '@roax/ui'

<GeneralCard
  title="Ventas totales"
  current={15420000}
  previous={12300000}
  change={25.4}
  isPositive={true}
  unit="COP"
  previousDateRange="2024-03-01 - 2024-03-31"
  tooltipText="Total de ventas brutas del período."
/>
```

**Unidades soportadas:** `'COP'` · `'%'` · `'x'` · `''` (número genérico)

#### Card Surface Preset (frontend-platform)

Para cards de contenedor y estados de integración, el preset recomendado es:

```jsx
<CCard className="border-0 rounded-4 shadow-lg">
  <CCardBody className="p-3">...</CCardBody>
</CCard>
```

Guía rápida de clases:

| Clase | Uso |
|---|---|
| `border-0` | Elimina borde por defecto para un look más limpio |
| `rounded-4` | Radio estándar del sistema para cards |
| `p-3` | Espaciado interno base |
| `shadow-lg` | Elevación principal de cards |

Nota: `GeneralCard` y `MetricCard` usan variante glass con borde visual intencional desde su SCSS.

#### Defaults y consideraciones (bordes y superficie)

| Elemento | Default recomendado | Mantener por defecto | Cambiar solo si |
|---|---|---|---|
| Border | `border-0` | Cards de contenedor y cards de integración | Necesitas variante visual explícita (glass, estado especial, highlight) |
| Radius | `rounded-4` | Layout general del dashboard | La UI del módulo pida un radio diferente |
| Padding | `p-3` | Cards compactas y listas | El contenido necesita más aire (`p-4`) |
| Shadow | `shadow-lg` | Cards primarias | Hay saturación visual y se requiere menor elevación |

Regla recomendada: iniciar con `border-0 rounded-4 p-3 shadow-lg` y ajustar de forma mínima.

---

### Inputs (tema frontend-platform)

Patrones de input a documentar y mantener en Storybook:

- Sin logo/ícono
- Con logo/ícono a la izquierda
- Con dropdown (label + valor seleccionable)

Preset visual recomendado para superficie:

```jsx
<CInputGroup style={{ borderRadius: 14, border: '1px solid #cfd4dc', background: '#f8f9fa' }}>
  <CInputGroupText className="border-0">...</CInputGroupText>
  <CFormInput className="border-0" />
</CInputGroup>
```

Defaults y consideraciones de borde:

| Elemento | Default recomendado | Mantener por defecto | Cambiar solo si |
|---|---|---|---|
| Borde externo | `1px solid #cfd4dc` | Inputs estándar de formularios | El módulo define una jerarquía especial (warning/success) |
| Borde interno (input/select) | `border-0` | Inputs dentro de superficie compuesta | El input es standalone y requiere contorno propio |
| Radius | `14px` | Inputs principales del dashboard | El contexto exige radios distintos |
| Prefix separator | `border-right: 1px solid #cfd4dc` | Variantes con logo/ícono | El diseño sea minimal sin separación |

Referencia visual: story `Roax/Inputs/Input Theme`.

---

### Caligrafía / Typography

`@roax/ui/styles` incluye tokens y utilidades tipográficas:

| Token / Clase | Uso recomendado |
|---|---|
| `--roax-font-family-base` | Texto general de UI |
| `--roax-font-family-heading` | Títulos y encabezados |
| `roax-type-display` | KPIs o encabezados de alto impacto |
| `roax-type-h1`, `roax-type-h2`, `roax-type-h3` | Jerarquía de títulos |
| `roax-type-body` | Texto operativo principal |
| `roax-type-caption` | Metadata y texto secundario |

```jsx
<h2 className="roax-type-h2">Resumen general</h2>
<p className="roax-type-body">Texto base de la pantalla.</p>
<span className="roax-type-caption">Actualizado hace 2 minutos</span>
```

Referencia visual: story `Roax/Foundations/Typography`.

---

### Charts

| Componente | Descripción |
|---|---|
| `FunnelChart` | Embudo horizontal con tarjetas de métricas |
| `TimeSeriesComparisonChart` | Gráfico de líneas para comparar series de tiempo |
| `TopProductsChart` | Ranking horizontal de productos más vendidos |
| `SalesByChannelChart` | Barras apiladas por canal (Meta, TikTok, Google) |
| `InvestmentByPlatformChart` | Gráfico de dona para inversión por plataforma |

```jsx
import { FunnelChart, TimeSeriesComparisonChart } from '@roax/ui'

// FunnelChart — solo el gráfico, sin cards
<FunnelChart
  data={[
    { label: 'Impressions', value: 120000 },
    { label: 'Clicks',      value: 8400 },
    { label: 'Purchases',   value: 630, unit: 'COP', color: '#5B01D2' },
  ]}
  gradientStart="#FF8AAE"
  gradientEnd="#FF1F3D"
/>

// TimeSeriesComparisonChart — genérico, cualquier clave de datos
<TimeSeriesComparisonChart
  data={[{ date: '2024-05-01', sales: 800000, adSpend: 200000 }]}
  lines={['sales', 'adSpend']}
  colors={{ sales: '#FF2F86', adSpend: '#5B01D2' }}
  currency="COP"
  yAxisLabel="COP"
  displayNames={{ sales: 'Sales', adSpend: 'Ad Spend' }}
  xDataKey="date"
  height={340}
/>

<InvestmentByPlatformChart
  data={[{ name: 'Meta', value: 4500000 }, { name: 'Google', value: 2500000 }]}
  title="Investment by Platform"
  currencySymbol="USD"
  locale="en-US"
/>
```

---

### Overlay

| Componente | Descripción |
|---|---|
| `Modal` | Modal con título, footer y botón de cierre |
| `CustomTooltip` | Wrapper de Tippy.js, funciona sobre cualquier elemento |

```jsx
import { Modal, CustomTooltip, SolidButton } from '@roax/ui'

<Modal
  visible={open}
  onClose={() => setOpen(false)}
  title="Confirmar acción"
  footer={<SolidButton title="Confirmar" onClick={() => setOpen(false)} />}
>
  <p>¿Estás seguro de continuar?</p>
</Modal>

<CustomTooltip content="Más información" placement="top">
  <span>Hover aquí</span>
</CustomTooltip>
```

---

### Pagination

| Componente | Descripción |
|---|---|
| `PaginatedTable` | Tabla con paginación y estado de loading |
| `PaginatedGrid` | Grid de cards con paginación |

```jsx
import { PaginatedTable } from '@roax/ui'
import { CTableRow, CTableDataCell } from '@coreui/react-pro'

<PaginatedTable
  data={rows}
  columns={['#', 'Nombre', 'Estado']}
  itemsPerPage={10}
  currentPage={page}
  setCurrentPage={setPage}
  renderRow={(row) => (
    <CTableRow key={row.id}>
      <CTableDataCell>{row.id}</CTableDataCell>
      <CTableDataCell>{row.name}</CTableDataCell>
    </CTableRow>
  )}
  emptyMessage="No se encontraron registros."
/>
```

---

### Skeletons

| Componente | Descripción |
|---|---|
| `CardSkeleton` | Placeholder de tarjeta |
| `TextSkeleton` | Placeholder de línea de texto |
| `MetricsSkeleton` | Placeholder de métrica |
| `ReportTableSkeleton` | Placeholder de tabla de reporte |
| `SummaryReportSkeleton` | Grid de placeholders para reportes de resumen |

```jsx
import { MetricsSkeleton, SummaryReportSkeleton } from '@roax/ui'

{loading ? <MetricsSkeleton /> : <GeneralCard {...props} />}

<SummaryReportSkeleton
  layout={[
    { sm: 6, md: 4 },
    { sm: 6, md: 4 },
    { sm: 6, md: 4 },
  ]}
/>
```

---

### Feedback

| Componente | Descripción |
|---|---|
| `NoDataMessage` | Alerta de advertencia cuando no hay datos disponibles |
| `WhatsappFloatingWidget` | Botón flotante de soporte WhatsApp configurable por ruta |

```jsx
import { NoDataMessage } from '@roax/ui'

<NoDataMessage message="No hay ventas para el período seleccionado." />

import { WhatsappFloatingWidget } from '@roax/ui'

<WhatsappFloatingWidget
  enabled={true}
  pathname="/dashboard"
  hiddenPrefixes={['/private/integrations/connect/meta']}
  phone="+573106779028"
  message="¡Hola! Necesito ayuda en la plataforma."
/>
```

---

### Navigation

| Componente | Descripción |
|---|---|
| `BackButton` | Botón de regreso agnóstico a framework (usa `onNavigate`, `onBack` o `window.history`) |

```jsx
import { BackButton } from '@roax/ui'

<BackButton title="Volver al listado" path="/dashboard" />

// Integración opcional con Next.js Router
<BackButton title="Volver" path="/dashboard" onNavigate={(target) => router.push(target)} />
```

---

## Design Tokens — Colores

Todas las variables están disponibles como CSS custom properties después de importar `@roax/ui/styles`.

| Escala | Variable principal | Hex |
|---|---|---|
| Rosa | `--roax-rosa-400` | `#ED1E78` |
| Naranja | `--roax-orange-400` | `#F05A24` |
| Morado | `--roax-purple-400` | `#5B01D2` |
| Neutral | `--roax-neutral-500` | `#071324` |
| Success | `--roax-success-400` | `#34C38F` |
| Warning | `--roax-warning-400` | `#FFCE33` |
| Error | `--roax-error-400` | `#FF0505` |
| Info | `--roax-info-400` | `#33A7FF` |

Cada escala va de `50` (más claro) a `900` (más oscuro).

---

## Utilidades

```jsx
import { formatValue, getBadgeStyles, formatDateRange } from '@roax/ui'

formatValue(15420000, 'COP')   // → 'COP 15.420.000'
formatValue(3.75, '%')          // → '3.75%'
formatValue(4.2, 'x')           // → 'x 4.20'

getBadgeStyles(true)   // → { backgroundColor: '#55ed7b', color: '#0b3e26', ... }
getBadgeStyles(false)  // → { backgroundColor: '#f74a4a', color: '#842029', ... }

formatDateRange('2024-03-01 - 2024-03-31')
// → { formattedRange: 'mar 01,24 - mar 31,24' }
```

---

## Storybook

Todos los componentes están documentados en Storybook con variantes interactivas y design tokens de color.

---

## Licencia

MIT © Roax SAS