Base UI Support
Switch from Radix UI to Base UI for tour components using the UnifiedSlot abstraction and UILibraryContext provider
userTourKit supports both Radix UI (default) and Base UI for headless component primitives. This allows you to choose your preferred headless UI library while using the same userTourKit components.
Installation
First, install Base UI as an additional dependency:
pnpm add @base-ui-components/reactnpm install @base-ui-components/reactyarn add @base-ui-components/reactbun add @base-ui-components/reactBase UI is an optional peer dependency. Radix UI remains the default and works without any additional setup.
@base-ui-components/react is the current Base UI package. The earlier
@mui/base preview was deprecated and renamed — if you still depend on it, see
the troubleshooting note. The
UnifiedSlot render-prop pattern is library-agnostic, so either works.
Enabling Base UI Mode
Wrap your application (or a portion of it) with UILibraryProvider and set the library prop to "base-ui":
import { UILibraryProvider, Tour, TourStep } from '@tour-kit/react';
function App() {
return (
<UILibraryProvider library="base-ui">
<Tour id="my-tour">
<TourStep target="#step-1" title="Welcome">
This tour uses Base UI primitives.
</TourStep>
</Tour>
</UILibraryProvider>
);
}Available Packages
Base UI support is available in all userTourKit packages:
| Package | Components with Base UI support |
|---|---|
@tour-kit/react | TourClose |
@tour-kit/hints | HintHotspot, HintTooltip |
@tour-kit/adoption | AdoptionNudge, FeatureButton |
@tour-kit/checklists | Checklist, ChecklistPanel |
How It Works
The asChild Pattern
userTourKit components use the asChild pattern to allow custom element composition:
// Radix UI style - passes an element as child
<TourClose asChild>
<button className="my-button">Close</button>
</TourClose>
// Base UI style - uses render props
<TourClose asChild>
{(props) => <button {...props} className="my-button">Close</button>}
</TourClose>The UILibraryProvider automatically switches between these patterns based on the selected library.
UnifiedSlot Component
Under the hood, userTourKit uses a UnifiedSlot component that handles both patterns:
- Radix UI mode: Clones the child element and merges props (like
@radix-ui/react-slot) - Base UI mode: Calls the render prop function with props
You can also use UnifiedSlot directly in custom components:
import { UnifiedSlot, useUILibrary } from '@tour-kit/react';
function CustomButton({ asChild, children, ...props }) {
const library = useUILibrary();
const Comp = asChild
? (library === 'base-ui' ? UnifiedSlot : Slot)
: 'button';
return <Comp {...props}>{children}</Comp>;
}API Reference
UILibraryProvider
Provider component for selecting the UI library.
interface UILibraryProviderProps {
library?: 'radix-ui' | 'base-ui'; // Default: 'radix-ui'
children: React.ReactNode;
}useUILibrary
Hook to get the current UI library.
function useUILibrary(): 'radix-ui' | 'base-ui';UnifiedSlot
Slot component that works with both Radix UI and Base UI patterns.
interface UnifiedSlotProps {
children: ReactNode | ((props: Record<string, unknown>) => ReactElement);
[key: string]: unknown; // Additional props to pass through
}Migration Guide
From Radix UI (Default)
No changes needed - Radix UI is the default behavior.
To Base UI
- Install
@base-ui-components/react - Wrap your app with
UILibraryProvider:
import { UILibraryProvider } from '@tour-kit/react';
function App() {
return (
<UILibraryProvider library="base-ui">
{/* Your app */}
</UILibraryProvider>
);
}- Update any
asChildusage to use render props:
// Before (Radix UI style)
<TourClose asChild>
<MyButton />
</TourClose>
// After (Base UI style)
<TourClose asChild>
{(props) => <MyButton {...props} />}
</TourClose>The element-based syntax still works in Base UI mode, but render props are recommended for full compatibility.
Mixing Libraries
You can nest providers to use different libraries in different parts of your app:
<UILibraryProvider library="radix-ui">
<Header /> {/* Uses Radix UI */}
<UILibraryProvider library="base-ui">
<MainContent /> {/* Uses Base UI */}
</UILibraryProvider>
<Footer /> {/* Uses Radix UI */}
</UILibraryProvider>Related
- Unified Slot deep-dive — the
UnifiedSlotprimitive behind everyasChildprop. - Custom components guide — go beyond
asChildto fully replace the component shell. <TourClose>,<HintHotspot>— examples of components that support both libraries.@tour-kit/reactAPI reference — fullUnifiedSlot/UILibraryProvider/useUILibraryexports.
Ship onboarding, not config.
npm i @tour-kit/core is MIT and free. The Pro packages work unlicensed too — a one-time $99 license removes the production watermark when you ship.
MIT-licensed — no signup, no credit card. Pay once, only when you ship.
Audience Segmentation
Target tours, hints, surveys, and announcements at named user segments using SegmentationProvider, useSegment, and CSV-driven user lists.
Theme Variations
Resolve tour themes by system colour scheme, explicit mode, route, or arbitrary trait predicates with `<ThemeProvider>` and `useThemeVariation`.