# Nuxt UI v4 - Tips y Cambios de API

Este documento contiene los cambios más comunes al migrar o trabajar con Nuxt UI v4, basado en la experiencia práctica del proyecto.

## UModal - Componente Modal

### Cambios de API en v4

#### 1. v-model actualizado a v-model:open

**❌ Incorrecto (API antigua):**
```vue
<UModal v-model="showModal">
  <!-- contenido -->
</UModal>
```

**✅ Correcto (Nuxt UI v4):**
```vue
<UModal v-model:open="showModal">
  <!-- contenido -->
</UModal>
```

#### 2. Slot #content requerido

En v4, el contenido debe ir dentro del slot `#content`.

**❌ Incorrecto:**
```vue
<UModal v-model:open="showModal">
  <MiComponente />
</UModal>
```

**✅ Correcto:**
```vue
<UModal v-model:open="showModal">
  <template #content>
    <MiComponente />
  </template>
</UModal>
```

#### 3. Prop :ui para personalización

La prop `:ui` no tiene un slot `width`. Para personalizar el ancho, debes usar el slot `content`.

**❌ Incorrecto:**
```vue
<UModal
  v-model:open="showModal"
  :ui="{ width: 'max-w-4xl' }"
>
  <!-- contenido -->
</UModal>
```

**✅ Correcto:**
```vue
<UModal
  v-model:open="showModal"
  :ui="{ content: 'w-[calc(100vw-2rem)] max-w-4xl rounded-lg shadow-lg ring ring-default' }"
>
  <template #content>
    <!-- contenido -->
  </template>
</UModal>
```

**Nota:** Las clases del tema por defecto son:
- `w-[calc(100vw-2rem)]` - ancho responsive
- `rounded-lg` - bordes redondeados
- `shadow-lg` - sombra
- `ring ring-default` - borde/anillo

Luego agregas tu clase de ancho máximo personalizado: `max-w-3xl`, `max-w-4xl`, etc.

### Slots disponibles en UModal

Según la documentación oficial de Nuxt UI v4:

```typescript
interface ModalSlots {
  default(): any;      // Elemento trigger (opcional)
  content(): any;      // Contenido completo del modal
  header(): any;       // Solo el header
  title(): any;        // Solo el título
  description(): any;  // Solo la descripción
  actions(): any;      // Acciones del header
  close(): any;        // Botón de cerrar
  body(): any;         // Solo el cuerpo
  footer(): any;       // Solo el footer
}
```

### Props importantes

```typescript
interface ModalProps {
  open?: boolean;              // Estado del modal (usar con v-model:open)
  defaultOpen?: boolean;       // Estado inicial
  modal?: boolean;             // Bloquea interacción fuera (default: true)
  overlay?: boolean;           // Mostrar overlay (default: true)
  dismissible?: boolean;       // Cerrar al hacer clic fuera (default: true)
  transition?: boolean;        // Animación (default: true)
  fullscreen?: boolean;        // Pantalla completa
  scrollable?: boolean;        // Contenido scrollable (v4.2+)
  title?: string;              // Título del modal
  description?: string;        // Descripción del modal
  close?: boolean | Partial<ButtonProps>;  // Customizar botón cerrar
}
```

### Ejemplo completo

```vue
<template>
  <!-- Modal básico con título y descripción -->
  <UModal
    v-model:open="showBasicModal"
    title="Crear Nuevo Lote"
    description="Complete el formulario para crear un lote"
  >
    <template #body>
      <LoteForm @submit="handleSubmit" />
    </template>

    <template #footer>
      <UButton @click="showBasicModal = false" variant="outline">
        Cancelar
      </UButton>
      <UButton @click="handleSubmit">
        Guardar
      </UButton>
    </template>
  </UModal>

  <!-- Modal con contenido personalizado y ancho custom -->
  <UModal
    v-model:open="showCustomModal"
    :ui="{ content: 'w-[calc(100vw-2rem)] max-w-4xl rounded-lg shadow-lg ring ring-default' }"
  >
    <template #content>
      <MiComponenteCustom />
    </template>
  </UModal>
</template>

<script setup lang="ts">
const showBasicModal = ref(false)
const showCustomModal = ref(false)

const handleSubmit = () => {
  // lógica
  showBasicModal.value = false
}
</script>
```

---

## Resumen de Cambios Comunes

| Componente | Cambio | Desde | Hacia |
|------------|--------|-------|-------|
| UModal | v-model | `v-model="show"` | `v-model:open="show"` |
| UModal | Contenido | Directo | `<template #content>` |
| UModal | Ancho custom | `:ui="{ width: 'max-w-4xl' }"` | `:ui="{ content: 'w-[calc(100vw-2rem)] max-w-4xl ...' }"` |

---

**Última actualización:** 2025-11-21
