Unstyled, accessible Vue 3 component primitives. WAI-ARIA compliant. Previously Radix Vue. **Current version:** v2.8.0 (January 2026) - Building headless/unstyled components from scratch
vue skillasChildv-model for controlled, default* props for uncontrolledforceMount// nuxt.config.ts (auto-imports all components) export default defineNuxtConfig({ modules: ['reka-ui/nuxt'] })
import { RekaResolver } from 'reka-ui/resolver' // vite.config.ts (with auto-import resolver) import Components from 'unplugin-vue-components/vite' export default defineConfig({ plugins: [ vue(), Components({ resolvers: [RekaResolver()] }) ] }) `## Basic Patterns` <!-- Dialog with controlled state --> <script setup> import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from 'reka-ui' const open = ref(false) </script> <template> <DialogRoot v-model:open="open"> <DialogTrigger>Open</DialogTrigger> <DialogPortal> <DialogOverlay /> <DialogContent> <DialogTitle>Title</DialogTitle> <DialogDescription>Description</DialogDescription> <DialogClose>Close</DialogClose> </DialogContent> </DialogPortal> </DialogRoot> </template>
<!-- Select with uncontrolled default --> <SelectRoot default-value="apple"> <SelectTrigger> <SelectValue placeholder="Pick fruit" /> </SelectTrigger> <SelectPortal> <SelectContent> <SelectViewport> <SelectItem value="apple"><SelectItemText>Apple</SelectItemText></SelectItem> <SelectItem value="banana"><SelectItemText>Banana</SelectItemText></SelectItem> </SelectViewport> </SelectContent> </SelectPortal> </SelectRoot>
<!-- asChild for custom trigger element --> <DialogTrigger as-child> <button>Open</button> </DialogTrigger>
hideShiftedArrow prop (v2.8.0)stepSnapping support (v2.8.0)weekStartsOn now locale-independent for date components (v2.8.0)estimateSize accepts function for Listbox/Tree (v2.7.0)useLocale, useDirection exposed (v2.6.0)disableOutsidePointerEvents prop on Content (v2.7.0)disableSwipe prop (v2.6.0)