Slideover
xph0000xUso
Use a Button or any other component in the default slot of the Slideover.
A continuación, utilice la ranura #content para añadir el contenido que se muestra cuando la diapositiva está abierta.
<template>
<USlideover>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="h-full m-4" />
</template>
</USlideover>
</template>También puede utilizar las ranuras #header, #body y #footer para personalizar el contenido de la diapositiva.
Nombre
Utilice el prop title para establecer el título de la cabecera de la diapositiva.
<template>
<USlideover title="Slideover with title">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Descripción
Utilice el prop description para establecer la descripción del encabezado de la diapositiva.
<template>
<USlideover
title="Slideover with description"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
>
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Close
Utilice el prop close para personalizar u ocultar el botón de cierre (con el valor false) que se muestra en el encabezado de la diapositiva.
Puede pasar cualquier propiedad del componente Button para personalizarlo.
<template>
<USlideover
title="Slideover with close button"
:close="{
color: 'primary',
variant: 'outline',
class: 'rounded-full'
}"
>
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>#content, ya que es parte del encabezado.Cerrar Icono
Use the close-icon prop to customize the close button Icon.
<template>
<USlideover title="Slideover with close button" close-icon="i-lucide-arrow-right">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Side (Edición)
Utilice el prop side para establecer el lado de la pantalla donde se deslizará la diapositiva de. Defaults a right.
<template>
<USlideover side="left" title="Slideover with side">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full min-h-48" />
</template>
</USlideover>
</template>Archivo de la etiqueta: badge{label="4.3+" class="align-text-top"}
Utilice el soporte inset para insertar el Slideover desde los bordes.
<template>
<USlideover side="right" inset title="Slideover with inset">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="min-w-96 min-h-96 size-full" />
</template>
</USlideover>
</template>Transición
Utilice el prop transition para controlar si la diapositiva está animada o no. Por defecto true.
<template>
<USlideover :transition="false" title="Slideover without transition">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Superpuesto
Utilice el prop overlay para controlar si el Slideover tiene una superposición o no. Por defecto true.
<template>
<USlideover :overlay="false" title="Slideover without overlay">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Modalidad
Utilice el prop modal para controlar si el Slideover bloquea la interacción con el contenido externo.
modal se establece en false, la superposición se deshabilita automáticamente y el contenido externo se vuelve interactivo.<template>
<USlideover :modal="false" title="Slideover interactive">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Desistible
Utilice el prop dismissible para controlar si el Slideover es descartable al hacer clic fuera de él o al presionar escape.
close:prevent cuando el usuario intente cerrarlo.modal: false con dismissible: false para hacer que el fondo de la diapositiva sea interactivo sin cerrarlo.<template>
<USlideover :dismissible="false" title="Slideover non-dismissible">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>Desmontar: badge{label="4.10+" class="align-text-top"}
Utilice el prop unmount-on-hide para evitar que el contenido de la diapositiva se desmonte cuando se cierra.
<template>
<USlideover :unmount-on-hide="false" title="Slideover">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>portal se establece en false, el contenido también se representa en el servidor. Esto es útil para representar una presentación de diapositivas abierta durante SSR sin un flash en la carga de la página, o para exponer su contenido para SEO.Ejemplos
Control estado abierto
Puede controlar el estado abierto usando la prop default-open o la directiva v-model:open.
<script setup lang="ts">
const open = ref(false)
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<USlideover v-model:open="open">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="h-full m-4" />
</template>
</USlideover>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<USlideover v-model:open="open">
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="h-full m-4" />
</template>
</USlideover>
</template>
defineShortcuts, puede alternar la diapositiva presionando: kbd{value="O"}.Uso programado
Puede usar el composable useOverlay para abrir una diapositiva de forma programática.
App que utiliza el componente OverlayProvider.En primer lugar, cree un componente de diapositiva que se abrirá mediante programación:
<script setup lang="ts">
defineProps<{
count: number
}>()
const emit = defineEmits<{ close: [boolean] }>()
</script>
<template>
<USlideover
:close="{ onClick: () => emit('close', false) }"
:description="`This slideover was opened programmatically ${count} times`"
>
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer>
<div class="flex gap-2">
<UButton color="neutral" label="Dismiss" @click="emit('close', false)" />
<UButton label="Success" @click="emit('close', true)" />
</div>
</template>
</USlideover>
</template>close cuando la diapositiva se cierra o se descarta aquí. Puede emitir cualquier dato a través del evento close, y esos datos se convierten en el valor resuelto de open().A continuación, utilízalo en tu app:
<script setup lang="ts">
import { LazySlideoverExample } from '#components'
const count = ref(0)
const toast = useToast()
const overlay = useOverlay()
const slideover = overlay.create(LazySlideoverExample)
async function open() {
const instance = slideover.open({
count: count.value
})
const shouldIncrement = await instance.result
if (shouldIncrement) {
count.value++
toast.add({
title: `Success: ${shouldIncrement}`,
color: 'success',
id: 'slideover-success'
})
// Update the count
slideover.patch({
count: count.value
})
return
}
toast.add({
title: `Dismissed: ${shouldIncrement}`,
color: 'error',
id: 'slideover-dismiss'
})
}
</script>
<template>
<UButton label="Open" color="neutral" variant="subtle" @click="open" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { LazySlideoverExample } from '#components'
const count = ref(0)
const toast = useToast()
const overlay = useOverlay()
const slideover = overlay.create(LazySlideoverExample)
async function open() {
const instance = slideover.open({
count: count.value
})
const shouldIncrement = await instance.result
if (shouldIncrement) {
count.value++
toast.add({
title: `Success: ${shouldIncrement}`,
color: 'success',
id: 'slideover-success'
})
// Update the count
slideover.patch({
count: count.value
})
return
}
toast.add({
title: `Dismissed: ${shouldIncrement}`,
color: 'error',
id: 'slideover-dismiss'
})
}
</script>
<template>
<UButton label="Open" color="neutral" variant="subtle" @click="open" />
</template>
emit('close').Anidados deslizamientos
Pueden anidar deslizamientos entre sí.
<script setup lang="ts">
const first = ref(false)
const second = ref(false)
</script>
<template>
<USlideover v-model:open="first" title="First slideover" :ui="{ footer: 'justify-end' }">
<UButton color="neutral" variant="subtle" label="Open" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer>
<UButton label="Close" color="neutral" variant="outline" @click="first = false" />
<USlideover v-model:open="second" title="Second slideover" :ui="{ footer: 'justify-end' }">
<UButton label="Open second" color="neutral" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer>
<UButton label="Close" color="neutral" variant="outline" @click="second = false" />
</template>
</USlideover>
</template>
</USlideover>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const first = ref(false)
const second = ref(false)
</script>
<template>
<USlideover v-model:open="first" title="First slideover" :ui="{ footer: 'justify-end' }">
<UButton color="neutral" variant="subtle" label="Open" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer>
<UButton label="Close" color="neutral" variant="outline" @click="first = false" />
<USlideover v-model:open="second" title="Second slideover" :ui="{ footer: 'justify-end' }">
<UButton label="Open second" color="neutral" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer>
<UButton label="Close" color="neutral" variant="outline" @click="second = false" />
</template>
</USlideover>
</template>
</USlideover>
</template>
Con ranura de pie
Utilice la ranura #footer para añadir contenido después del cuerpo de la diapositiva.
<script setup lang="ts">
const open = ref(false)
</script>
<template>
<USlideover v-model:open="open" title="Slideover with footer" description="This is useful when you want a form in a Slideover." :ui="{ footer: 'justify-end' }">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<UButton label="Submit" color="neutral" />
</template>
</USlideover>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<USlideover v-model:open="open" title="Slideover with footer" description="This is useful when you want a form in a Slideover." :ui="{ footer: 'justify-end' }">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<UButton label="Submit" color="neutral" />
</template>
</USlideover>
</template>
API (Edición española)
Props
| Prop | Default | Type |
|---|---|---|
title | string | |
description | string | |
content | DialogContentProps & Partial<EmitsToProps<DialogContentImplEmits>>The content of the slideover. | |
overlay | true | boolean Render an overlay behind the slideover. |
transition | true | boolean Animate the slideover when opening or closing. |
side | 'right' | "right" | "top" | "bottom" | "left"The side of the slideover. |
inset | false | boolean Whether to inset the slideover from the edges. |
portal | true | string | false | true | HTMLElementRender the slideover in a portal. |
close | true | boolean | Omit<ButtonProps, LinkPropsKeys> Display a close button to dismiss the slideover.
|
closeIcon | appConfig.ui.icons.close | anyThe icon displayed in the close button. |
dismissible | true | boolean When |
open | boolean The controlled open state of the dialog. Can be binded as | |
defaultOpen | boolean The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. | |
modal | true | boolean The modality of the dialog When set to |
unmountOnHide | true | boolean When set to |
ui | { overlay?: SlotClass; content?: SlotClass; header?: SlotClass; wrapper?: SlotClass; body?: SlotClass; footer?: SlotClass; title?: SlotClass; description?: SlotClass; close?: SlotClass; } |
Slots
| Slot | Type |
|---|---|
default | { open: boolean; } |
content | { close: () => void; } |
header | { close: () => void; } |
title | {} |
description | {} |
actions | {} |
close | { ui: object; } |
body | { close: () => void; } |
footer | { close: () => void; } |
Emisiones
| Event | Type |
|---|---|
leave | [] |
after:leave | [] |
enter | [] |
after:enter | [] |
close:prevent | [] |
update:open | [value: boolean] |
Temas
export default defineAppConfig({
ui: {
slideover: {
slots: {
overlay: 'fixed inset-0 bg-elevated/75',
content: 'fixed bg-default divide-y divide-default sm:ring ring-default sm:shadow-lg flex flex-col focus:outline-none',
header: 'flex items-center gap-1.5 p-4 sm:px-6 min-h-(--ui-header-height)',
wrapper: '',
body: 'flex-1 overflow-y-auto p-4 sm:p-6',
footer: 'flex items-center gap-1.5 p-4 sm:px-6',
title: 'text-highlighted font-semibold',
description: 'mt-1 text-muted text-sm',
close: 'absolute top-4 end-4'
},
variants: {
side: {
top: {
content: ''
},
right: {
content: 'max-w-md'
},
bottom: {
content: ''
},
left: {
content: 'max-w-md'
}
},
inset: {
true: {
content: 'rounded-lg'
}
},
transition: {
true: {
overlay: 'data-[state=open]:animate-[fade-in_200ms_var(--ease-out)] data-[state=closed]:animate-[fade-out_200ms_var(--ease-out)]'
}
}
},
compoundVariants: [
{
side: 'top',
inset: true,
class: {
content: 'max-h-[calc(100%-2rem)] inset-x-4 top-4'
}
},
{
side: 'top',
inset: false,
class: {
content: 'max-h-full inset-x-0 top-0'
}
},
{
side: 'right',
inset: true,
class: {
content: 'w-[calc(100%-2rem)] inset-y-4 right-4'
}
},
{
side: 'right',
inset: false,
class: {
content: 'w-full inset-y-0 right-0'
}
},
{
side: 'bottom',
inset: true,
class: {
content: 'max-h-[calc(100%-2rem)] inset-x-4 bottom-4'
}
},
{
side: 'bottom',
inset: false,
class: {
content: 'max-h-full inset-x-0 bottom-0'
}
},
{
side: 'left',
inset: true,
class: {
content: 'w-[calc(100%-2rem)] inset-y-4 left-4'
}
},
{
side: 'left',
inset: false,
class: {
content: 'w-full inset-y-0 left-0'
}
},
{
transition: true,
side: 'top',
class: {
content: 'data-[state=open]:animate-[slide-in-from-top_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-top_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'right',
class: {
content: 'data-[state=open]:animate-[slide-in-from-right_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-right_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'bottom',
class: {
content: 'data-[state=open]:animate-[slide-in-from-bottom_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-bottom_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'left',
class: {
content: 'data-[state=open]:animate-[slide-in-from-left_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-left_200ms_var(--ease-out)]'
}
}
]
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
slideover: {
slots: {
overlay: 'fixed inset-0 bg-elevated/75',
content: 'fixed bg-default divide-y divide-default sm:ring ring-default sm:shadow-lg flex flex-col focus:outline-none',
header: 'flex items-center gap-1.5 p-4 sm:px-6 min-h-(--ui-header-height)',
wrapper: '',
body: 'flex-1 overflow-y-auto p-4 sm:p-6',
footer: 'flex items-center gap-1.5 p-4 sm:px-6',
title: 'text-highlighted font-semibold',
description: 'mt-1 text-muted text-sm',
close: 'absolute top-4 end-4'
},
variants: {
side: {
top: {
content: ''
},
right: {
content: 'max-w-md'
},
bottom: {
content: ''
},
left: {
content: 'max-w-md'
}
},
inset: {
true: {
content: 'rounded-lg'
}
},
transition: {
true: {
overlay: 'data-[state=open]:animate-[fade-in_200ms_var(--ease-out)] data-[state=closed]:animate-[fade-out_200ms_var(--ease-out)]'
}
}
},
compoundVariants: [
{
side: 'top',
inset: true,
class: {
content: 'max-h-[calc(100%-2rem)] inset-x-4 top-4'
}
},
{
side: 'top',
inset: false,
class: {
content: 'max-h-full inset-x-0 top-0'
}
},
{
side: 'right',
inset: true,
class: {
content: 'w-[calc(100%-2rem)] inset-y-4 right-4'
}
},
{
side: 'right',
inset: false,
class: {
content: 'w-full inset-y-0 right-0'
}
},
{
side: 'bottom',
inset: true,
class: {
content: 'max-h-[calc(100%-2rem)] inset-x-4 bottom-4'
}
},
{
side: 'bottom',
inset: false,
class: {
content: 'max-h-full inset-x-0 bottom-0'
}
},
{
side: 'left',
inset: true,
class: {
content: 'w-[calc(100%-2rem)] inset-y-4 left-4'
}
},
{
side: 'left',
inset: false,
class: {
content: 'w-full inset-y-0 left-0'
}
},
{
transition: true,
side: 'top',
class: {
content: 'data-[state=open]:animate-[slide-in-from-top_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-top_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'right',
class: {
content: 'data-[state=open]:animate-[slide-in-from-right_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-right_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'bottom',
class: {
content: 'data-[state=open]:animate-[slide-in-from-bottom_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-bottom_200ms_var(--ease-out)]'
}
},
{
transition: true,
side: 'left',
class: {
content: 'data-[state=open]:animate-[slide-in-from-left_200ms_var(--ease-out)] data-[state=closed]:animate-[slide-out-to-left_200ms_var(--ease-out)]'
}
}
]
}
}
})
]
})