Migrating from Radix UI
A guide to migrating from Radix UI to Base UI.
Overview
Radix UI and Base UI are both excellent libraries for building web applications. However, they differ in their approach to component architecture. This guide will help you migrate your shadcn/ui components from Radix UI to Base UI.
Installation
pnpm add @base-ui-components/react
Migration Steps
asChild
to render
Prop
Radix UI uses an asChild
prop, while Base UI uses a render
prop.
In Radix UI, the Slot
component lets you implement an asChild
prop.
import { Slot } from 'radix-ui';
function Button({ asChild, ...props }) {
const Comp = asChild ? Slot.Root : 'button';
return <Comp {...props} />;
}
// Usage
<Button asChild>
<a href="/contact">Contact</a>
</Button>
In Base UI, useRender
lets you implement a render prop. The example below shows the equivalent implementation to the Radix example above.
import { useRender } from '@base-ui-components/react/use-render';
function Button({ render = <button />, ...props }) {
return useRender({ render, props });
}
// Usage 1
<Button render={<a href="/contact">Contact</a>} />
// Usage 2
<Button render={<a href="/contact"/>}>Contact</Button>
Positioning Content Popups
In Radix UI, for components such as Select
, Tooltip
, Popover
, Dropdown Menu
, HoverCard
, etc., you can position or align the content popup by passing props such as side
or align
to the Content
component.
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="left" align="start">
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
With Base UI, to position or align the content popup by passing props such as side
or align
, you'll need to use the positioner component instead of the content component. This is a required component, and your Content
component should be wrapped with Positioner
. The example below shows the equivalent implementation to the Radix example above.
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Open
</DropdownMenuTrigger>
<DropdownMenuPositioner side="left" align="start">
<DropdownMenuContent>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenuPositioner>
</DropdownMenu>
Using Labels in Popups
In Radix UI, you can use the Label
component to add a label to the popup content. It can be used anywhere in the popup content.
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">Open</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
With Base UI, you must ensure that the label is wrapped with the Group
component. The example below shows the equivalent implementation to the Radix example above.
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Open
</DropdownMenuTrigger>
<DropdownMenuPositioner>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenuPositioner>
</DropdownMenu>
Component Props
Radix UI and Base UI have different prop names for the same components. You'll need to ensure that you're using the correct prop names for each component when migrating. We'll soon have a migration guide for each component to help you with this process.