用法
在 Slideover 的默认插槽中使用 Button 或任何其他组件。
然后,使用 #content
插槽添加当 Slideover 打开时显示的内容。
<template>
<USlideover>
<UButton label="Open" color="neutral" variant="subtle" />
<template #content>
<Placeholder class="h-full m-4" />
</template>
</USlideover>
</template>
您还可以使用 #header
、#body
和 #footer
插槽来自定义 Slideover 的内容。
标题
使用 title
属性设置 Slideover 头部的标题。
<template>
<USlideover title="Slideover with title">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>
描述
使用 description
属性设置 Slideover 头部的描述。
<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
属性自定义或隐藏 Slideover 头部中显示的关闭按钮(使用 false
值)。
您可以传递 Button 组件的任何属性来对其进行自定义。
<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
插槽,则关闭按钮不会显示,因为它属于头部的一部分。关闭图标
使用 close-icon
属性自定义关闭按钮 Icon。默认为 i-lucide-x
。
<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
属性设置 Slideover 从屏幕哪一侧滑入。默认为 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>
遮罩层
使用 overlay
属性控制 Slideover 是否有遮罩层。默认为 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>
过渡效果
使用 transition
属性控制 Slideover 是否有动画效果。默认为 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>
示例
控制打开状态
您可以通过使用 default-open
属性或 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>
defineShortcuts
,您可以通过按下 O 来切换 Slideover。禁用关闭
将 dismissible
属性设置为 false
可防止 Slideover 在点击外部或按下 Esc 键时关闭。当用户尝试关闭它时,将触发 close:prevent
事件。
<template>
<USlideover :dismissible="false" title="Slideover non-dismissible">
<UButton label="Open" color="neutral" variant="subtle" />
<template #body>
<Placeholder class="h-full" />
</template>
</USlideover>
</template>
编程方式使用
您可以使用 useOverlay
组合式函数以编程方式打开 Slideover。
App
组件进行包裹,该组件使用OverlayProvider
组件的任何属性。首先,创建一个将以编程方式打开的滑入式组件
<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
事件。您可以通过 close
事件发出任何数据,但是,必须发出此事件才能捕获返回值。然后,在您的应用程序中使用它
<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>
emit('close')
来关闭滑入式组件。嵌套滑入式组件
您可以将滑入式组件相互嵌套。
<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>
带页脚插槽
使用 #footer
插槽在 Slideover 的主体内容之后添加内容。
<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>
API
属性
属性 | 默认值 | 类型 |
---|---|---|
title |
| |
description |
| |
内容 |
滑入式组件的内容。
| |
叠加层 |
|
在滑入式组件后面渲染一个遮罩层。 |
过渡动画 |
|
在打开或关闭时为滑入式组件添加动画效果。 |
side |
|
滑入式组件的侧边。 |
portal |
|
在门户中渲染滑入式组件。 |
close |
|
显示关闭按钮以关闭滑入式组件。 |
closeIcon |
|
关闭按钮中显示的图标。 |
可关闭的 |
|
当为 |
open |
对话框的受控打开状态。可以绑定为 | |
defaultOpen |
对话框初始渲染时的打开状态。当您不需要控制其打开状态时使用。 | |
modal |
|
对话框的模态性。当设置为 |
ui |
|
插槽
插槽 | 类型 |
---|---|
default |
|
内容 |
|
页头 |
|
title |
|
description |
|
actions |
|
close |
|
主体 |
|
页脚 |
|
事件
事件 | 类型 |
---|---|
update:open |
|
after:leave |
|
after:enter |
|
close:prevent |
|
主题
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-16',
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: 'inset-x-0 top-0 max-h-full'
},
right: {
content: 'right-0 inset-y-0 w-full max-w-md'
},
bottom: {
content: 'inset-x-0 bottom-0 max-h-full'
},
left: {
content: 'left-0 inset-y-0 w-full max-w-md'
}
},
transition: {
true: {
overlay: 'data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]'
}
}
},
compoundVariants: [
{
transition: true,
side: 'top',
class: {
content: 'data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'right',
class: {
content: 'data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'bottom',
class: {
content: 'data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-bottom_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'left',
class: {
content: 'data-[state=open]:animate-[slide-in-from-left_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-left_200ms_ease-in-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-16',
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: 'inset-x-0 top-0 max-h-full'
},
right: {
content: 'right-0 inset-y-0 w-full max-w-md'
},
bottom: {
content: 'inset-x-0 bottom-0 max-h-full'
},
left: {
content: 'left-0 inset-y-0 w-full max-w-md'
}
},
transition: {
true: {
overlay: 'data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]'
}
}
},
compoundVariants: [
{
transition: true,
side: 'top',
class: {
content: 'data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'right',
class: {
content: 'data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'bottom',
class: {
content: 'data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-bottom_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'left',
class: {
content: 'data-[state=open]:animate-[slide-in-from-left_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-left_200ms_ease-in-out]'
}
}
]
}
}
})
]
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'
export default defineConfig({
plugins: [
vue(),
uiPro({
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-16',
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: 'inset-x-0 top-0 max-h-full'
},
right: {
content: 'right-0 inset-y-0 w-full max-w-md'
},
bottom: {
content: 'inset-x-0 bottom-0 max-h-full'
},
left: {
content: 'left-0 inset-y-0 w-full max-w-md'
}
},
transition: {
true: {
overlay: 'data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]'
}
}
},
compoundVariants: [
{
transition: true,
side: 'top',
class: {
content: 'data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'right',
class: {
content: 'data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'bottom',
class: {
content: 'data-[state=open]:animate-[slide-in-from-bottom_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-bottom_200ms_ease-in-out]'
}
},
{
transition: true,
side: 'left',
class: {
content: 'data-[state=open]:animate-[slide-in-from-left_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-left_200ms_ease-in-out]'
}
}
]
}
}
})
]
})