Migration - Radix Vue to Akar

This guide provides step-by-step instructions for developers transitioning their projects from Radix Vue to Akar.
Akar v2.0.20 already includes these Reka v2 API changes. If you are coming from radix-vue or reka-ui, switch the package name to akar and apply the breakages below that you have not already adopted.

Installation

First, install the latest akar.

pnpm add akar

Congratulations! 🎉 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 or reka-ui with akar.

<script setup lang="ts">
import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'akar';import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'radix-vue';</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; --akar-accordion-content-width: 300px; 
[data-radix-collection-item] {
}[data-reka-collection-item] {
}

Component Breaking Changes

Combobox

Arrow

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.
  • Similar to the changes in form component, the API for binding CheckboxItem has been changed from v-model:checked to v-model.
<template>
  <DropdownMenuCheckboxItem v-model:checked="value" />
  <DropdownMenuCheckboxItem v-model="value" />

  <DropdownMenuCheckboxItem checked />
  <DropdownMenuCheckboxItem :model-value="true" />
</template>

Pagination

  • Required itemsPerPage prop - The itemsPerPage prop is now required instead of relying on a default value.
    <template>
      <PaginationRoot :items-per-page="10" />
    </template>
    

Calendar

  • Remove deprecated step prop - Use prevPage/nextPage props for greater control.
    <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 renders a teleported element - The previous implementation of SelectValue rendered the selected SelectItem through a teleported fragment. This caused SSR flicker and unnecessary computation.
    <template>
      <SelectValue>
        <!-- render the content similar to `SelectItem` -->
      </SelectValue>
    </template>
    

Presence

To have better support for SSR content, we also modified the logic around the usage of forceMount for components that utilize Presence:

  • Accordion
  • Collapsible
  • Tabs
  • NavigationMenu

forceMount will now render the component even though 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",    "akar/nuxt",  ],
});