PricingPlans

Display a list of pricing plans in a responsive grid layout.

Usage

The PricingPlans component provides a flexible layout to display a list of PricingPlan components using either the default slot or the plans prop.

<template>
  <UPricingPlans>
    <UPricingPlan
      v-for="(plan, index) in plans"
      :key="index"
      v-bind="plan"
    />
  </UPricingPlans>
</template>
The grid columns will be automatically calculated based on the number of plans, this works with the plans prop but also with the default slot.

Plans

Use the plans prop as an array of objects with the properties of the PricingPlan component.

Solo
Tailored for indie hackers.
$249
  • One developer
  • Lifetime access
Startup
Best suited for small teams.
$499
  • Up to 5 developers
  • Everything in Solo
Organization
Ideal for larger teams and organizations.
$999
  • Up to 20 developers
  • Everything in Startup
<script setup lang="ts">
const plans = ref([
  {
    title: 'Solo',
    description: 'Tailored for indie hackers.',
    price: '$249',
    features: [
      'One developer',
      'Lifetime access'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Startup',
    description: 'Best suited for small teams.',
    price: '$499',
    features: [
      'Up to 5 developers',
      'Everything in Solo'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Organization',
    description: 'Ideal for larger teams and organizations.',
    price: '$999',
    features: [
      'Up to 20 developers',
      'Everything in Startup'
    ],
    button: {
      label: 'Buy now'
    }
  }
])
</script>

<template>
  <UPricingPlans :plans="plans" />
</template>

Orientation

Use the orientation prop to change the orientation of the PricingPlans. Defaults to horizontal.

Solo
Tailored for indie hackers.
  • One developer
  • Lifetime access
$249
Startup
Best suited for small teams.
  • Up to 5 developers
  • Everything in Solo
$499
Organization
Ideal for larger teams and organizations.
  • Up to 20 developers
  • Everything in Startup
$999
<script setup lang="ts">
const plans = ref([
  {
    title: 'Solo',
    description: 'Tailored for indie hackers.',
    price: '$249',
    features: [
      'One developer',
      'Lifetime access'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Startup',
    description: 'Best suited for small teams.',
    price: '$499',
    features: [
      'Up to 5 developers',
      'Everything in Solo'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Organization',
    description: 'Ideal for larger teams and organizations.',
    price: '$999',
    features: [
      'Up to 20 developers',
      'Everything in Startup'
    ],
    button: {
      label: 'Buy now'
    }
  }
])
</script>

<template>
  <UPricingPlans orientation="vertical" :plans="plans" />
</template>
When using the plans prop instead of the default slot, the orientation of the plans is automatically reversed, horizontal to vertical and vice versa.

Compact

Use the compact prop to reduce the padding between the plans when one of the plans is scaled for a better visual balance.

Solo
Tailored for indie hackers.
$249
  • One developer
  • Lifetime access
Startup
Best suited for small teams.
$499
  • Up to 5 developers
  • Everything in Solo
Organization
Ideal for larger teams and organizations.
$999
  • Up to 20 developers
  • Everything in Startup
<script setup lang="ts">
const plans = ref([
  {
    title: 'Solo',
    description: 'Tailored for indie hackers.',
    price: '$249',
    features: [
      'One developer',
      'Lifetime access'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Startup',
    description: 'Best suited for small teams.',
    price: '$499',
    scale: true,
    features: [
      'Up to 5 developers',
      'Everything in Solo'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Organization',
    description: 'Ideal for larger teams and organizations.',
    price: '$999',
    features: [
      'Up to 20 developers',
      'Everything in Startup'
    ],
    button: {
      label: 'Buy now'
    }
  }
])
</script>

<template>
  <UPricingPlans compact :plans="plans" />
</template>

Scale

Use the scale prop to adjust the spacing between the plans when one of the plans is scaled for a better visual balance.

Solo
Tailored for indie hackers.
$249
  • One developer
  • Lifetime access
Startup
Best suited for small teams.
$499
  • Up to 5 developers
  • Everything in Solo
Organization
Ideal for larger teams and organizations.
$999
  • Up to 20 developers
  • Everything in Startup
<script setup lang="ts">
const plans = ref([
  {
    title: 'Solo',
    description: 'Tailored for indie hackers.',
    price: '$249',
    features: [
      'One developer',
      'Lifetime access'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Startup',
    description: 'Best suited for small teams.',
    price: '$499',
    scale: true,
    features: [
      'Up to 5 developers',
      'Everything in Solo'
    ],
    button: {
      label: 'Buy now'
    }
  },
  {
    title: 'Organization',
    description: 'Ideal for larger teams and organizations.',
    price: '$999',
    features: [
      'Up to 20 developers',
      'Everything in Startup'
    ],
    button: {
      label: 'Buy now'
    }
  }
])
</script>

<template>
  <UPricingPlans scale :plans="plans" />
</template>

Examples

While these examples use Nuxt Content v3, the components can be integrated with any content management system.

Within a page

Use the PricingPlans component in a page to create a pricing page:

pages/pricing/index.vue
<script setup lang="ts">
const { data: plans } = await useAsyncData('plans', () => queryCollection('plans').all())
</script>

<template>
  <UPage>
    <UPageHero title="Pricing" />

    <UPageBody>
      <UContainer>
        <UPricingPlans :plans="plans" />
      </UContainer>
    </UPageBody>
  </UPage>
</template>
In this example, the plans are fetched using queryCollection from the @nuxt/content module.

API

Props

Prop Default Type
as

'div'

any

The element or component this component should render as.

plans

PricingPlanProps[]

orientation

'horizontal'

"vertical" | "horizontal"

The orientation of the pricing plans.

compact

false

boolean

When true, the plans will be displayed without gap.

scale

false

boolean

When true, the plans will be displayed with a larger gap. Useful when one plan is scaled. Doesn't work with compact.

Slots

Slot Type
default

{}

Theme

app.config.ts
export default defineAppConfig({
  uiPro: {
    pricingPlans: {
      base: 'flex flex-col gap-y-8',
      variants: {
        orientation: {
          horizontal: 'lg:grid lg:grid-cols-[repeat(var(--count),minmax(0,1fr))]',
          vertical: ''
        },
        compact: {
          false: 'gap-x-8'
        },
        scale: {
          true: ''
        }
      },
      compoundVariants: [
        {
          compact: false,
          scale: true,
          class: 'lg:gap-x-13'
        }
      ]
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      uiPro: {
        pricingPlans: {
          base: 'flex flex-col gap-y-8',
          variants: {
            orientation: {
              horizontal: 'lg:grid lg:grid-cols-[repeat(var(--count),minmax(0,1fr))]',
              vertical: ''
            },
            compact: {
              false: 'gap-x-8'
            },
            scale: {
              true: ''
            }
          },
          compoundVariants: [
            {
              compact: false,
              scale: true,
              class: 'lg:gap-x-13'
            }
          ]
        }
      }
    })
  ]
})