@tour-kit/reactHeadless
HeadlessTourCard
HeadlessTourCard: unstyled card primitive exposing step data, actions, and positioning via render props for custom UIs
HeadlessTourCard
An unstyled tour card that exposes all state and actions via render props.
Usage
import { HeadlessTourCard } from '@tour-kit/react/headless';
<HeadlessTourCard>
{(props) => (
<div className="my-card">
<h3>{props.currentStep?.title}</h3>
<p>{props.currentStep?.content}</p>
</div>
)}
</HeadlessTourCard>Render Props
Prop
Type
Complete Example
<HeadlessTourCard>
{({
currentStep,
currentStepIndex,
totalSteps,
isFirstStep,
isLastStep,
next,
prev,
skip,
complete,
}) => (
<div className="bg-white rounded-lg shadow-xl p-6 w-80">
{/* Header */}
<div className="flex justify-between items-center mb-4">
<span className="text-sm text-gray-500">
{currentStepIndex + 1} of {totalSteps}
</span>
<button onClick={skip} className="text-gray-400 hover:text-gray-600">
×
</button>
</div>
{/* Content */}
<h3 className="text-lg font-semibold mb-2">
{currentStep?.title}
</h3>
<p className="text-gray-600 mb-6">
{currentStep?.content}
</p>
{/* Navigation */}
<div className="flex justify-between">
{!isFirstStep && (
<button
onClick={prev}
className="px-4 py-2 border rounded hover:bg-gray-50"
>
Back
</button>
)}
<button
onClick={isLastStep ? complete : next}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 ml-auto"
>
{isLastStep ? 'Done' : 'Next'}
</button>
</div>
</div>
)}
</HeadlessTourCard>With Framer Motion
import { motion, AnimatePresence } from 'framer-motion';
<HeadlessTourCard>
{({ isActive, currentStep, ...actions }) => (
<AnimatePresence>
{isActive && (
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
className="tour-card"
>
{/* Your custom UI */}
</motion.div>
)}
</AnimatePresence>
)}
</HeadlessTourCard>Positioning
Use targetRect to position the card:
<HeadlessTourCard>
{({ targetRect, currentStep }) => {
const style = targetRect ? {
position: 'fixed',
top: targetRect.bottom + 16,
left: targetRect.left,
} : {};
return (
<div style={style} className="tour-card">
{currentStep?.content}
</div>
);
}}
</HeadlessTourCard>