Menu

Change language

GitHub repo

Pricing Tier Comparison Matrix

blockmarketing

Comprehensive pricing tier comparison matrix with billing cycle discount toggles, prominent recommended plan, and granular capability matrix table.

Installation

$npx shadcn-vue@latest add https://uipkge.dev/r/vue/pricing-tier-comparison-matrix.json
Named registry:npx shadcn-vue@latest add @uipkge/pricing-tier-comparison-matrixInstalls to:app/components/blocks/

Variants

Loading interactive previews…

Schema

Type aliases exported from this item's source. Use these to shape the data you pass in.

Plan
interface Plan {
  id: string
  name: string
  description: string
  monthlyPrice: number
  annualPrice: number
  highlight: boolean
  badge?: string
  ctaText: string
  ctaVariant: 'default' | 'outline' | 'secondary'
}
FeatureComparisonRow
interface FeatureComparisonRow {
  category: string
  features: {
    name: string
    tooltip: string
    community: boolean | string
    pro: boolean | string
    enterprise: boolean | string
  }[]
}

npm dependencies

Files installed (1)

  • app/components/blocks/PricingTierComparisonMatrix.vue11.3 kB
    <script setup lang="ts">
    import { ref } from 'vue'
    import { ArrowRight, Check, Minus, ShieldCheck } from 'lucide-vue-next'
    import { Badge } from '@/components/ui/badge'
    import { Button } from '@/components/ui/button'
    import { Card } from '@/components/ui/card'
    
    type BillingCycle = 'monthly' | 'annual'
    
    const billing = ref<BillingCycle>('annual')
    
    interface Plan {
      id: string
      name: string
      description: string
      monthlyPrice: number
      annualPrice: number
      highlight: boolean
      badge?: string
      ctaText: string
      ctaVariant: 'default' | 'outline' | 'secondary'
    }
    
    const plans: Plan[] = [
      {
        id: 'community',
        name: 'Community OSS',
        description: 'For indie hackers and developers building open source products.',
        monthlyPrice: 0,
        annualPrice: 0,
        highlight: false,
        ctaText: 'Start Building Free',
        ctaVariant: 'outline',
      },
      {
        id: 'pro',
        name: 'Pro Team',
        description: 'For growing startup engineering teams that require high velocity.',
        monthlyPrice: 29,
        annualPrice: 24,
        highlight: true,
        badge: 'Most Popular',
        ctaText: 'Claim Pro License',
        ctaVariant: 'default',
      },
      {
        id: 'enterprise',
        name: 'Enterprise Scale',
        description: 'Dedicated registry syncing, SSO, SOC2 compliance audits, and SLA.',
        monthlyPrice: 119,
        annualPrice: 99,
        highlight: false,
        ctaText: 'Talk to Sales',
        ctaVariant: 'outline',
      },
    ]
    
    interface FeatureComparisonRow {
      category: string
      features: {
        name: string
        tooltip: string
        community: boolean | string
        pro: boolean | string
        enterprise: boolean | string
      }[]
    }
    
    const comparisonData: FeatureComparisonRow[] = [
      {
        category: 'Registry & Core Primitives',
        features: [
          {
            name: 'Full AST Component Source Access',
            tooltip: 'Raw SFC and TSX source files copied directly into your repository.',
            community: true,
            pro: true,
            enterprise: true,
          },
          {
            name: 'Dual-Framework Parity (Vue + React)',
            tooltip: 'Identical DOM semantics and CVA tokens across both ecosystems.',
            community: true,
            pro: true,
            enterprise: true,
          },
          {
            name: 'Curated Marketing & SaaS Blocks',
            tooltip: 'Access to 450+ production-grade unbundled layout blocks.',
            community: '100+ Blocks',
            pro: 'All 450+ Blocks',
            enterprise: 'All Blocks + Custom',
          },
          {
            name: 'Tailwind CSS v4 OKLCH Token System',
            tooltip: 'Hardware-calibrated color spaces and spring curves.',
            community: true,
            pro: true,
            enterprise: true,
          },
        ],
      },
      {
        category: 'Enterprise & Security Compliance',
        features: [
          {
            name: 'Private Registry Mirroring',
            tooltip: 'Host your organization’s customized internal registry behind a firewall.',
            community: false,
            pro: '1 Private Repo',
            enterprise: 'Unlimited Private Hubs',
          },
          {
            name: 'SOC2 & ISO 27001 Audit Packs',
            tooltip: 'Pre-certified security documentation and architecture proofs.',
            community: false,
            pro: false,
            enterprise: true,
          },
          {
            name: 'Guaranteed 99.99% Registry CDN SLA',
            tooltip: 'Global multi-region edge distribution uptime guarantee.',
            community: false,
            pro: '99.9% SLA',
            enterprise: '99.99% High Availability',
          },
          {
            name: 'Dedicated Design Engineering Support',
            tooltip: 'Direct Slack / Discord channel with core design system maintainers.',
            community: false,
            pro: 'Priority Email',
            enterprise: 'Dedicated Slack Channel',
          },
        ],
      },
    ]
    </script>
    
    <template>
      <section
        data-slot="pricing-tier-comparison-matrix"
        class="bg-background relative overflow-hidden px-4 py-16 sm:px-6 sm:py-24 lg:px-8"
      >
        <div class="mx-auto max-w-7xl space-y-16">
          <!-- Header -->
          <div class="mx-auto max-w-3xl space-y-4 text-center">
            <Badge variant="secondary" class="gap-1.5 px-3 py-1 font-mono text-xs shadow-xs">
              <ShieldCheck class="text-primary size-3.5" />
              Predictable Pricing
            </Badge>
            <h2 class="text-foreground text-3xl font-bold tracking-tight sm:text-4xl">
              Zero seat taxes. Own your source code forever.
            </h2>
            <p class="text-muted-foreground text-base">
              Choose the tier that fits your engineering team's delivery scale and compliance needs.
            </p>
    
            <!-- Billing Toggle -->
            <div class="flex items-center justify-center gap-3 pt-4">
              <span
                class="font-mono text-xs"
                :class="billing === 'monthly' ? 'text-foreground font-bold' : 'text-muted-foreground'"
              >
                Monthly
              </span>
              <div class="border-border bg-card relative flex items-center rounded-full border p-1">
                <button
                  type="button"
                  class="relative z-10 rounded-full px-3 py-1 font-mono text-xs transition-colors"
                  :class="
                    billing === 'monthly'
                      ? 'bg-primary text-primary-foreground font-semibold shadow-xs'
                      : 'text-muted-foreground'
                  "
                  @click="billing = 'monthly'"
                >
                  Monthly
                </button>
                <button
                  type="button"
                  class="relative z-10 flex items-center gap-1.5 rounded-full px-3 py-1 font-mono text-xs transition-colors"
                  :class="
                    billing === 'annual'
                      ? 'bg-primary text-primary-foreground font-semibold shadow-xs'
                      : 'text-muted-foreground'
                  "
                  @click="billing = 'annual'"
                >
                  <span>Annual</span>
                  <span class="bg-success rounded-full px-1.5 py-0.5 text-xs font-bold text-white">Save 20%</span>
                </button>
              </div>
            </div>
          </div>
    
          <!-- Pricing Plan Cards Grid (3 Columns) -->
          <div class="grid grid-cols-1 items-stretch gap-6 md:grid-cols-3">
            <Card
              v-for="plan in plans"
              :key="plan.id"
              class="border-border bg-card relative flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-xl transition-colors sm:p-8"
              :class="
                plan.highlight
                  ? 'border-primary/80 ring-primary/20 scale-[1.02] shadow-sm ring-2'
                  : 'hover:border-border/80'
              "
            >
              <!-- Top Badge -->
              <div v-if="plan.badge" class="absolute -top-3 left-1/2 -translate-x-1/2">
                <Badge class="px-3 py-0.5 font-mono text-xs tracking-wider uppercase shadow-md">
                  {{ plan.badge }}
                </Badge>
              </div>
    
              <div class="space-y-4">
                <div>
                  <h3 class="text-foreground font-mono text-xl font-bold">{{ plan.name }}</h3>
                  <p class="text-muted-foreground mt-1 min-h-[36px] text-xs">{{ plan.description }}</p>
                </div>
    
                <!-- Price display -->
                <div class="flex items-baseline gap-1.5 font-mono">
                  <span class="text-foreground text-4xl font-bold">
                    ${{ billing === 'annual' ? plan.annualPrice : plan.monthlyPrice }}
                  </span>
                  <span class="text-muted-foreground text-xs">/ month</span>
                </div>
                <p class="text-muted-foreground font-mono text-xs">
                  {{
                    billing === 'annual' && plan.annualPrice > 0
                      ? 'Billed annually ($' + plan.annualPrice * 12 + '/yr)'
                      : 'Billed monthly'
                  }}
                </p>
              </div>
    
              <Button :variant="plan.ctaVariant" class="h-10 w-full gap-1.5 font-mono text-xs shadow-xs">
                <span>{{ plan.ctaText }}</span>
                <ArrowRight class="size-3.5" />
              </Button>
            </Card>
          </div>
    
          <!-- Deep Feature Comparison Matrix Table -->
          <div class="space-y-6">
            <div class="text-center">
              <h3 class="text-foreground font-mono text-xl font-bold">Detailed Feature Comparison</h3>
              <p class="text-muted-foreground mt-1 text-xs">Full granular matrix of capabilities and entitlements.</p>
            </div>
    
            <Card class="border-border bg-card overflow-hidden rounded-2xl text-left shadow-sm">
              <div class="overflow-x-auto">
                <table class="w-full border-collapse text-left text-xs">
                  <thead>
                    <tr class="border-border bg-muted/40 text-muted-foreground border-b font-mono">
                      <th class="w-1/2 p-4 font-semibold">Capability</th>
                      <th class="p-4 text-center font-semibold">Community</th>
                      <th class="text-primary p-4 text-center font-bold font-semibold">Pro Team</th>
                      <th class="p-4 text-center font-semibold">Enterprise</th>
                    </tr>
                  </thead>
                  <tbody>
                    <template v-for="(section, sIdx) in comparisonData" :key="sIdx">
                      <tr class="bg-muted/20 border-border/80 border-b">
                        <td
                          colspan="4"
                          class="text-muted-foreground p-3 px-4 font-mono text-xs font-bold tracking-wider uppercase"
                        >
                          {{ section.category }}
                        </td>
                      </tr>
                      <tr
                        v-for="(row, rIdx) in section.features"
                        :key="rIdx"
                        class="border-border/60 hover:bg-muted/10 border-b transition-colors"
                      >
                        <td class="p-4">
                          <div class="text-foreground font-medium">{{ row.name }}</div>
                          <div class="text-muted-foreground mt-0.5 text-xs">{{ row.tooltip }}</div>
                        </td>
                        <td class="p-4 text-center font-mono">
                          <template v-if="typeof row.community === 'boolean'">
                            <Check v-if="row.community" class="text-success mx-auto size-4" />
                            <Minus v-else class="text-muted-foreground/40 mx-auto size-4" />
                          </template>
                          <span v-else class="text-muted-foreground">{{ row.community }}</span>
                        </td>
                        <td class="p-4 text-center font-mono font-semibold">
                          <template v-if="typeof row.pro === 'boolean'">
                            <Check v-if="row.pro" class="text-success mx-auto size-4" />
                            <Minus v-else class="text-muted-foreground/40 mx-auto size-4" />
                          </template>
                          <span v-else class="text-primary">{{ row.pro }}</span>
                        </td>
                        <td class="p-4 text-center font-mono">
                          <template v-if="typeof row.enterprise === 'boolean'">
                            <Check v-if="row.enterprise" class="text-success mx-auto size-4" />
                            <Minus v-else class="text-muted-foreground/40 mx-auto size-4" />
                          </template>
                          <span v-else class="text-foreground font-semibold">{{ row.enterprise }}</span>
                        </td>
                      </tr>
                    </template>
                  </tbody>
                </table>
              </div>
            </Card>
          </div>
        </div>
      </section>
    </template>
    

Raw manifest:https://uipkge.dev/r/vue/pricing-tier-comparison-matrix.json