# Base vs Radix API differences between `base` and `radix`. Check the `base` field from `npx shadcn@latest info`. ## Contents - Composition: asChild vs render - Button / trigger as non-button element - Select (items prop, placeholder, positioning, multiple, object values) - ToggleGroup (type vs multiple) - Slider (scalar vs array) - Accordion (type and defaultValue) --- ## Composition: asChild (radix) vs render (base) Radix uses `asChild` to replace the default element. Base uses `render`. Don't wrap triggers in extra elements. **Incorrect:** ```tsx
``` **Correct (radix):** ```tsx ``` **Correct (base):** ```tsx }>Open ``` This applies to all trigger and close components: `DialogTrigger`, `SheetTrigger`, `AlertDialogTrigger`, `DropdownMenuTrigger`, `PopoverTrigger`, `TooltipTrigger`, `CollapsibleTrigger`, `DialogClose`, `SheetClose`, `NavigationMenuLink`, `BreadcrumbLink`, `SidebarMenuButton`, `Badge`, `Item`. --- ## Button / trigger as non-button element (base only) When `render` changes an element to a non-button (``, ``), add `nativeButton={false}`. **Incorrect (base):** missing `nativeButton={false}`. ```tsx ``` **Correct (base):** ```tsx ``` **Correct (radix):** ```tsx ``` Same for triggers whose `render` is not a `Button`: ```tsx // base. } nativeButton={false}> Pick date ``` --- ## Select **items prop (base only).** Use `items` to supply labels for values as required by the installed wrapper; it is not universally required by the primitive. Radix uses inline JSX only. **Incorrect (base):** ```tsx ``` **Correct (base):** ```tsx const items = [ { label: "Select a fruit", value: null }, { label: "Apple", value: "apple" }, { label: "Banana", value: "banana" }, ] ``` **Correct (radix):** ```tsx ``` **Placeholder.** Current Base UI primitives also support a `Select.Value` placeholder. Check the installed shadcn wrapper; a null-label item is one supported data pattern, not a universal requirement. Radix uses ``. **Content positioning.** Base uses `alignItemWithTrigger`. Radix uses `position`. ```tsx // base. // radix. ``` --- ## Select — multiple selection and object values (base only) Base supports `multiple`, render-function children on `SelectValue`, and object values with `itemToStringValue`. Radix is single-select with string values only. **Correct (base — multiple selection):** ```tsx ``` **Correct (base — object values):** ```tsx ``` --- ## ToggleGroup Base uses a `multiple` boolean prop. Radix uses `type="single"` or `type="multiple"`. **Incorrect (base):** ```tsx Daily ``` **Correct (base):** ```tsx // Single (no prop needed), defaultValue is always an array. Daily Weekly // Multi-selection. Bold Italic ``` **Correct (radix):** ```tsx // Single, defaultValue is a string. Daily Weekly // Multi-selection. Bold Italic ``` **Controlled single value:** ```tsx // base — wrap/unwrap arrays. const [value, setValue] = React.useState("normal") setValue(v[0] ?? "")}> // radix — plain string. const [value, setValue] = React.useState("normal") ``` --- ## Slider Base supports a number or number array, including a one-element array for one thumb. Radix requires an array. Check the installed wrapper type. **Also valid for a compatible Base wrapper:** ```tsx ``` **Correct (base):** ```tsx ``` **Correct (radix):** ```tsx ``` Both use arrays for range sliders. Controlled `onValueChange` in base may need a cast: ```tsx // base. const [value, setValue] = React.useState([0.3, 0.7]) setValue(v as number[])} /> // radix. const [value, setValue] = React.useState([0.3, 0.7]) ``` --- ## Accordion Radix requires `type="single"` or `type="multiple"` and supports `collapsible` for single mode. `defaultValue` is a string in single mode and an array in multiple mode. Base uses no `type` prop, uses `multiple` boolean, and `defaultValue` is always an array. **Incorrect (base):** ```tsx ... ``` **Correct (base):** ```tsx ... // Multi-select. ... ... ``` **Correct (radix):** ```tsx ... ```