Radix Vue Primitives
Radix Vue is an unofficial, community-driven Vue 3 port of the popular Radix UI primitives, providing a comprehensive set of unstyled, accessible UI components for building high-quality design systems. The library focuses on robust, headless component logic, enabling developers to fully control styling via CSS, Tailwind CSS, or other solutions. While the npm registry lists version 1.9.17, the recent release notes indicate active development, with versions up to 2.9.6, suggesting a rapid release cadence primarily focused on bug fixes and new feature additions. Key differentiators include its strong emphasis on web accessibility standards, unopinionated styling, and deep integration with the Vue 3 ecosystem, making it a powerful foundation for custom component libraries.
Common errors
-
[Vue warn]: Failed to resolve component: AccordionRoot
cause The Radix Vue component was used in a Vue template but not correctly imported or registered within the script setup or component options.fixEnsure you have `import { AccordionRoot } from 'radix-vue';` (or the respective component) in your script block where the component is used. -
TypeError: Cannot read properties of undefined (reading 'setup') (or similar Vue runtime error mentioning 'vue' context)
cause This error often indicates that the `vue` peer dependency is missing or an incompatible version is installed, preventing Radix Vue components from initializing correctly.fixInstall or update Vue to the required version: `npm install vue@latest` or `npm install vue@3` to satisfy the `>= 3.2.0` peer dependency. -
Error: 'radix-vue' does not export 'SomeComponent'
cause Attempting to import a component or utility that is either not exported by the library, misspelled, or only available as a sub-component of a larger primitive.fixVerify the exact export name and path from the official Radix Vue documentation. For composite components (e.g., `DropdownMenu`), ensure you are importing `DropdownMenuRoot`, `DropdownMenuTrigger`, etc., not just `DropdownMenu`.
Warnings
- breaking In `v2.8.0`, the `weekStartsOn` prop for `DatePicker`, `DateRangePicker`, `Calendar`, and `RangeCalendar` components was made locale-independent. This change might alter calendar display behavior if your application relied on locale-specific interpretations of this prop previously. You may need to adjust its value to match your desired starting day of the week.
- gotcha Radix Vue components are 'headless' and provide no default styling. Developers are responsible for applying all visual styles (e.g., via CSS, Tailwind CSS, or scoped styles) to make components visually functional and integrated into their design system. Failure to add styling will result in invisible or unstyled, but functionally accessible, elements.
- gotcha Correct component composition and nesting are crucial for both functionality and accessibility. Many Radix Vue components require specific parent-child relationships (e.g., `AccordionItem` must be a direct child of `AccordionRoot`). Incorrect nesting can lead to broken UI, accessibility issues, or runtime errors.
Install
-
npm install radix-vue -
yarn add radix-vue -
pnpm add radix-vue
Imports
- AccordionRoot, AccordionItem
const { AccordionRoot } = require('radix-vue')import { AccordionRoot, AccordionItem } from 'radix-vue' - Primitive
import { Primitive } from 'radix-vue' - DropdownMenu
import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuContent } from 'radix-vue'
Quickstart
<script setup lang="ts">
import { AccordionRoot, AccordionItem, AccordionHeader, AccordionTrigger, AccordionContent } from 'radix-vue';
import { ref } from 'vue';
const accordionValue = ref('item-1');
</script>
<template>
<AccordionRoot
v-model="accordionValue"
class="bg-white rounded-md shadow-[0_2px_10px] shadow-black/5 w-[300px]"
type="single"
:collapsible="true"
>
<AccordionItem
class="mt-px overflow-hidden first:mt-0 first:rounded-t last:rounded-b focus-within:relative focus-within:z-10 focus-within:shadow-[0_0_0_2px] focus-within:shadow-black"
value="item-1"
>
<AccordionHeader class="flex">
<AccordionTrigger
class="text-grass11 shadow-[0_1px_0] shadow-black/0.5 hover:bg-mauve2 flex h-[45px] flex-1 cursor-default items-center justify-between bg-white px-5 text-[15px] leading-none outline-none group"
>
Is it accessible?
<svg
class="ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180"
width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"
>
<polygon points="3,1.5 8.5,5 3,8.5" />
</svg>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent
class="text-mauve11 bg-mauve2 data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden text-[15px]"
>
<div class="py-[15px] px-5">
Yes. Radix Vue is built on Radix UI's accessible primitives.
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem
class="mt-px overflow-hidden first:mt-0 first:rounded-t last:rounded-b focus-within:relative focus-within:z-10 focus-within:shadow-[0_0_0_2px] focus-within:shadow-black"
value="item-2"
>
<AccordionHeader class="flex">
<AccordionTrigger
class="text-grass11 shadow-[0_1px_0] shadow-black/0.5 hover:bg-mauve2 flex h-[45px] flex-1 cursor-default items-center justify-between bg-white px-5 text-[15px] leading-none outline-none group"
>
Is it unstyled?
<svg
class="ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180"
width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"
>
<polygon points="3,1.5 8.5,5 3,8.5" />
</svg>
</AccordionTrigger>
</AccordionHeader>
<AccordionContent
class="text-mauve11 bg-mauve2 data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden text-[15px]"
>
<div class="py-[15px] px-5">
Yes. Radix Vue components provide only the logic and accessibility, you provide the styles.
</div>
</AccordionContent>
</AccordionItem>
</AccordionRoot>
</template>