Blocks
PricingPlans
The responsive row a set of `PricingPlan`s sits in — pass a `plans` array or write the cards out yourself, and it handles the columns, the equal heights and scaling the highlighted plan above its neighbours.
<UiPricingPlans />Options
One block per prop — what it does, and what it looks like set.
Plans
plans is the row, left to right. Each entry takes every PricingPlan prop — so highlight, badge and button are per plan — plus a value used as the key and handed back by select. color falls back to this component's when a plan doesn't set it; orientation and layout are the row's alone, since they also pick the columns.
Free
For trying things out.
- 1 project
- Community support
- Custom domains
Pro
Most popularFor small teams shipping together.
billed annually
- Unlimited projects
- Custom domains
- Priority support
14 days free. No credit card required.
Enterprise
For organisations with a procurement team.
- Everything in Pro
- SSO and audit logs
- 99.9% uptime SLA
value is the only field in a plan entry that isn't a PricingPlan prop — it's the list key and what select hands back. Everything else is passed straight through to the card.
Columns
auto fits as many 240px columns as the container has room for, which is right for both a plans array and hand-written cards in the default slot — a counted class can't see the latter. Pin it to a number when you want a specific break, like four plans going 2×2 on a tablet before lining up on a wide screen.
Free
- 1 project
Pro
- Unlimited projects
Team
- Everything in Pro
Enterprise
- Everything in Team
Free
- 1 project
Pro
- Unlimited projects
Team
- Everything in Pro
Enterprise
- Everything in Team
columns="auto" is a CSS auto-fit grid, not a count: it fits as many 240px tracks as the container has room for and collapses the ones it can't fill. That's why it works for cards written into the default slot, which no counted class could see.
Orientation
orientation is passed to every plan. horizontal also forces a single column, since a horizontal plan is a full-width row rather than a card in a lineup — which makes it the shape for an add-on or a one-off purchase listed under the main plans.
Premium support
A named engineer and a one-hour response time.
- 1 hour first response
- Named support engineer
- Quarterly review call
Lifetime
LimitedPay once, use it forever.
one-time payment
- Every feature in Pro
- All future updates
Scale
scale grows whichever plan is marked highlight slightly above its neighbours from md up. It's off by default because it only reads as emphasis where the plans are genuinely side by side — on one column it just makes a card wider than the rest.
Free
For trying things out.
- 1 project
- Community support
- Custom domains
Pro
Most popularFor small teams shipping together.
billed annually
- Unlimited projects
- Custom domains
- Priority support
14 days free. No credit card required.
Enterprise
For organisations with a procurement team.
- Everything in Pro
- SSO and audit logs
- 99.9% uptime SLA
Free
For trying things out.
- 1 project
- Community support
- Custom domains
Pro
Most popularFor small teams shipping together.
billed annually
- Unlimited projects
- Custom domains
- Priority support
14 days free. No credit card required.
Enterprise
For organisations with a procurement team.
- Everything in Pro
- SSO and audit logs
- 99.9% uptime SLA
Color
color is the accent every plan inherits unless it sets its own — the checkmarks, the buttons, and the highlighted card.
Free
- 1 project
Pro
- Unlimited projects
Team
- Everything in Pro
Free
- 1 project
Pro
- Unlimited projects
Team
- Everything in Pro
Layout
layout sets the density. compact drops every plan a size and tightens the gap to match. Reach for it wherever the plans are a control rather than a pitch — an account panel, a checkout step, an upgrade dialog. It combines with orientation: vertical keeps the lineup and just shrinks it, horizontal turns each plan into a single switcher row.
Free
For trying things out.
Pro
For small teams shipping together.
Team
For a company with a finance department.
Free
For trying things out.
Pro
For small teams shipping together.
Team
For a company with a finance department.
Variant
variant sets the card for every plan that doesn't set its own: subtle, soft or outline, as on PricingPlan. A plan's own variant wins, so one can stand apart from the row.
Free
- 1 project
Pro
- Unlimited projects
Team
- Everything in Pro
Examples
The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.
A compact plan switcher
Inside an account or billing panel there's no room for a lineup of cards, and no selling left to do — the reader already knows the plans. layout='compact' is that view: one row each, the current plan marked highlight with its button disabled, and select telling you which one they moved to.
Plans
Free
For trying things out.
Pro
For small teams shipping together.
Team
For a company with a finance department.
Writing the cards out yourself
The default slot replaces the generated cards and keeps the layout, which is how you reach a single plan's slots — a custom price row, an extra control between the description and the features. v-for over your own array inside it if you'd rather not repeat the markup.
Metered
Pay for what you actually use.
12 seats × $4
- Unlimited projects
- Usage-based billing
Flat
Most popularOne price, however many people join.
- Unlimited projects
- Unlimited seats
The default slot replaces the generated cards entirely — plans is ignored while it's in use, and select fires from your own PricingPlans rather than from this component.
Equal heights come from the grid, not the cards
Plans stretch to the tallest one in the row, and each card's button block is pushed to the bottom — so the calls to action line up even when one plan lists twice as many features as its neighbour.
API Reference
Generated from the component's source — props, slots and emits as the component actually declares them.
Props
PricingPlanItem[]1 | 2 | 3 | 4 | "auto"'auto'"vertical" | "horizontal"'vertical'booleanfalse"neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending"'primary'"default" | "compact"'default'"subtle" | "soft" | "outline"'subtle'Slots
defaultEmits
select[plan: PricingPlanItem, index: number]Types
type Color = "neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending";interface PricingPlanItem {
/**
* Identity for this plan — the list key, and what you match on in a `select` handler. Falls back
* to `title`, then to the index.
*/
value?: string | number;
}interface PricingPlanProps {
/**
* The plan's name — 'Free', 'Pro', 'Enterprise'.
*/
title?: string;
/**
* One line on who the plan is for, under the name — and in `layout="compact"`, on its own line
* where the feature list would otherwise be.
*/
description?: string;
/**
* A pill beside the name, for 'Most popular' or 'Save 20%'. A bare string uses the plan's own
* `color`; pass an object to set the pill's color yourself.
*/
badge?: string | PricingPlanBadge;
/**
* The headline figure, formatted however you want it ('$29', '€29', 'Free', 'Custom') — the
* component never formats a number, since currency and locale are the app's to decide.
*/
price?: string;
/**
* The price this plan is *currently* going for, when that's less than `price`. Setting it strikes
* `price` out and promotes this to the headline figure — so a plan on offer sets both, and
* `price` alone is the regular case.
*/
discount?: string;
/**
* What the price buys, printed right after it — '/month', '/seat', '/1,000 credits'.
*/
billingCycle?: string;
/**
* When the money actually moves, under the price — 'billed annually', 'billed monthly'. This is
* the line that keeps an annual-discounted price honest. `layout="compact"` has no room for a
* second line under the price, so it hangs this off an `Info` popover beside the billing cycle
* rather than printing it.
*/
billingPeriod?: string;
/**
* What the plan includes, as a `CheckList`. A bare string is a checked item; an object is a full
* `CheckListItem`, so `checked: false` marks what this plan leaves out and `description` adds a
* second line under a feature. Not rendered by `layout="compact"`, which shows the plan's
* `description` in that space instead.
*/
features?: (string | CheckListItem)[];
/**
* The call to action under the features. Omit it for a plan that isn't self-serve, or replace
* the whole block with the `footer` slot.
*/
button?: PricingPlanButton;
/**
* Small print under the button — 'No credit card required', 'Prices exclude VAT'.
*/
terms?: string;
/**
* Marks this as the recommended plan: the card keeps its `variant` and takes the plan's `color`
* — a tinted `subtle` or `soft` card, a coloured `outline` ring. The button follows too, taking
* that `color` and going `solid` — the rest stay `neutral` and `subtle` — unless it sets its own.
* @defaultValue false
*/
highlight?: boolean;
/**
* Grows the card slightly above its neighbours from the `md` breakpoint up. Only worth it beside
* other plans — `PricingPlans` applies it to the highlighted plan for you.
* @defaultValue false
*/
scale?: boolean;
/**
* Which way the card runs. `vertical` is the usual one in a row of plans; `horizontal` puts the
* price and button beside the features instead, for a plan that stands on its own — a single
* lifetime deal, an add-on above a comparison table. Both densities have both directions: a
* `compact` `horizontal` plan is the one-line switcher row, a `compact` `vertical` one is a
* small card that still fits a lineup.
* @defaultValue 'vertical'
*/
orientation?: "vertical" | "horizontal";
/**
* The accent color: the highlighted card, the feature checkmarks, an unstyled `badge`, and the
* button on the highlighted plan — every other plan's button is `neutral`.
* @defaultValue 'primary'
*/
color?: Color;
/**
* The density. `compact` tightens the padding, drops the type a size, shows the plan's
* `description` in place of its feature checklist and moves `billingPeriod` into an `Info`
* beside the billing cycle — for a plan switcher inside a settings panel, where the pricing page
* has already done the selling. Combines with `orientation`: horizontal gives the one-line row,
* vertical a small card.
* @defaultValue 'default'
*/
layout?: "default" | "compact";
/**
* The card's surface, named after `Card`'s variants. `subtle` is a raised panel with a faint
* ring; `soft` a flat tint with no ring, for plans sitting on an already-busy page; `outline`
* the page background with only the ring, the quietest of the three. A highlighted plan keeps its
* variant and only changes colour, to the plan's `color`.
* @defaultValue 'subtle'
*/
variant?: "subtle" | "soft" | "outline";
}