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.

vue
<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.

$0/month
  • 1 project
  • Community support
  • Custom domains

Pro

Most popular

For small teams shipping together.

$29/month

billed annually

  • Unlimited projects
  • Custom domains
  • Priority support

14 days free. No credit card required.

Enterprise

For organisations with a procurement team.

Custom
  • 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

$0/month
  • 1 project

Pro

$29/month
  • Unlimited projects

Team

$79/month
  • Everything in Pro

Enterprise

Custom
  • Everything in Team

Free

$0/month
  • 1 project

Pro

$29/month
  • Unlimited projects

Team

$79/month
  • Everything in Pro

Enterprise

Custom
  • 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.

$400/month
  • 1 hour first response
  • Named support engineer
  • Quarterly review call

Lifetime

Limited

Pay once, use it forever.

$499$399

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.

$0/month
  • 1 project
  • Community support
  • Custom domains

Pro

Most popular

For small teams shipping together.

$29/month

billed annually

  • Unlimited projects
  • Custom domains
  • Priority support

14 days free. No credit card required.

Enterprise

For organisations with a procurement team.

Custom
  • Everything in Pro
  • SSO and audit logs
  • 99.9% uptime SLA

Free

For trying things out.

$0/month
  • 1 project
  • Community support
  • Custom domains

Pro

Most popular

For small teams shipping together.

$29/month

billed annually

  • Unlimited projects
  • Custom domains
  • Priority support

14 days free. No credit card required.

Enterprise

For organisations with a procurement team.

Custom
  • 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

$0/month
  • 1 project

Pro

$29/month
  • Unlimited projects

Team

$79/month
  • Everything in Pro

Free

$0/month
  • 1 project

Pro

$29/month
  • Unlimited projects

Team

$79/month
  • 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

$0/month

For trying things out.

Pro

$29/month

For small teams shipping together.

Team

$99/month

For a company with a finance department.

Free

$0/month

For trying things out.

Pro

$29/month

For small teams shipping together.

Team

$99/month

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

$0/month
  • 1 project

Pro

$29/month
  • Unlimited projects

Team

$79/month
  • 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

$0/month

For trying things out.

Pro

$29/month

For small teams shipping together.

Team

$99/month

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.

$48.00/month

12 seats × $4

  • Unlimited projects
  • Usage-based billing

Flat

Most popular

One price, however many people join.

$149/month
  • 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

Prop
Type
Default
Description
PricingPlanItem[]
—
The plans to render, left to right. Each entry takes every `PricingPlan` prop except `orientation` and `layout`, which the row owns because they also decide the columns and the gap — so `highlight`, `badge` and `button` are per plan, while `color` falls back to this component's own when a plan doesn't set it.
1 | 2 | 3 | 4 | "auto"
'auto'
How many plans sit side by side from the `lg` breakpoint up. `auto` fits as many 240px columns as the container has room for, which is what you want both for a plain `plans` array and for hand-written plans in the default slot — a fixed number can't count the latter.
"vertical" | "horizontal"
'vertical'
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.
boolean
false
Grows any plan marked `highlight` slightly above its neighbours from `md` up. Off by default: it only reads as emphasis where the plans are actually side by side.
"neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending"
'primary'
Accent color for plans that don't set their own.
"default" | "compact"
'default'
Passed to every plan, along with a tighter gap to match. `compact` shows each plan's `description` in place of its features. Combines with `orientation`: `compact` `horizontal` is a stack of one-line switcher rows, `compact` `vertical` a lineup of small cards.
"subtle" | "soft" | "outline"
'subtle'
The card surface for plans that don't set their own — `subtle`, `soft` or `outline`, as on `PricingPlan`. Left unset, each plan falls back to its own default, so an `app.config.ts` default for `PricingPlan` still applies inside the row.

Slots

Slot
default

Emits

Event
Payload
Description
select
[plan: PricingPlanItem, index: number]
Fires when a plan's call-to-action button is clicked, with that plan and its index.

Types

ts
type Color = "neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending";
ts
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;
}
ts
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";
}