diff --git a/playground/components/SlideoverProgrammaticExample.vue b/playground/components/SlideoverProgrammaticExample.vue
new file mode 100644
index 00000000..c087f7e6
--- /dev/null
+++ b/playground/components/SlideoverProgrammaticExample.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
diff --git a/playground/pages/slideover.vue b/playground/pages/slideover.vue
index 1f26011c..54e32439 100644
--- a/playground/pages/slideover.vue
+++ b/playground/pages/slideover.vue
@@ -1,5 +1,17 @@
@@ -105,5 +117,7 @@ const open = ref(false)
+
+
diff --git a/src/module.ts b/src/module.ts
index c5773c5c..13c930b3 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -68,6 +68,9 @@ export default defineNuxtModule({
addPlugin({
src: resolve('./runtime/plugins/modal')
})
+ addPlugin({
+ src: resolve('./runtime/plugins/slideover')
+ })
addComponentsDir({
path: resolve('./runtime/components'),
diff --git a/src/runtime/components/App.vue b/src/runtime/components/App.vue
index 2010e0bd..28684c5c 100644
--- a/src/runtime/components/App.vue
+++ b/src/runtime/components/App.vue
@@ -13,7 +13,7 @@ import { toRef } from 'vue'
import { ConfigProvider, TooltipProvider, useForwardProps } from 'radix-vue'
import { reactivePick } from '@vueuse/core'
import { useId } from '#imports'
-import { UToaster, UModalProvider } from '#components'
+import { UToaster, UModalProvider, USlideoverProvider } from '#components'
const props = withDefaults(defineProps(), {
useId: () => useId()
@@ -33,5 +33,6 @@ const toasterProps = toRef(() => props.toaster)
+
diff --git a/src/runtime/components/SlideoverProvider.vue b/src/runtime/components/SlideoverProvider.vue
new file mode 100644
index 00000000..7dd54445
--- /dev/null
+++ b/src/runtime/components/SlideoverProvider.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/src/runtime/composables/useSlideover.ts b/src/runtime/composables/useSlideover.ts
new file mode 100644
index 00000000..731784cd
--- /dev/null
+++ b/src/runtime/composables/useSlideover.ts
@@ -0,0 +1,71 @@
+import { ref, inject } from 'vue'
+import type { ShallowRef, Component, InjectionKey } from 'vue'
+import { createSharedComposable } from '@vueuse/core'
+import type { SlideoverProps } from '#ui/types'
+import type { ComponentProps } from '#ui/types/component'
+
+export interface SlideoverState {
+ component: Component | string
+ props: SlideoverProps
+}
+
+export const slideoverInjectionKey: InjectionKey> = Symbol('nuxt-ui.slideover')
+
+function _useSlideover() {
+ const slideoverState = inject(slideoverInjectionKey)
+
+ const isOpen = ref(false)
+
+ function open(component: T, props?: SlideoverProps & ComponentProps) {
+ if (!slideoverState) {
+ throw new Error('useSlideover() is called without provider')
+ }
+
+ slideoverState.value = {
+ component,
+ props: props ?? {}
+ }
+
+ isOpen.value = true
+ }
+
+ async function close() {
+ if (!slideoverState) return
+
+ isOpen.value = false
+ }
+
+ function reset() {
+ if (!slideoverState) return
+
+ slideoverState.value = {
+ component: 'div',
+ props: {}
+ }
+ }
+
+ /**
+ * Allows updating the slideover props
+ */
+ function patch>(props: Partial>) {
+ if (!slideoverState) return
+
+ slideoverState.value = {
+ ...slideoverState.value,
+ props: {
+ ...slideoverState.value.props,
+ ...props
+ }
+ }
+ }
+
+ return {
+ open,
+ close,
+ reset,
+ patch,
+ isOpen
+ }
+}
+
+export const useSlideover = createSharedComposable(_useSlideover)
diff --git a/src/runtime/plugins/slideover.ts b/src/runtime/plugins/slideover.ts
new file mode 100644
index 00000000..f24d1d9d
--- /dev/null
+++ b/src/runtime/plugins/slideover.ts
@@ -0,0 +1,12 @@
+import { shallowRef } from 'vue'
+import { defineNuxtPlugin } from '#imports'
+import { slideoverInjectionKey, type SlideoverState } from '../composables/useSlideover'
+
+export default defineNuxtPlugin((nuxtApp) => {
+ const slideoverState = shallowRef({
+ component: 'div',
+ props: {}
+ })
+
+ nuxtApp.vueApp.provide(slideoverInjectionKey, slideoverState)
+})