Reka UI - Vue Headless Components
Reka UI is a comprehensive Vue 3 port of the popular Radix UI Primitives, offering an unstyled, accessible, and highly customizable set of headless UI components. It empowers developers to build robust web applications with a strong focus on delivering excellent accessibility out-of-the-box and maximum flexibility for custom styling. The library is actively maintained, currently at version 2.9.6, and follows a frequent release cadence with regular bug fixes and feature additions, as seen in the recent v2.9.x patches and v2.9.0 feature release. It provides full TypeScript support, making it an ideal choice for TypeScript-first Vue projects. Its key differentiators include its headless architecture, strict adherence to WAI-ARIA standards, and a rich suite of Vue-specific components adapted from the battle-tested Radix UI primitives.
Common errors
-
TS2307: Cannot find module 'reka-ui' or its corresponding type declarations.
cause TypeScript compiler cannot locate the type definitions for reka-ui, or the package itself is not installed.fixEnsure 'reka-ui' is installed (`npm install reka-ui`) and your `tsconfig.json` includes `"compilerOptions": { "allowSyntheticDefaultImports": true }` if you're mixing CJS/ESM, though `reka-ui` primarily uses named exports. -
Vue warn: Failed to resolve component: RekaButton (or similar component name). If this is a native custom element, ensure it's registered with Vue's compilerOptions.
cause The Reka UI component was not correctly imported or registered within the Vue component where it's being used.fixVerify that you have correctly imported the component using named imports (e.g., `import { RekaButton } from 'reka-ui'`) and that the component name in your template exactly matches the imported name (e.g., `<RekaButton>`). -
Property 'weekStartsOn' does not exist on type '...' for DatePicker/Calendar components.
cause You are using a `weekStartsOn` prop that was changed in Reka UI v2.8.0. The previous type signature or interpretation might be causing a mismatch.fixIf you recently updated to Reka UI v2.8.0+, review your usage of `weekStartsOn` to conform to its new locale-independent behavior. Ensure the value provided matches the expected type and range (e.g., 0 for Sunday, 1 for Monday). -
Error: Cannot find module 'vue' or 'vue/dist/vue.runtime.esm-bundler.js'
cause Your project's `vue` dependency might be missing or an incompatible version with `reka-ui`.fixEnsure `vue` is installed and meets the `reka-ui` peer dependency requirement (Vue >= 3.4.0). Run `npm install vue@latest` or `pnpm update vue`.
Warnings
- breaking The `weekStartsOn` prop for DatePicker, DateRangePicker, Calendar, and RangeCalendar components was made locale-independent. If you were relying on its previous behavior that might have been tied to specific locale settings, you will need to adjust your implementation.
- gotcha Reka UI components are 'headless' or 'unstyled'. This means they provide functionality and accessibility features, but no visual styling by default. Developers are responsible for providing all styling (CSS, Tailwind, etc.) for the components.
- gotcha Reka UI has a peer dependency on Vue >= 3.4.0. Using it with older versions of Vue 3 might lead to unexpected behavior, warnings, or runtime errors.
- gotcha Many Reka UI components are composed of multiple sub-components (e.g., `RekaDialogRoot`, `RekaDialogTrigger`, `RekaDialogContent`). Incorrectly importing or structuring these sub-components can lead to non-functional or inaccessible UI.
Install
-
npm install reka-ui -
yarn add reka-ui -
pnpm add reka-ui
Imports
- RekaButton
import RekaButton from 'reka-ui'
import { RekaButton } from 'reka-ui' - RekaDialogRoot
import { DialogRoot } from 'reka-ui'import { RekaDialogRoot, RekaDialogTrigger, RekaDialogContent } from 'reka-ui' - TimeRange
import type { TimeRange } from 'reka-ui'
Quickstart
<!-- src/components/MyDialog.vue -->
<script setup lang="ts">
import { ref } from 'vue';
import { RekaButton, RekaDialogRoot, RekaDialogTrigger, RekaDialogContent, RekaDialogTitle, RekaDialogDescription } from 'reka-ui';
const isDialogOpen = ref(false);
</script>
<template>
<RekaDialogRoot v-model:open="isDialogOpen">
<RekaDialogTrigger as-child>
<RekaButton class="my-custom-button">Open Dialog</RekaButton>
</RekaDialogTrigger>
<Teleport to="body">
<RekaDialogContent class="my-dialog-content">
<RekaDialogTitle class="my-dialog-title">My Dialog Title</RekaDialogTitle>
<RekaDialogDescription class="my-dialog-description">
This is an accessible dialog, built with Reka UI primitives.
You need to provide your own styling for these headless components.
</RekaDialogDescription>
<RekaButton @click="isDialogOpen = false" class="my-close-button">Close</RekaButton>
</RekaDialogContent>
</Teleport>
</RekaDialogRoot>
</template>
<style scoped>
.my-custom-button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.my-dialog-content {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 1000;
min-width: 300px;
}
.my-dialog-title {
font-size: 1.5em;
margin-bottom: 10px;
}
.my-dialog-description {
margin-bottom: 15px;
}
.my-close-button {
background-color: #f44336;
color: white;
padding: 8px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
</style>