Migration - Radix Vue to Reka UI
Installation
First and foremost, you need to install the latest reka-ui
.
$ npm add reka-ui
Congratulation! 🎉 Now that you've installed the above package, let's perform the migration! The first 2 steps are relatively simple. Just do a global search and replace for the following changes.
Import Statement Changes
The primary change in imports is replacing radix-vue
with reka-ui
.
<script setup lang="ts">
import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'radix-vue'
import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'reka-ui'
</script>
Naming Convention Changes
CSS variable and data attributes names have been updated to use the reka
prefix instead of radix
.
--radix-accordion-content-width: 300px;
--reka-accordion-content-width: 300px;
[data-radix-collection-item] {}
[data-reka-collection-item] {}
Component Breaking Changes
Combobox
Remove
filter-function
props -Combobox
has been refactored and improved to support better custom filtering. Read more.vue<template> <ComboboxRoot :filter-function="customFilter" /> </template>
Move
displayValue
props from Root to Inputvue<template> <ComboboxRoot v-model:search-term="search" :display-value="(v) => v.name" /> <ComboboxRoot> <ComboboxInput v-model="search" :display-value="(v) => v.name" /> </ComboboxRoot> </template>
Arrow
- Improve arrow polygon - Change the svg polygon to allow better styling.
Form component
- Rename controlled state to
v-model
- Replacev-model:checked
,v-model:pressed
with more familiar API for form component.
<template>
<CheckboxRoot v-model:checked="value" />
<CheckboxRoot v-model="value" />
</template>
- Reposition
VisuallyHidden
- Previously,VisuallyHidden
were positioned at the root node, causing style scoped to not be applied.
Menu CheckboxItem
- Similar to the changes in form component, the API for binding
CheckboxItem
has been changed fromv-model:checked
tov-model
.
<template>
<DropdownMenuCheckboxItem v-model:checked="value" />
<DropdownMenuCheckboxItem v-model="value" />
<DropdownMenuCheckboxItem checked />
<DropdownMenuCheckboxItem :model-value="true" />
</template>
Pagination
Required
itemsPerPage
prop - Instead of defaultitemsPerPage
value, now it is required as to provide a more explicit hint about the page size.vue<template> <PaginationRoot :items-per-page="10" /> </template>
Calendar
Remove deprecated step prop - Use
prevPage/nextPage
props for greater control.vue<script setup lang="ts"> function pagingFunc(date: DateValue, sign: -1 | 1) { if (sign === -1) return date.subtract({ years: 1 }) return date.add({ years: 1 }) } </script> <template> <CalendarPrev step="year" /> <CalendarPrev :prev-page="(date: DateValue) => pagingFunc(date, -1)" /> <CalendarNext step="year" /> <CalendarNext :next-page="(date: DateValue) => pagingFunc(date, 1)" /> </template>
Select
SelectValue
no longer render teleported element - Previous implementation ofSelectValue
will render the selectedSelectItem
via teleporting fragment. This causes SSR flickering, and it is unnecessarily computation.vue<template> <SelectValue> <!-- render the content similar to `SelectItem` --> </SelectValue> </template>
Presence
To have better supports for SSR content, we also modify the logic around the usage of forceMount
for component that utilize Presence:
Accordion
Collapsible
Tabs
NavigationMenu
forceMount
will now render the component eventhough the state is inactive. You are now required to handle the visibility logic of the component manually.
<template>
<TabsRoot
v-slot="{ modelValue }"
default-value="tab1"
>
<TabsContent
value="tab1"
force-mount
:hidden="modelValue !== 'tab1'"
>
…
</TabsContent>
<TabsContent
value="tab2"
force-mount
:hidden="modelValue !== 'tab2'"
>
…
</TabsContent>
</TabsRoot>
</template>
For Nuxt module users
If you are using Nuxt, you need to update your module import.
// nuxt.config.ts
export default defineNuxtConfig({
modules: [
'radix-vue/nuxt' <!-- [!code --] -->
'reka-ui/nuxt' <!-- [!code ++] -->
],
})