Checkout
Multi-step checkout flow management component with step-specific state management and navigation.
Purpose
This library provides a headless multi-step checkout flow system that manages step navigation, state management, and step-specific data storage. It's designed as a context provider that enables complete UI customization while handling the complexity of multi-step form flows, step validation, and step transitions.
Features
- Multi-step checkout flow management
- Step-specific data storage and retrieval
- Automatic step navigation controls
- Step validation callbacks
- Transition state management
- Automatic data attributes for step elements
Installation
- npm
- Yarn
npm install @haus-storefront-react/checkout
yarn add @haus-storefront-react/checkout
Note: This is not a public package. Contact the Haus Tech Team for access.
API Reference
CheckoutProvider
Main checkout context provider that manages multi-step checkout flow state and provides context to child components.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | React.ReactNode | Yes | - | Child components that will have access to checkout context |
useCheckoutContext
Hook to access checkout context and operations. Provides overloads for accessing full context or step-specific context.
Parameters
When called without parameters:
No parameters - Returns full checkout context
When called with step parameter:
| Parameter | Type | Required | Description |
|---|---|---|---|
step | TStep extends keyof TData | Yes | The step index to get step-specific context |
Returns
Full Context (no step parameter):
| Return Value | Type | Description |
|---|---|---|
currentStep | number | Current active step index |
finishedSteps | number[] | Array of completed step indices |
data | TData | All step data indexed by step number |
canGoToNextStep | boolean | Whether navigation to next step is possible |
canGoToPreviousStep | boolean | Whether navigation to previous step is possible |
stepRefs | readonly React.RefObject<HTMLElement>[] | Array of refs for each step element |
nextStep | (props?: StepFunctionProps) => void | Function to navigate to next step |
previousStep | (props?: StepFunctionProps) => void | Function to navigate to previous step |
gotoStep | (step: number, props?: StepFunctionProps) => void | Function to navigate to specific step |
setCurrentStep | Dispatch<SetStateAction<number>> | Function to directly set current step |
setData | Dispatch<SetStateAction<TData>> | Function to set all step data |
setDataForStep | (data: CheckoutDataType, step: number) => void | Function to set data for a specific step |
setStepRef | (el: HTMLElement, stepIndex: number) => void | Function to register a step element ref |
Step-Specific Context (with step parameter):
Returns the same properties as full context, but with:
data- The specific step's data (TData[TStep])ref- The ref for the specific step (RefObject<unknown>)
Throws
Throws an error if used outside of CheckoutProvider.
Data Attributes
The component automatically adds data attributes to step elements when refs are registered via setStepRef:
data-step- Step indexdata-finished- Whether step is finished (boolean string)data-current- Whether step is current (boolean string)data-total-steps- Total number of stepsdata-can-go-next- Whether can proceed to next step (boolean string)data-can-go-previous- Whether can go back (boolean string)data-step-data- JSON string of step datadata-is-transitioning-in- Whether step is transitioning in (boolean string)data-is-transitioning-out- Whether step is transitioning out (boolean string)
StepFunctionProps
Configuration object for step navigation functions (nextStep, previousStep, gotoStep).
Properties
| Property | Type | Required | Description |
|---|---|---|---|
onClick | () => Promise<void> | void | No | Callback executed before step change attempt |
onStepChange | () => Promise<void> | void | No | Callback executed after successful step change |
onFailed | () => Promise<void> | void | No | Callback executed when step change fails |
Basic Usage
Simple Multi-Step Flow
- React
- React Native
import {
CheckoutProvider,
useCheckoutContext,
} from '@haus-storefront-react/checkout'
function CheckoutApp() {
return (
<CheckoutProvider>
<CheckoutFlow />
</CheckoutProvider>
)
}
function CheckoutFlow() {
const {
currentStep,
nextStep,
previousStep,
canGoToNextStep,
canGoToPreviousStep,
} = useCheckoutContext()
return (
<div>
<div>Current Step: {currentStep}</div>
<button onClick={() => previousStep()} disabled={!canGoToPreviousStep}>
Previous
</button>
<button onClick={() => nextStep()} disabled={!canGoToNextStep}>
Next
</button>
</div>
)
}
import { View, Text, Pressable } from 'react-native'
import {
CheckoutProvider,
useCheckoutContext,
} from '@haus-storefront-react/checkout'
function CheckoutApp() {
return (
<CheckoutProvider>
<CheckoutFlow />
</CheckoutProvider>
)
}
function CheckoutFlow() {
const {
currentStep,
nextStep,
previousStep,
canGoToNextStep,
canGoToPreviousStep,
} = useCheckoutContext()
return (
<View>
<Text>Current Step: {currentStep}</Text>
<Pressable
onPress={() => previousStep()}
disabled={!canGoToPreviousStep}
>
<Text>Previous</Text>
</Pressable>
<Pressable onPress={() => nextStep()} disabled={!canGoToNextStep}>
<Text>Next</Text>
</Pressable>
</View>
)
}
Step-Specific Context
- React
- React Native
import { useCheckoutContext } from '@haus-storefront-react/checkout'
function CustomerStep() {
const { data, setDataForStep, setStepRef } = useCheckoutContext(0)
const handleSave = () => {
setDataForStep({ name: 'John Doe', email: 'john@example.com' }, 0)
}
return (
<div ref={(el: HTMLDivElement) => el && setStepRef(el, 0)}>
<h2>Customer Information</h2>
<input defaultValue={(data as { name?: string })?.name} />
<input defaultValue={(data as { email?: string })?.email} />
<button onClick={handleSave}>Save</button>
</div>
)
}
import { View, Text, TextInput, Pressable } from 'react-native'
import { useCheckoutContext } from '@haus-storefront-react/checkout'
function CustomerStep() {
const { data, setDataForStep, setStepRef } = useCheckoutContext(0)
const handleSave = () => {
setDataForStep({ name: 'John Doe', email: 'john@example.com' }, 0)
}
return (
<View ref={(el) => el && setStepRef(el as any, 0)}>
<Text>Customer Information</Text>
<TextInput defaultValue={(data as { name?: string })?.name} />
<TextInput defaultValue={(data as { email?: string })?.email} />
<Pressable onPress={handleSave}>
<Text>Save</Text>
</Pressable>
</View>
)
}
Advanced Usage
Complete Multi-Step Checkout
- React
- React Native
import {
CheckoutProvider,
useCheckoutContext,
} from '@haus-storefront-react/checkout'
function CompleteCheckout() {
return (
<CheckoutProvider>
<CheckoutSteps />
</CheckoutProvider>
)
}
function CheckoutSteps() {
const {
currentStep,
nextStep,
previousStep,
canGoToNextStep,
canGoToPreviousStep,
} = useCheckoutContext()
return (
<div>
<StepIndicator currentStep={currentStep} />
<div>
{currentStep === 0 && <CustomerStep />}
{currentStep === 1 && <AddressStep />}
{currentStep === 2 && <PaymentStep />}
{currentStep === 3 && <ReviewStep />}
</div>
<NavigationButtons
onNext={nextStep}
onPrevious={previousStep}
canGoNext={canGoToNextStep}
canGoPrevious={canGoToPreviousStep}
/>
</div>
)
}
function CustomerStep() {
const { data, setDataForStep, setStepRef } = useCheckoutContext(0)
return (
<div ref={(el: HTMLDivElement) => el && setStepRef(el, 0)}>
<h2>Customer Information</h2>
<input
defaultValue={(data as { name?: string })?.name}
onChange={(e) => setDataForStep({ name: e.target.value }, 0)}
/>
</div>
)
}
import React from 'react'
import { View, Text, TextInput, Pressable } from 'react-native'
import {
CheckoutProvider,
useCheckoutContext,
} from '@haus-storefront-react/checkout'
function CompleteCheckout() {
return (
<CheckoutProvider>
<CheckoutSteps />
</CheckoutProvider>
)
}
function CheckoutSteps() {
const {
currentStep,
nextStep,
previousStep,
canGoToNextStep,
canGoToPreviousStep,
} = useCheckoutContext()
return (
<View>
<StepIndicator currentStep={currentStep} />
<View>
{currentStep === 0 && <CustomerStep />}
{currentStep === 1 && <AddressStep />}
{currentStep === 2 && <PaymentStep />}
{currentStep === 3 && <ReviewStep />}
</View>
<NavigationButtons
onNext={nextStep}
onPrevious={previousStep}
canGoNext={canGoToNextStep}
canGoPrevious={canGoToPreviousStep}
/>
</View>
)
}
function CustomerStep() {
const { data, setDataForStep, setStepRef } = useCheckoutContext(0)
return (
<View ref={(el) => el && setStepRef(el as any, 0)}>
<Text>Customer Information</Text>
<TextInput
defaultValue={(data as { name?: string })?.name}
onChangeText={(value) => setDataForStep({ name: value }, 0)}
/>
</View>
)
}
Conditional Step Navigation
- React
- React Native
import { useCheckoutContext } from '@haus-storefront-react/checkout'
function ConditionalNavigation() {
const { gotoStep, currentStep, nextStep } = useCheckoutContext()
const handleSkip = () => {
gotoStep(3, {
onClick: async () => {
console.log('Skipping steps 1 and 2')
},
onStepChange: async () => {
console.log('Jumped to step 3')
},
})
}
return (
<div>
{currentStep === 0 && (
<button onClick={handleSkip}>Skip Optional Steps</button>
)}
<button onClick={() => nextStep()}>Continue Normally</button>
</div>
)
}
import { View, Text, Pressable } from 'react-native'
import { useCheckoutContext } from '@haus-storefront-react/checkout'
function ConditionalNavigation() {
const { gotoStep, currentStep, nextStep } = useCheckoutContext()
const handleSkip = () => {
gotoStep(3, {
onClick: async () => {
console.log('Skipping steps 1 and 2')
},
onStepChange: async () => {
console.log('Jumped to step 3')
},
})
}
return (
<View>
{currentStep === 0 && (
<Pressable onPress={handleSkip}>
<Text>Skip Optional Steps</Text>
</Pressable>
)}
<Pressable onPress={() => nextStep()}>
<Text>Continue Normally</Text>
</Pressable>
</View>
)
}
Made with ❤️ by Haus Tech Team