Create a modern, attractive SaaS website landing page with the use of smart gradients and slick animations including appealing, modern mouse hover animations.
0bfd444 verified Download components/pricing-card.js from wanderingcloud/gradientflow-saas: direct link, hf CLI and curl.
- Browser
- Download file 7.85 kB
-
https://huggingface.co/spaces/wanderingcloud/gradientflow-saas/resolve/main/components/pricing-card.js
- Command line
-
hf download hf://spaces/wanderingcloud/gradientflow-saas/components/pricing-card.js
-
curl -L -o pricing-card.js https://huggingface.co/spaces/wanderingcloud/gradientflow-saas/resolve/main/components/pricing-card.js
7.85 kB
| class PricingCard extends HTMLElement { | |
| constructor() { | |
| super(); | |
| this.isYearly = false; | |
| } | |
| connectedCallback() { | |
| this.attachShadow({ mode: 'open' }); | |
| this.render(); | |
| this.bindEvents(); | |
| } | |
| render() { | |
| const plan = this.getAttribute('plan') || 'Basic'; | |
| const price = this.getAttribute('price') || '0'; | |
| const popular = this.hasAttribute('popular'); | |
| const features = JSON.parse(this.getAttribute('features') || '[]'); | |
| const yearly = this.getAttribute('yearly') === 'true'; | |
| const monthlyPrice = parseInt(price); | |
| const yearlyPrice = Math.round(monthlyPrice * 12 * 0.8); // 20% discount | |
| const savings = Math.round((1 - 0.8) * 100); | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| } | |
| .pricing-card { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| border-radius: 24px; | |
| padding: 2rem; | |
| position: relative; | |
| transition: all 0.3s ease; | |
| overflow: hidden; | |
| } | |
| .pricing-card:hover { | |
| transform: translateY(-10px); | |
| box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); | |
| } | |
| .pricing-card.popular { | |
| border-color: rgba(147, 51, 234, 0.5); | |
| background: rgba(147, 51, 234, 0.1); | |
| } | |
| .popular-badge { | |
| position: absolute; | |
| top: 1rem; | |
| right: 1rem; | |
| background: linear-gradient(135deg, #9333ea, #ec4899); | |
| color: white; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| } | |
| .plan-name { | |
| font-size: 1.5rem; | |
| font-weight: bold; | |
| margin-bottom: 0.5rem; | |
| color: #1f2937; | |
| } | |
| .plan-description { | |
| color: #6b7280; | |
| margin-bottom: 2rem; | |
| } | |
| .price-container { | |
| margin-bottom: 2rem; | |
| } | |
| .price { | |
| font-size: 3rem; | |
| font-weight: bold; | |
| color: #1f2937; | |
| display: inline-block; | |
| } | |
| .price-crossed { | |
| position: relative; | |
| display: inline-block; | |
| color: #9ca3af; | |
| font-size: 1.5rem; | |
| margin-left: 0.5rem; | |
| } | |
| .price-crossed::after { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| top: 50%; | |
| width: 100%; | |
| height: 2px; | |
| background: #ef4444; | |
| transform: rotate(-15deg); | |
| animation: strike 0.3s ease-out; | |
| } | |
| .savings-badge { | |
| display: inline-block; | |
| background: #10b981; | |
| color: white; | |
| padding: 0.25rem 0.5rem; | |
| border-radius: 0.25rem; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| margin-left: 0.5rem; | |
| } | |
| .period { | |
| color: #6b7280; | |
| } | |
| .features { | |
| list-style: none; | |
| padding: 0; | |
| margin: 0 0 2rem 0; | |
| } | |
| .features li { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 1rem; | |
| color: #4b5563; | |
| } | |
| .features li::before { | |
| content: '✓'; | |
| color: #10b981; | |
| font-weight: bold; | |
| margin-right: 0.75rem; | |
| font-size: 1.25rem; | |
| } | |
| .btn-choose { | |
| width: 100%; | |
| padding: 0.75rem 1.5rem; | |
| background: linear-gradient(135deg, #9333ea, #ec4899); | |
| color: white; | |
| border: none; | |
| border-radius: 12px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .btn-choose:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 20px rgba(147, 51, 234, 0.3); | |
| } | |
| .dark .pricing-card { | |
| background: rgba(0, 0, 0, 0.3); | |
| border-color: rgba(255, 255, 255, 0.1); | |
| color: #e5e7eb; | |
| } | |
| .dark .plan-name { | |
| color: #f9fafb; | |
| } | |
| .dark .price { | |
| color: #f9fafb; | |
| } | |
| .dark .plan-description, | |
| .dark .period, | |
| .dark .features li { | |
| color: #d1d5db; | |
| } | |
| @keyframes strike { | |
| from { width: 0; } | |
| to { width: 100%; } | |
| } | |
| </style> | |
| <div class="pricing-card ${popular ? 'popular' : ''}"> | |
| ${popular ? '<span class="popular-badge">Most Popular</span>' : ''} | |
| <h3 class="plan-name">${plan}</h3> | |
| <p class="plan-description">Perfect for ${plan.toLowerCase()} teams</p> | |
| <div class="price-container"> | |
| <span class="price">$${yearly ? yearlyPrice : monthlyPrice}</span> | |
| ${yearly ? `<span class="price-crossed">$${monthlyPrice * 12}</span>` : ''} | |
| <span class="savings-badge" style="display: ${yearly ? 'inline-block' : 'none'}">Save ${savings}%</span> | |
| <div class="period">per ${yearly ? 'year' : 'month'}</div> | |
| </div> | |
| <ul class="features"> | |
| ${features.map(feature => `<li>${feature}</li>`).join('')} | |
| </ul> | |
| <button class="btn-choose">Choose Plan</button> | |
| </div> | |
| `; | |
| } | |
| bindEvents() { | |
| this.shadowRoot.querySelector('.btn-choose').addEventListener('click', () => { | |
| // Handle plan selection | |
| const event = new CustomEvent('planselected', { | |
| detail: { plan: this.getAttribute('plan') } | |
| }); | |
| window.dispatchEvent(event); | |
| }); | |
| } | |
| static get observedAttributes() { | |
| return ['yearly']; | |
| } | |
| attributeChangedCallback(name, oldValue, newValue) { | |
| if (name === 'yearly') { | |
| this.isYearly = newValue === 'true'; | |
| this.render(); | |
| } | |
| } | |
| } | |
| customElements.define('custom-pricing-card', PricingCard); |