PricingPlans

GitLab
Exiba uma lista de planos de preços em um layout de grade responsivo.

Uso

O componente PricingPlans oferece um layout flexível para exibir uma lista de componentes PricingPlan usando o slot padrão ou a prop plans.

<template>
  <NPricingPlans>
    <NPricingPlan
      v-for="(plan, index) in plans"
      :key="index"
      v-bind="plan"
    />
  </NPricingPlans>
</template>
As colunas da grade são calculadas automaticamente com base no número de planos; isso funciona com a prop plans, mas também com o slot padrão.

Planos

Use a prop plans como um array de objetos com as propriedades do componente PricingPlan.

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">
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans :plans="plans" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans :plans="plans" />
</template>

Orientação

Use a prop orientation para alterar a orientação do PricingPlans. O padrão é 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">
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans orientation="vertical" :plans="plans" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans orientation="vertical" :plans="plans" />
</template>
Ao usar a prop plans em vez do slot padrão, a orientation dos planos é invertida automaticamente, de horizontal para vertical e vice-versa.

Compacto

Use a prop compact para reduzir o espaçamento entre os planos quando um deles está escalado, para um melhor equilíbrio visual.

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">
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans compact :plans="plans" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans compact :plans="plans" />
</template>

Escala

Use a prop scale para ajustar o espaçamento entre os planos quando um deles está escalado, para um melhor equilíbrio visual.

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">
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans scale :plans="plans" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { PricingPlanProps } from '@nitro/ui'

const plans = ref<PricingPlanProps[]>([
  {
    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>
  <NPricingPlans scale :plans="plans" />
</template>

Exemplos

Embora estes exemplos usem o Nuxt Content, os componentes podem ser integrados a qualquer sistema de gerenciamento de conteúdo.

Dentro de uma página

Use o componente PricingPlans em uma página para criar uma página de preços:

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

<template>
  <NPage>
    <NPageHero title="Pricing" />

    <NPageBody>
      <NContainer>
        <NPricingPlans :plans="plans" />
      </NContainer>
    </NPageBody>
  </NPage>
</template>
Neste exemplo, os plans são buscados usando queryCollection do módulo @nuxt/content.

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

plans PricingPlanProps[]
orientation'horizontal' "horizontal" | "vertical"

The orientation of the pricing plans.

compactfalseboolean

When true, the plans will be displayed without gap.

scalefalseboolean

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

ui { base?: any; }

Slots

Slot Type
badge{ ui: object; }
title{}
description{}
price{}
discount{}
billing{ ui: object; }
features{}
button{ ui: object; }
header{}
body{}
footer{}
tagline{}
terms{}
default{}

Tema

app.config.ts
export default defineAppConfig({
  ui: {
    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 '@nitro/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        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'
            }
          ]
        }
      }
    })
  ]
})

Changelog

No recent changes