1
0 Comments

How to create an interactive pricing table with Astro, Tailwind CSS, and Alpine.js

This tutorial delves into creating a responsive and interactive pricing table component, leveraging the powerful combination of Astro for static generation, Tailwind CSS for styling, and Alpine.js for interactivity. Our focus will be on the dynamic aspects of the component, particularly how Alpine.js works and how Astro passes data through an array to render our pricing plans.

See it live and get the code

Let's populate the array for the pricing plans

Starting with the pricingPlans array, the backbone of our component. This array contains objects, each representing a different pricing plan and styles for our pricing cards, because of course, we need to think about UX.

const pricingPlans = [
  {
    name: "Starter Pack",
    monthlyPrice: "15",
    annualPrice: "8",
    description: "This plan is ideal for individual users...",
    cardBgClass: "bg-black/20",
    buttonClass: "text-white bg-black/50 hover:bg-black/20",
    features: ["5 mb/PDF", "75 pages/PDF"],
    unavailableFeatures: ["Gpt-3.5-turbo model"],
  },
  // More plans...
];

Each plan includes details such as pricing, descriptions, styling classes, and arrays of available and unavailable features.

Rendering the Component with Astro

Using Astro's component model, we dynamically render each pricing plan. Astro's template syntax allows us to iterate over the pricingPlans array, generating the markup for each plan:

---
// Import statements and the pricingPlans array defined here
---
<BaseLayout>
  <div x-data="{ annual: false }">
    <!-- Pricing Plans Rendering -->
    {pricingPlans.map((plan) => (
      <div class={`rounded-xl overflow-hidden shadow-lg ${plan.cardBgClass}`}>
        <!-- Content goes here -->
      </div>
    ))}
  </div>
</BaseLayout>

Styling with Tailwind CSS

Within each plan's markup, Tailwind CSS classes are applied for styling. This approach ensures our pricing table is not only functional but also visually appealing and responsive:

<div class="text-xl font-semibold text-gray-800">{plan.name}</div>
<div class="mt-4">
  <span class="text-4xl font-bold">${plan.monthlyPrice}</span>
  <span class="text-base">/ month</span>
</div>
<!-- More styling with Tailwind CSS -->

For each pricing plan, we conditionally display the price based on this state:

<p>
  <span x-show="!annual">${plan.monthlyPrice}</span>
  <span x-show="annual">${plan.annualPrice}</span>
  /month
</p>

Dynamic Feature Listing

A key part of our pricing table is listing what's included and what's not. Using Alpine.js's x-show, we dynamically render features based on their availability:

<ul>
  {plan.features.map((feature) => (
    <li x-show="available">
       <!-- Icons goes here -->
      {feature}
      </li>
  ))}
  {plan.unavailableFeatures.map((feature) => (
    <li x-show="!available" class="text-gray-500">
    <!-- Icons goes here -->
    {feature}</li>
  ))}
</ul>

By combining Astro's static generation with Tailwind CSS for styling and Alpine.js for interactivity, we've created a dynamic and responsive pricing table component. This tutorial showcases the power of integrating these modern web technologies to build interactive components efficiently.

Experiment with the code snippets provided, tweaking styles, and adding more features as you see fit. The flexibility of Astro, combined with the utility-first approach of Tailwind CSS and the reactivity of Alpine.js, offers a solid foundation for building sophisticated web interfaces.

Trending on Indie Hackers
Here's how we got our first 200 users 30 comments Reaching $100k MRR Organically in 12 months 25 comments What you can learn from Marc Lou 20 comments Software Developers Can Build Beautiful Software 13 comments Worst Hire - my lessons 11 comments How to Secure #1 on Product Hunt: DO’s and DON'Ts / Experience from PitchBob – AI Pitch Deck Generator & Founders Co-Pilot 7 comments