VibeCoderzVibeCoderz
Telegram
All Prompts
Interactive Tailwind Pricing Section with Mode & Upsell Toggle preview
pricingsectiontailwindinteractiveupsellresponsivelanding page

Interactive Tailwind Pricing Section with Mode & Upsell Toggle

Интерактивный раздел цен Tailwind с переключением режима (фикс/месяц) и доп. опций. Обновляет цену и сроки. Для лендингов.

Prompt

<section id="pricing" class="max-w-7xl sm:px-6 sm:mt-20 mt-8 mr-auto mb-8 ml-auto pr-4 pl-4">
  <div
    class="relative overflow-hidden rounded-[40px] border border-white/20 bg-neutral-950 text-white shadow-[0_8px_30px_rgba(0,0,0,0.18)]">
    <div class="absolute inset-0 pointer-events-none">
      <div
        class="absolute inset-0 bg-[radial-gradient(1200px_600px_at_20%_-20%,rgba(255,255,255,0.08),transparent_60%)]">
      </div>
      <div
        class="absolute inset-0 bg-[radial-gradient(1200px_600px_at_80%_120%,rgba(255,255,255,0.06),transparent_60%)]">
      </div>
      <div
        class="absolute inset-0 bg-[radial-gradient(#ffffff0d_1px,transparent_1px)] [background-size:20px_20px] opacity-[0.15]">
      </div>
    </div>

    <div class="relative sm:p-8 pt-6 pr-6 pb-6 pl-6">
      <div class="flex items-center gap-2 text-sm text-white/70 font-geist">
        <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none"
          stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" data-lucide="plus"
          class="lucide lucide-plus w-4 h-4">
          <path d="M5 12h14"></path>
          <path d="M12 5v14"></path>
        </svg>
        <span class="font-geist">Transparent rates</span>
      </div>

      <div class="mt-2 text-center">
        <h2 class="text-[56px] sm:text-[80px] leading-none font-semibold tracking-tighter font-geist">Pricing.</h2>
        <div class="mt-5 inline-flex items-center gap-1 rounded-full bg-white/10 p-1 ring-1 ring-white/10">
          <button type="button" data-mode-button="project" class="font-geist text-sm tracking-tight rounded-full px-3 py-1.5 bg-white text-gray-900">Fixed price</button>
          <button type="button" data-mode-button="monthly" class="font-geist text-sm tracking-tight rounded-full px-3 py-1.5 text-white/80">Retainer</button>
        </div>
      </div>

      <div class="mt-8 rounded-3xl bg-white/5 ring-1 ring-white/10 p-4 sm:p-6">
        <div class="grid grid-cols-1 md:grid-cols-12 gap-4 sm:gap-6 items-stretch">
          <!-- Upsell -->
          <div class="md:col-span-4">
            <div class="h-full rounded-2xl bg-black/30 ring-1 ring-white/10 p-5 flex flex-col justify-between">
              <div>
                <p class="text-base font-medium tracking-tight font-geist">Need growth acceleration?</p>
                <p class="mt-2 text-sm text-white/70 font-geist">Add strategic marketing and SEO optimization.</p>
              </div>
              <div class="mt-8 flex items-center justify-between">
                <div class="text-sm font-geist">
                  <span class="text-white/90">+ $1,850</span>
                </div>
                <button type="button" role="switch" aria-checked="false" data-upsell-switch="" class="inline-flex h-6 w-11 items-center rounded-full bg-white/10 ring-1 ring-white/10 transition-colors duration-200">
                  <span data-upsell-knob="" class="h-4 w-4 translate-x-0 rounded-full bg-white transition-transform duration-200"></span>
                  <span class="sr-only">Toggle Growth Package add-on</span>
                </button>
              </div>
            </div>
          </div>

          <!-- Price -->
          <div class="md:col-span-4">
            <div class="h-full rounded-2xl bg-black/30 ring-1 ring-white/10 p-5 flex flex-col">
              <div class="flex-1">
                <div class="flex items-end gap-2">
                  <div class="text-5xl sm:text-6xl lg:text-7xl font-semibold tracking-tighter tabular-nums font-geist"
                    data-amount="">$3,200</div>
                  <div class="pb-2 text-white/60 text-base font-geist" data-period="">/project</div>
                </div>
              </div>
              <div
                class="mt-8 pt-4 border-t border-white/10 text-xs text-white/70 flex items-center justify-between font-geist">
                <span data-delivery-key="">Timeline</span>
                <span data-delivery-val="">4–6 weeks</span>
              </div>
            </div>
          </div>

          <!-- Features + CTA -->
          <div class="md:col-span-4">
            <div class="h-full rounded-2xl bg-black/30 ring-1 ring-white/10 p-5 flex flex-col">
              <ul class="space-y-3">
                <li class="flex items-start gap-2">
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                    stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"
                    data-lucide="plus" class="lucide lucide-plus w-5 h-5 text-white/80">
                    <path d="M5 12h14"></path>
                    <path d="M12 5v14"></path>
                  </svg>
                  <span class="text-sm font-geist">Complete visual brand system</span>
                </li>
                <li class="flex items-start gap-2">
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                    stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"
                    data-lucide="plus" class="lucide lucide-plus w-5 h-5 text-white/80">
                    <path d="M5 12h14"></path>
                    <path d="M12 5v14"></path>
                  </svg>
                  <span class="text-sm font-geist">Custom website or digital product</span>
                </li>
                <li class="flex items-start gap-2">
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                    stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"
                    data-lucide="plus" class="lucide lucide-plus w-5 h-5 text-white/80">
                    <path d="M5 12h14"></path>
                    <path d="M12 5v14"></path>
                  </svg>
                  <span class="text-sm font-geist">Launch support and guidelines</span>
                </li>
              </ul>

              <div class="mt-auto">
                <a href="#contact"
                  class="mt-6 w-full inline-flex items-center justify-center gap-2 rounded-full px-5 py-3 text-sm font-medium tracking-tight text-gray-900 bg-white hover:bg-white/90 transition-colors border border-white/10">
                  <span class="font-geist">Start conversation</span>
                  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                    stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                    data-lucide="arrow-right" class="lucide lucide-arrow-right w-4 h-4">
                    <path d="M5 12h14"></path>
                    <path d="m12 5 7 7-7 7"></path>
                  </svg>
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Bottom note -->
      <p class="mt-4 text-[11px] text-white/50 font-geist text-center">Clear pricing, no surprises. Every project is
        scoped individually for your unique needs.</p>
    </div>
  </div>

  <script>
    (function () {
      function initPricing() {
        const root = document.getElementById('pricing');
        if (!root) return;

        const amountEl = root.querySelector('[data-amount]');
        const periodEl = root.querySelector('[data-period]');
        const deliveryKeyEl = root.querySelector('[data-delivery-key]');
        const deliveryValEl = root.querySelector('[data-delivery-val]');
        const btnProject = root.querySelector('[data-mode-button="project"]');
        const btnMonthly = root.querySelector('[data-mode-button="monthly"]');
        const upsellSwitch = root.querySelector('[data-upsell-switch]');
        const upsellKnob = root.querySelector('[data-upsell-knob]');

        const prices = { project: 3200, monthly: 4500 };
        const addon = 1850;
        const state = { mode: 'project', upsell: false };

        function money(n) {
          return n.toLocaleString('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
        }

        function render() {
          const base = prices[state.mode];
          const total = base + (state.upsell ? addon : 0);
          amountEl.textContent = money(total);
          periodEl.textContent = state.mode === 'project' ? '/project' : '/month';
          deliveryKeyEl.textContent = state.mode === 'project' ? 'Timeline' : 'Commitment';
          deliveryValEl.textContent = state.mode === 'project' ? '4–6 weeks' : '3 month minimum';

          // Segmented control visuals
          btnProject.classList.toggle('bg-white', state.mode === 'project');
          btnProject.classList.toggle('text-gray-900', state.mode === 'project');
          btnProject.classList.toggle('text-white/80', state.mode !== 'project');

          btnMonthly.classList.toggle('bg-white', state.mode === 'monthly');
          btnMonthly.classList.toggle('text-gray-900', state.mode === 'monthly');
          btnMonthly.classList.toggle('text-white/80', state.mode !== 'monthly');

          // Upsell switch visuals
          upsellSwitch.setAttribute('aria-checked', state.upsell ? 'true' : 'false');
          upsellSwitch.classList.toggle('bg-white', state.upsell);
          upsellSwitch.classList.toggle('bg-white/10', !state.upsell);
          upsellKnob.classList.toggle('translate-x-5', state.upsell);
          upsellKnob.classList.toggle('translate-x-0', !state.upsell);
        }

        btnProject.addEventListener('click', () => { state.mode = 'project'; render(); });
        btnMonthly.addEventListener('click', () => { state.mode = 'monthly'; render(); });
        upsellSwitch.addEventListener('click', () => { state.upsell = !state.upsell; render(); });

        render();
        if (window.lucide && typeof lucide.createIcons === 'function') lucide.createIcons();
      }

      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initPricing, { once: true });
      } else {
        initPricing();
      }
    })();
  </script>
</section>
All Prompts