UNPKG

@blocklet/payment-react

Version:

Reusable react components for payment kit v2

140 lines (120 loc) 6.6 kB
# PricingTable The `PricingTable` component is a flexible UI element designed to display subscription plans and pricing options in a structured, responsive table. It allows users to toggle between billing cycles (e.g., monthly, yearly), select their preferred currency, and choose a plan to proceed with. This component is ideal for building custom checkout flows where you need granular control over the presentation of pricing plans. For a more integrated solution that handles the entire checkout process, consider using the higher-level [`CheckoutTable`](./components-checkout-checkout-table.md) component. ## Props | Prop | Type | Default | Description | | --- | --- | --- | --- | | `table` | `TPricingTableExpanded` | - | **Required**. An object containing the pricing table data, including a list of items (plans), currency information, and other details. | | `onSelect` | `(priceId: string, currencyId: string) => void` | - | **Required**. A callback function that is triggered when a user clicks the action button for a plan. It receives the selected `priceId` and `currencyId`. | | `alignItems` | `'center' \| 'left'` | `'center'` | Controls the horizontal alignment of the table's header content (billing cycle and currency selectors). | | `mode` | `'checkout' \| 'select'` | `'checkout'` | Determines the behavior and text of the action button. `'checkout'` mode is for initiating a payment, while `'select'` mode is for selecting a plan within a larger form. | | `interval` | `string` | `''` | Sets the initially selected billing interval. The format is typically `interval-interval_count` (e.g., `month-1`, `year-1`). | | `hideCurrency` | `boolean` | `false` | If `true`, the currency selector dropdown will be hidden, even if multiple currencies are available. | ## Usage Example To use the `PricingTable`, you must wrap it in a `PaymentProvider`. The component requires a `table` object with your product data and an `onSelect` handler to manage user selections. ```tsx Integration Example icon=lucide:code import { PaymentProvider } from '@blocklet/payment-react'; import { PricingTable } from '@blocklet/payment-react/components/ui'; import type { TPricingTableExpanded } from '@blocklet/payment-types'; // In a real application, you would fetch this data from your payment service. const pricingTableData: TPricingTableExpanded = { id: 'pt_123', livemode: false, currency: { id: 'usd', symbol: '$' }, items: [ { price_id: 'price_basic_monthly', product: { name: 'Basic Plan', description: 'For individuals and small teams.', unit_label: 'user', features: [{ name: '5 Projects' }, { name: '10GB Storage' }, { name: 'Basic Support' }], }, price: { currency: 'usd', unit_amount: '1000', // in cents recurring: { interval: 'month', interval_count: 1 }, currency_options: [{ currency_id: 'usd', unit_amount: '1000' }], }, is_highlight: false, }, { price_id: 'price_pro_monthly', product: { name: 'Pro Plan', description: 'For growing businesses.', unit_label: 'user', features: [{ name: 'Unlimited Projects' }, { name: '100GB Storage' }, { name: 'Priority Support' }], }, price: { currency: 'usd', unit_amount: '2500', recurring: { interval: 'month', interval_count: 1 }, currency_options: [{ currency_id: 'usd', unit_amount: '2500' }], }, is_highlight: true, highlight_text: 'Popular', }, { price_id: 'price_basic_yearly', product: { name: 'Basic Plan', description: 'For individuals and small teams.', unit_label: 'user', features: [{ name: '5 Projects' }, { name: '10GB Storage' }, { name: 'Basic Support' }], }, price: { currency: 'usd', unit_amount: '10000', recurring: { interval: 'year', interval_count: 1 }, currency_options: [{ currency_id: 'usd', unit_amount: '10000' }], }, is_highlight: false, }, { price_id: 'price_pro_yearly', product: { name: 'Pro Plan', description: 'For growing businesses.', unit_label: 'user', features: [{ name: 'Unlimited Projects' }, { name: '100GB Storage' }, { name: 'Priority Support' }], }, price: { currency: 'usd', unit_amount: '25000', recurring: { interval: 'year', interval_count: 1 }, currency_options: [{ currency_id: 'usd', unit_amount: '25000' }], }, is_highlight: true, highlight_text: 'Popular', }, ], }; function MyPricingPage() { const { session, connect } = useSessionContext(); const handlePlanSelect = async (priceId: string, currencyId: string) => { console.log(`Plan selected: ${priceId}, Currency: ${currencyId}`); // Here, you would typically navigate to a checkout page or open a payment modal. // For example: `router.push(\"/checkout?price_id=${priceId}&currency_id=${currencyId}\")` alert(`Selected Price ID: ${priceId}`); }; return ( <PaymentProvider session={session} connect={connect}> <div style={{ maxWidth: 800, margin: 'auto' }}> <PricingTable table={pricingTableData} onSelect={handlePlanSelect} /> </div> </PaymentProvider> ); } export default MyPricingPage; ``` ## Usage Scenarios ### Mode: `checkout` vs. `select` The `mode` prop changes the call-to-action button to fit different use cases. - **`mode='checkout'` (Default):** The button text will be context-aware, showing labels like "Subscribe" or "Start Trial". This mode is intended for when the user's click should immediately initiate the payment or checkout process. - **`mode='select'`:** The button text will show "Select" or "Selected". This is useful when the pricing table is part of a larger form or multi-step process. The `onSelect` callback can be used to update the application's state with the chosen plan, and the UI will visually indicate which plan is currently selected. ### Handling `onSelect` The `onSelect` callback is the core mechanism for handling user interaction. It's an async function that receives the `priceId` and `currencyId` of the chosen plan. Your application logic should reside here. Common actions include: - Storing the selected plan in your application's state. - Redirecting the user to a dedicated checkout page, passing the `priceId` as a URL parameter. - Using the `priceId` to create a checkout session with the payment service backend and then opening a payment form.