Fix: Actualizar implementación de UTabs a Nuxt UI v4
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s

- Cambiar selectedTab de ref(0) a ref('lotes') para usar string
- Agregar propiedad value explícita a cada tab item
- Crear documento nuxt-ui-tips.md con documentación de cambios
- Los valores deben ser strings según API de v4
This commit is contained in:
2025-11-21 20:44:04 -06:00
parent d9ea2fb18d
commit 6f713a5ed1
2 changed files with 176 additions and 3 deletions

173
nuxt-ui-tips.md Normal file
View File

@@ -0,0 +1,173 @@
# 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

View File

@@ -174,10 +174,10 @@ import type { Lote, Operacion } from '~/composables/useLotes'
const { isAuthenticated } = useAuthentik() const { isAuthenticated } = useAuthentik()
// Navegación // Navegación
const selectedTab = ref(0) const selectedTab = ref('lotes')
const tabs = [ const tabs = [
{ label: 'Lotes', icon: 'i-heroicons-cube', slot: 'lotes' }, { label: 'Lotes', icon: 'i-heroicons-cube', slot: 'lotes', value: 'lotes' },
{ label: 'Operaciones', icon: 'i-heroicons-beaker', slot: 'operaciones' }, { label: 'Operaciones', icon: 'i-heroicons-beaker', slot: 'operaciones', value: 'operaciones' },
] ]
// Estados de modales // Estados de modales