primitives
Drawer
Drawer — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).
Загрузка превью…
src/ui/drawer/Drawer.vue
<script setup lang="ts">
/**
* Порт базового радикс-слоя (registry/bases/radix/ui/drawer.tsx, MIT).
* Оригинал построен на npm-пакете `vaul` (React). Vue-порт `vaul-vue`
* не используется: пакет помечен на npm лицензией "Proprietary"
* (в package.json нет поля license), а его README прямо помечает
* пакет как unmaintained и рекомендует переходить на встроенный
* Drawer из reka-ui (MIT, уже зависимость воркспейса) — что и сделано
* здесь. API отличается от vaul (нет проп `direction`, вместо
* `data-vaul-drawer-direction` — свои атрибуты), см. docs/PORTING.md.
*/
import { DrawerRoot } from "reka-ui"
</script>
<template>
<DrawerRoot data-slot="drawer">
<slot />
</DrawerRoot>
</template>
src/ui/drawer/DrawerClose.vue
<script setup lang="ts">
import { DrawerClose } from "reka-ui"
</script>
<template>
<DrawerClose data-slot="drawer-close">
<slot />
</DrawerClose>
</template>
src/ui/drawer/DrawerContent.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { DrawerContent } from "reka-ui"
import { cn } from "@/lib/utils"
import DrawerOverlay from "./DrawerOverlay.vue"
import DrawerPortal from "./DrawerPortal.vue"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<DrawerPortal data-slot="drawer-portal">
<DrawerOverlay />
<DrawerContent
data-slot="drawer-content"
:class="
cn(
'cn-drawer-content group/drawer-content fixed z-50 data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm',
props.class
)
"
>
<div
class="cn-drawer-handle mx-auto hidden shrink-0 group-data-[vaul-drawer-direction=bottom]/drawer-content:block"
/>
<slot />
</DrawerContent>
</DrawerPortal>
</template>
src/ui/drawer/DrawerDescription.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { DrawerDescription } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<DrawerDescription
data-slot="drawer-description"
:class="cn('cn-drawer-description', props.class)"
>
<slot />
</DrawerDescription>
</template>
src/ui/drawer/DrawerFooter.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div
data-slot="drawer-footer"
:class="cn('cn-drawer-footer mt-auto flex flex-col', props.class)"
>
<slot />
</div>
</template>
src/ui/drawer/DrawerHeader.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div
data-slot="drawer-header"
:class="
cn(
'cn-drawer-header flex flex-col group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center',
props.class
)
"
>
<slot />
</div>
</template>
src/ui/drawer/DrawerOverlay.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { DrawerOverlay } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<DrawerOverlay
data-slot="drawer-overlay"
:class="
cn(
'cn-drawer-overlay fixed inset-0 z-50 data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0',
props.class
)
"
/>
</template>
src/ui/drawer/DrawerPortal.vue
<script setup lang="ts">
import { DrawerPortal } from "reka-ui"
</script>
<template>
<DrawerPortal data-slot="drawer-portal">
<slot />
</DrawerPortal>
</template>
src/ui/drawer/DrawerTitle.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { DrawerTitle } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<DrawerTitle
data-slot="drawer-title"
:class="cn('cn-drawer-title cn-font-heading', props.class)"
>
<slot />
</DrawerTitle>
</template>
src/ui/drawer/DrawerTrigger.vue
<script setup lang="ts">
import { DrawerTrigger } from "reka-ui"
</script>
<template>
<DrawerTrigger data-slot="drawer-trigger">
<slot />
</DrawerTrigger>
</template>
src/ui/drawer/index.ts
export { default as Drawer } from "./Drawer.vue"
export { default as DrawerTrigger } from "./DrawerTrigger.vue"
export { default as DrawerPortal } from "./DrawerPortal.vue"
export { default as DrawerClose } from "./DrawerClose.vue"
export { default as DrawerOverlay } from "./DrawerOverlay.vue"
export { default as DrawerContent } from "./DrawerContent.vue"
export { default as DrawerHeader } from "./DrawerHeader.vue"
export { default as DrawerFooter } from "./DrawerFooter.vue"
export { default as DrawerTitle } from "./DrawerTitle.vue"
export { default as DrawerDescription } from "./DrawerDescription.vue"
Установка
npx shadcn-vue@latest add https://revueui.rootapi.dev/r/drawer.jsonЗависимости реестра
npm-зависимости
- reka-ui
Источник: порт из ReUI (Keenthemes, MIT)