# StatGrid

> Una grilla responsive de indicadores: un `Stat` dentro de una `Card` cada uno, con esqueleto de carga del alto final.

```tsx
import { StatGrid } from "sebs7n-ui/stat-grid"
```

Sin `"use client"`: sirve en un Server Component.

## Ejemplos

### Cuatro indicadores

1 columna en el teléfono, 2 en tablet y 4 en escritorio. Cada uno es un `Stat` en una `Card`.

```tsx
import { StatGrid } from "sebs7n-ui/stat-grid"

function Four() {
  return <StatGrid className="w-full" items={ITEMS} />
}
```

### Cargando

Los rótulos quedan y las cifras pasan a esqueleto del alto final: la card no cambia de alto al llegar el dato.

```tsx
import { Button } from "sebs7n-ui/button"
import { StatGrid } from "sebs7n-ui/stat-grid"
import { useState } from "react"

function Loading() {
  const [loading, setLoading] = useState(true)
  return (
    <div className="flex w-full flex-col gap-3">
      <div>
        <Button onClick={() => setLoading((value) => !value)} size="sm" variant="secondary">
          {loading ? "Mostrar datos" : "Volver a cargar"}
        </Button>
      </div>
      <StatGrid items={ITEMS.slice(0, 3)} loading={loading} />
    </div>
  )
}
```

## Props

### StatGrid

Hereda las props de `<div>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `items` * | `readonly StatGridItem[]` | — | Los indicadores, en orden: `{ id?, label, value, aside?, badge?, delta?, trend?, hint?, chart?, actions? }`. |
| `chartLayout` | `"bleed" \| "inset"` | `"bleed"` | Dónde se apoya el gráfico de cada indicador (`chart`). `bleed` (default): pegado a los bordes de la card, a lo ancho y hasta abajo, que la card recorta con su radio, como las cards de analítica. `inset`: adentro del padding de la card, con aire alrededor. |
| `columns` | `1 \| 2 \| 3 \| 4` | — | Cuántos a lo ancho como máximo en escritorio. Por defecto sale de la cantidad, para no dejar huérfanos: 1 → 1, 2 → 2, 3 → 3, 4 → 4 (2 en tablet), 5 y 6 → 3 (2 en tablet), más → 4. |
| `labels` | `Partial<StatGridLabels>` | — | Textos internos (español por defecto: `statGridLabels`). |
| `loading` | `boolean` | `false` | Cargando: los rótulos quedan y las cifras pasan a esqueleto del alto final, así la card no cambia de alto al llegar. |
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

`*` obligatoria.

## Teclado

| Tecla | Qué hace |
|---|---|
| Tab | Con `actions`, llega al botón «…» de cada card; el gráfico (`MetricChart`) es otra parada. |
| Enter · Espacio · ↓ | Abren el menú de la card; las flechas lo recorren y Escape lo cierra. |

## Accesibilidad

- Cada indicador es un `Stat` en una `Card`: la variación se lee junto al número y el verde y el rojo llegan a contraste sobre el cuerpo de la card. Una etiqueta de estado lleva texto («Al día»).
- Con `loading` la región queda `aria-busy`, los rótulos siguen a la vista y el botón «…» se deshabilita.
- El botón «…» se llama «Opciones de {rótulo}» (`labels.actions`). Un `Sparkline` en `chart` se oculta solo; un `MetricChart` es una imagen con nombre y tabla.
- Sin estado ni `"use client"` propio: sirve en un Server Component (el menú es un cliente aparte).

## Reglas de uso

- Responde al ancho de la grilla (container queries), no al de la ventana: 1 columna por debajo de 32 rem, 2 desde ahí y hasta 4 desde 56 rem (3 ítems → 1 columna y 3 desde 48 rem, sin pasar por 2 + 1). Por defecto la cantidad sale de los ítems y evita huérfanos; `columns` fija el máximo. Con un panel lateral abierto se ve como en una pantalla chica.
- Con `loading`, los rótulos quedan y las cifras pasan a esqueleto del alto final: la card no cambia de alto al llegar el dato.
- Cada ítem: `{ id?, label, value, aside?, badge?, delta?, trend?, hint?, chart?, actions? }`. Para una sola cifra suelta, `Stat`.
- Estilo consola de analítica: `chart={<MetricChart … />}` ocupa el ancho y el alto que sobran de la card (con `chartLayout="bleed"`, hasta los bordes), y la variación pasa junto a la cifra. `actions` son los ítems de un `DropdownMenu` (Ver detalle, Actualizar, `DropdownMenuSub` de Período, Quitar): la grilla pone el botón «…» arriba a la derecha.

## Relacionados

[stat](/docs/components/stat.md) · [card](/docs/components/card.md) · [skeleton](/docs/components/skeleton.md) · [metric-chart](/docs/components/metric-chart.md) · [sparkline](/docs/components/sparkline.md) · [dropdown-menu](/docs/components/dropdown-menu.md)
