Skip to content

Add rebate offer type to the React SDK#7

Merged
robert-moore merged 4 commits into
mainfrom
feature/rebate-offer
May 30, 2026
Merged

Add rebate offer type to the React SDK#7
robert-moore merged 4 commits into
mainfrom
feature/rebate-offer

Conversation

@robert-moore
Copy link
Copy Markdown
Contributor

@robert-moore robert-moore commented May 29, 2026

Adds a rebate offer type to the cancel flow, and tidies the offer panels so they share one surface treatment.

Rebate offers

A rebate is a partial refund of the customer's most recent paid invoice while their subscription stays active. It's aimed at money-back-guarantee windows: a customer who would otherwise cancel to get their money back can take a partial refund and keep the subscription instead. In connected mode the refund is issued through Stripe.

  • RebateOffer joins the offer union — the local config plus the shape resolved in token mode (amountMinor, currency, amountPaidMinor, netAfterRebateMinor) — wired through the state machine, the config transform, and the offer-type map.
  • DefaultRebateOffer renders the offer as an itemized invoice: the period charge, the rebate being credited (the accented line), and what's still due. Themed with the --ck-* tokens and overridable via components.RebateOffer.
  • handleRebate / onRebate callbacks, consistent with the other offer types. In connected mode the SDK runs the rebate server-side; defining handleRebate overrides that to run the refund through your own billing system.
  • The accepted rebate amount is recorded on the session.

The public surface stays minimal — one component, one type, two callbacks — mirroring the existing offer types. Connected-mode rebates are Stripe-only for now.

Offer panel styling

While building the rebate panel I unified how offer panels are filled. Discount and trial-extension were using colorPrimarySoft (the indigo tint); they now use colorSurfaceMuted (the neutral callout surface), matching pause and leaving colorPrimarySoft for selected-state highlights, as the theming docs describe. The rebate panel itself renders as plain invoice lines on the surface rather than a filled card.

This is a visual change to two existing default components. Override the relevant --ck-* properties to restore the previous tint.

Versioning

Minor bump to 0.4.0, with a changelog entry (Added: rebate offer; Changed: offer panel surfaces).

Testing

Typecheck, lint, and build pass. 156 unit tests pass, including coverage for the rebate config transform and the accept paths (handler override and connected-mode action).

DefaultRebateOffer now renders the period charge, the rebate being credited
(the accented line), and what's still due — as invoice lines on the surface
rather than a filled panel. Quieter paid line, more room below the total.

Also unifies the offer panels: discount and trial-extension move from
colorPrimarySoft to colorSurfaceMuted so every offer panel reads the same, and
colorPrimarySoft is left for selected-state highlights. The playground's
all-offers scenario gains a rebate reason.
@robert-moore robert-moore merged commit b5f0adf into main May 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant