PricingPlan

A single plan on a pricing page — name, price, a `CheckList` of what it includes, and a call to action. `highlight` marks the recommended one, which colors the card and turns its button solid.

vue
<UiPricingPlan />

Options

One block per prop — what it does, and what it looks like set.

Title

title is the plan's name, and the first thing read on the card. Keep it to the word a customer would use in a sentence — 'I'm on Pro' — not a marketing phrase.

Pro

Description

description is the one line under the name saying who the plan is for. It's what saves a reader from comparing four feature lists to work out which column is theirs.

Pro

For small teams shipping together.

Badge

badge is the pill beside the name — 'Most popular', 'Save 20%'. A bare string takes the plan's own color; pass an object to color it yourself. It's a claim about the plan, so use it on exactly one plan in a row, and pair it with highlight.

Pro

Most popular

A bare string.

Team

Save 20%

An object, colored.

Price

price is a string, never a number: currency symbol, separators and locale are the app's to decide, and a plan whose price is 'Free' or 'Custom' isn't a number at all. Format it however your pricing page already does.

Free

$0

Pro

$29

Enterprise

Custom

Discount

discount is what the plan costs right now, 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 on its own is the ordinary case. It's named after the offer rather than after the number, matching Nuxt UI.

Pro

$29/month

Pro

$29$19/month

price is the regular figure and discount is what it drops to, so the *smaller* number goes in discount and a plan on offer sets both. Setting discount on its own renders it as the only price, with nothing struck out.

Billing cycle

billingCycle is what the price buys, printed right after it — '/month', '/seat', '/1,000 credits'. Without it a bare figure means nothing; with it the price row reads as one sentence.

Pro

$29/month

Team

$12/seat/month

Billing period

billingPeriod is when the money actually moves, in small print under the price. It's the line that keeps a monthly figure honest when the plan is billed a year at a time — the single most common complaint about a pricing page. A compact plan has no room for a second line, so it hangs the same text off an Info beside the billing cycle instead.

Pro

$29$23/month

billed annually

Pro

$29$23/month

For growing teams

Features

features renders as a CheckList. A bare string is an included feature; an object is a full CheckListItem, so checked: false tones a feature down as something this plan leaves out, and description adds a second line under it.

Free

$0
  • 1 project
  • Community support
  • Custom domains
  • SSO and audit logs

Pro

$29
  • Unlimited projects
  • Custom domainsUp to 10, with automatic certificates
  • Priority support
  • SSO and audit logs

Feature strings are turned into CheckListItems, so everything CheckList accepts works here — { label, description, checked }. A checked: false feature stays in the list rather than disappearing from it, which is what keeps two plans lining up row for row.

Button

button is the call to action. Give it a to for a plain link, or leave it off and handle select when signing up has to run something first. Its color follows the plan and its variant follows highlight, so a row of plans gets one loud button and the rest quiet without setting either.

Pro

$29

Enterprise

Custom

Terms

terms is the small print under the button — 'No credit card required', 'Prices exclude VAT', 'Cancel any time'. It belongs under the button because that's where the hesitation is.

Pro

$29/month

14 days free. No credit card required.

Highlight

highlight marks the plan you're recommending: the same card variant in the plan's color, and a button that goes solid unless it sets its own variant. Exactly one plan in a row should have it — two recommendations are none.

Free

$0
  • 1 project

Pro

Most popular
$29
  • Unlimited projects

Scale

scale grows the card slightly above its neighbours from md up. It only means anything beside other plans, so PricingPlans applies it to the highlighted plan for you rather than making you set it per card.

Free

$0/month
  • 1 project

Pro

Most popular
$29/month
  • Unlimited projects

Team

$79/month
  • Everything in Pro

scale is a transform, so the card grows out of its grid cell instead of pushing its neighbours. Give the row a little vertical padding (class="py-sm") or the top of the grown card gets clipped by whatever sits above it.

Orientation

horizontal moves the price and button beside the features instead of under them — for a plan that stands on its own, like a lifetime deal or an add-on above a comparison table. It stacks back to vertical below md, so it's safe on a phone. Both densities have both directions, so it combines with layout rather than excluding it.

Lifetime

Limited

Pay once, use it forever.

$499$399

one-time payment

  • Every feature in Pro
  • All future updates
  • Priority support

Color

color is the accent, not the card: the highlighted card, the feature checkmarks, the button, and an uncolored badge. The card itself only takes the color when the plan is highlighted.

neutral

$29
  • Included
  • Not included

primary (default)

$29
  • Included
  • Not included

secondary

$29
  • Included
  • Not included

success

$29
  • Included
  • Not included

error

$29
  • Included
  • Not included

warning

$29
  • Included
  • Not included

info

$29
  • Included
  • Not included

pending

$29
  • Included
  • Not included

color tints the card itself only when the plan is also highlighted. On the rest it stays an accent — checkmarks, button, badge — because a row of plans each tinted a different color reads as decoration rather than as a recommendation.

Layout

layout sets the density. compact tightens the padding, drops the type a size and collapses the features to a dot-separated summary instead of a CheckList — for wherever the plans are a control rather than a pitch. It combines with orientation: horizontal gives the one-line switcher row, vertical a small card that still fits a lineup.

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 is the card itself, named after Card's variants. subtle is a raised panel with a faint ring; soft a flat tint with no ring, for plans on a page that's already busy; outline just the ring on the page background, the quietest of the three. A highlighted plan keeps its variant and only changes colour.

Free

For trying things out.

$0/month
  • 1 project
  • Community support

Pro

For small teams shipping together.

$29/month
  • Unlimited projects
  • Priority support

Team

For a company with a finance department.

$99/month
  • Everything in Pro
  • SSO & audit logs

Free

For trying things out.

$0/month
  • 1 project
  • Community support

Pro

For small teams shipping together.

$29/month
  • Unlimited projects
  • Priority support

Team

For a company with a finance department.

$99/month
  • Everything in Pro
  • SSO & audit logs

Free

For trying things out.

$0/month
  • 1 project
  • Community support

Pro

For small teams shipping together.

$29/month
  • Unlimited projects
  • Priority support

Team

For a company with a finance department.

$99/month
  • Everything in Pro
  • SSO & audit logs

Examples

The component in real use: compositions that answer "how do I build X with this", rather than one prop at a time.

A monthly / annual toggle

The component never derives one price from another — it renders the strings it's given. Keep the billing period in your own state and compute the price props from it, which is also what lets the annual figure carry its own discount and billingPeriod.

Free

For trying things out.

$0/month
  • 1 project
  • Community support

Pro

Save 17%

For small teams shipping together.

$29$24/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

Prices are strings, and nothing here charges anyone

PricingPlan formats no numbers and calls no API. It renders the price strings you hand it and emits select when its button is clicked — the checkout, the subscription, the currency and the locale are all yours.


API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
string
—
The plan's name — 'Free', 'Pro', 'Enterprise'.
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.
string | PricingPlanBadge
—
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.
string
—
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.
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.
string
—
What the price buys, printed right after it — '/month', '/seat', '/1,000 credits'.
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.
(string | CheckListItem)[]
—
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.
PricingPlanButton
—
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.
string
—
Small print under the button — 'No credit card required', 'Prices exclude VAT'.
boolean
false
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.
boolean
false
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.
"vertical" | "horizontal"
'vertical'
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.
"neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending"
'primary'
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`.
"default" | "compact"
'default'
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.
"subtle" | "soft" | "outline"
'subtle'
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`.

Slots

Slot
header
price
default
features
footer

Emits

Event
Payload
Description
select
[]
Fires when the call-to-action button is clicked, including when it navigates.

Types

ts
type Color = "neutral" | "primary" | "secondary" | "success" | "error" | "warning" | "info" | "pending";
ts
interface PricingPlanBadge {
    /**
     * The pill's text — 'Most popular', 'Save 20%'.
     */
    label: string;

    /**
     * Defaults to the plan's own `color`.
     */
    color?: Color;

    /**
     * @defaultValue 'soft'
     */
    variant?: "solid" | "soft";
}
ts
interface PricingPlanButton {
    /**
     * The button's text — 'Get started', 'Contact sales'.
     */
    label: string;

    /**
     * Route or URL to navigate to. Leave it off and handle `select` instead when signing up needs
     * to run something first (open a checkout, create a subscription).
     */
    to?: string;

    /**
     * The target attribute for the link (e.g. '_blank').
     */
    target?: string;

    /**
     * Name of the icon displayed inside the button.
     */
    icon?: string;

    /**
     * Defaults to the plan's own `color` on a highlighted plan and `neutral` on the rest — so the
     * recommended plan owns the only coloured call to action in the row.
     */
    color?: Color;

    /**
     * Defaults to `solid` on a highlighted plan and `subtle` on the rest — which is what makes the
     * recommended plan's call to action the loudest one in a row. A `disabled` button stays
     * `subtle` either way: `Button` dims a disabled control to 50%, and half a solid fill reads as
     * broken rather than as "you are already on this plan".
     */
    variant?: "solid" | "subtle" | "soft" | "ghost";

    /**
     * @defaultValue 'md'
     */
    size?: "sm" | "md" | "lg";

    /**
     * Disables the button — for the plan the viewer is already on.
     * @defaultValue false
     */
    disabled?: boolean;
}
ts
interface CheckListItem {
    /**
     * Text label for this item.
     */
    label: string;

    /**
     * Secondary text shown below the label.
     */
    description?: string;

    /**
     * Identity used for `v-model` when the list is interactive. Falls back to the item's index.
     */
    value?: string | number;

    /**
     * Whether this item is checked. Used directly when the list isn't interactive; only used as the
     * initial state when interactive and uncontrolled.
     * @defaultValue true
     */
    checked?: boolean;

    /**
     * Disables interaction with this item. Has no effect on a non-interactive list.
     * @defaultValue false
     */
    disabled?: boolean;
}