Components
Pricing Pair
Two panels side by side in one frame: what is bought once on a sky band, then the monthly plans. Every price comes from your data.
Preview
Mirrored is the same English content laid out right to left: it separates a mirroring bug from a translation one.
Installation
SoonInstalling from the registry is coming soon. Until then, these are the commands you will run.
npx ritla add pricing-pairAlso works with shadcn: npx shadcn@latest add @ritla/pricing-pair
Dependencies it brings: @phosphor-icons/react
Installing by hand copies the component's source into your project. The source comes with a Ritla UI license, so the CLI is the short way to the same files.
Usage
import { PricingFeatures, PricingPair, PricingPanel, PricingPlan, PricingPlans } from "@/components/ui/pricing-pair";<PricingPair>
<PricingPanel tone="brand" eyebrow="One-time purchase" title="Card kit">
<PricingFeatures items={["Card designs, lifetime updates", "A license key for your team"]} />
</PricingPanel>
<PricingPanel eyebrow="Monthly subscription" title="Accounts">
<PricingPlans label="Account plans">
{plans.map((p) => <PricingPlan key={p.id} name={p.name} amount={p.amount} currency="USD" period="/mo" description={p.text} />)}
</PricingPlans>
</PricingPanel>
</PricingPair>API reference
PricingPair
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | None | Two PricingPanels: what is bought once, then what is subscribed to. |
PricingPanel
| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | ReactNode | None | The small label above the title. Capitals in English; Arabic is never tracked. |
title | ReactNode | None | The product's name, a heading. |
headingLevel | 2 | 3 | 4 | 3 | The title's heading level under the section's heading. |
tone | "default" | "brand" | "default" | brand puts the panel on the sky band. |
PricingPlan
| Prop | Type | Default | Description |
|---|---|---|---|
name | ReactNode | None | The plan's name. |
amount | number | None | The amount from your pricing data; no amount is written into the component. |
currency | string | None | The ISO 4217 code from your data (USD, SAR). |
period | ReactNode | None | After the amount, smaller (“/mo”). Leave it out for a free plan. |
description | ReactNode | None | What the plan includes, one line. |
PricingPlans
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | None | Names the list for screen readers (“Account plans”). |
PricingFeatures
| Prop | Type | Default | Description |
|---|---|---|---|
items | ReactNode[] | None | What is included, one line each. |
Accessibility
ARIA
- Each panel is a
sectionwith a heading; the plans are a list named bylabel; the features are a list. - An amount and its currency are one isolated unit, so their order never flips inside Arabic text.
Arabic and RTL notes
Mirrors
- The first panel sits on the right, and the rules between panels and between plans sit at their inline start.
- The check sits at the start of each line.
Does not mirror
- The check doesn't mirror, and the amount keeps its language's order.
- Numerals
- Prices are always in Western digits (
123) in both languages, whatever the numerals setting, to match the checkout. The currency comes from your data. - Arabic typography
- Title
body-20Medium, amountheading-32, eyebrowlabel-12in English andlabel-14in Arabic. - Mixed-direction text
- The amount is isolated; Latin product names are isolated inside Arabic text.