Docs navigation

<CancelFlow>

The drop-in cancel flow component.

import { CancelFlow } from '@churnkey/react'
import '@churnkey/react/styles.css'

Mode selection

PropTypeRequiredDefault
appIdstringanalytics + connected
customerDirectCustomeranalytics
subscriptionsDirectSubscription[]optional
sessionstringconnected
mode'live' | 'test'optional'live'
apiBaseUrlstringoptionalChurnkey production API

apiBaseUrl is for self-hosted Churnkey deployments only. Leave it unset in normal use.

Flow definition

PropTypeNotes
stepsStep[]Required in open source and analytics. Optional in connected mode; the dashboard supplies them.

Handlers

Action callbacks. In open source and analytics they're the only way an action happens — the SDK doesn't call your billing API on its own. In connected mode, defining one overrides Churnkey's server action for that offer type only.

PropSignature
handleDiscount(offer: AcceptedOffer, customer) => Promise<void> | void
handlePause(offer: AcceptedOffer, customer) => Promise<void> | void
handlePlanChange(offer: AcceptedOffer, customer) => Promise<void> | void
handleTrialExtension(offer: AcceptedOffer, customer) => Promise<void> | void
handleCancel(customer) => Promise<void> | void

Handlers receive an AcceptedOffer: the offer config plus reasonId and (for custom offers) result. AcceptedOffer is a union over every offer type, so narrow on offer.type to read type-specific fields like couponId or months. See Callbacks for the narrowing pattern.

Listeners

Side-effect callbacks. They fire after the action commits — analytics, toasts, route changes. The per-type listener runs first; the catch-all onAccept runs after, for every offer type. Listener errors are swallowed so they can't break the flow.

PropSignature
onAccept(offer, customer) => void | Promise<void>
onDiscount(offer, customer) => void | Promise<void>
onPause(offer, customer) => void | Promise<void>
onPlanChange(offer, customer) => void | Promise<void>
onTrialExtension(offer, customer) => void | Promise<void>
onCancel(customer) => void | Promise<void>
onClose() => void
onStepChange(step, prevStep) => void

Customization

PropTypeNotes
appearanceAppearanceColor scheme, CSS variable overrides.
classNamesStructuralClassNamesclassName overrides for modal, overlay, close, back.
componentsComponentOverridesReplace built-in UI components.
customComponentsRecord<string, Component>Components for custom step and offer types, keyed by type.

Appearance

interface Appearance {
  colorScheme?: 'light' | 'dark' | 'auto'
  variables?: Partial<AppearanceVariables>
}
 
interface AppearanceVariables {
  // Surfaces
  colorBackground:       string
  colorSurface:          string
  colorSurfaceMuted:     string
 
  // Borders
  colorBorder:           string
  colorBorderStrong:     string
 
  // Text
  colorText:             string
  colorTextSecondary:    string
  colorTextMuted:        string
 
  // Primary
  colorPrimary:          string
  colorPrimaryHover:     string
  colorPrimarySoft:      string
 
  // Semantic
  colorSuccess:          string
  colorSuccessSoft:      string
  colorDanger:           string
  colorDangerHover:      string
  colorDangerSoft:       string
 
  // Typography
  fontFamily:            string
  fontFamilyMono:        string
  fontFamilyDisplay:     string
  fontSize:              string
  fontWeightDisplay:     string
  letterSpacingDisplay:  string
 
  // Geometry
  borderRadius:          string
  radiusSm:              string
  radiusMd:              string
  radiusLg:              string
  radiusXl:              string
 
  // Elevation
  shadowModal:           string
  shadowCard:            string
 
  // Overlay
  overlayColor:          string
}

See Theming for usage.

StructuralClassNames

interface StructuralClassNames {
  modal?:        string
  overlay?:      string
  closeButton?:  string
  backButton?:   string
}

Per-step classNames go on the step config, not here. See classNames.

Built-in close behavior

The default modal closes when the customer clicks the close button, clicks the overlay, or presses Escape. Each fires onClose. Override the Modal component slot to change this behavior.

Subpath exports

The package has three entry points:

import { CancelFlow }         from '@churnkey/react'              // drop-in component
import { useCancelFlow }      from '@churnkey/react/headless'     // headless hook
import { CancelFlowMachine }  from '@churnkey/react/core'         // state machine, no React dependency

The core export is the state machine without React — useful for testing flow logic in isolation or wiring it into a non-React framework.

Next steps

  • useCancelFlow — the headless hook with the same config.
  • Step types — every built-in step and the custom-step shape.
  • Offer types — every built-in offer and AcceptedOffer.