Skip to content

Commit e5be06c

Browse files
committed
Enhance payment form UI with comparison table and improved plan selection styling
1 parent ea1086a commit e5be06c

File tree

1 file changed

+227
-34
lines changed

1 file changed

+227
-34
lines changed

public/js/components/stripe-payment-form.js

Lines changed: 227 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,31 +46,52 @@ class StripePaymentForm extends HTMLElement {
4646
4747
.plan-options {
4848
display: flex;
49-
gap: 1rem;
49+
gap: 1.5rem;
50+
margin-bottom: 1.5rem;
5051
}
5152
5253
.plan-option {
5354
flex: 1;
5455
border: 2px solid var(--border-color, #ddd);
55-
border-radius: 8px;
56-
padding: 1.25rem;
56+
border-radius: 10px;
57+
padding: 1.5rem;
5758
cursor: pointer;
5859
text-align: center;
59-
transition: all 0.2s ease;
60+
transition: all 0.3s ease;
6061
position: relative;
62+
overflow: hidden;
63+
background-color: var(--card-bg);
64+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
6165
}
6266
6367
.plan-option:hover {
6468
border-color: var(--primary-color);
65-
transform: translateY(-2px);
66-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
69+
transform: translateY(-5px);
70+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
6771
}
6872
6973
.plan-option.selected {
7074
border-color: var(--primary-color);
7175
background-color: rgba(var(--primary-color-rgb, 0, 102, 204), 0.05);
72-
transform: translateY(-2px);
73-
box-shadow: 0 4px 12px rgba(var(--primary-color-rgb, 0, 102, 204), 0.2);
76+
transform: translateY(-5px);
77+
box-shadow: 0 8px 24px rgba(var(--primary-color-rgb, 0, 102, 204), 0.2);
78+
}
79+
80+
.plan-option.popular {
81+
border: 2px solid var(--primary-color);
82+
position: relative;
83+
}
84+
85+
.plan-option.popular::before {
86+
content: "Best Value";
87+
position: absolute;
88+
top: 10px;
89+
right: -30px;
90+
background-color: var(--primary-color);
91+
color: white;
92+
padding: 5px 30px;
93+
font-size: 0.8rem;
94+
transform: rotate(45deg);
7495
}
7596
7697
.plan-option input {
@@ -81,47 +102,84 @@ class StripePaymentForm extends HTMLElement {
81102
width: 0;
82103
}
83104
84-
.plan-option span {
105+
.plan-name {
85106
display: block;
86107
font-weight: bold;
87-
margin-bottom: 5px;
88-
font-size: 1.125rem;
108+
margin-bottom: 0.5rem;
109+
font-size: 1.25rem;
110+
color: var(--primary-color);
111+
}
112+
113+
.plan-price {
114+
font-size: 1.5rem;
115+
font-weight: bold;
116+
margin: 0.75rem 0;
117+
color: var(--text-color);
118+
}
119+
120+
.plan-price small {
121+
font-size: 1rem;
122+
opacity: 0.8;
123+
}
124+
125+
.plan-features {
126+
list-style: none;
127+
padding: 0;
128+
margin: 0.75rem 0 0;
129+
text-align: left;
130+
}
131+
132+
.plan-features li {
133+
padding: 0.5rem 0;
134+
position: relative;
135+
padding-left: 1.5rem;
136+
font-size: 0.9rem;
137+
}
138+
139+
.plan-features li::before {
140+
content: "✓";
141+
position: absolute;
142+
left: 0;
143+
color: var(--success-color, #28a745);
89144
}
90145
91146
.price-display {
92-
font-size: 1.75rem;
147+
font-size: 2rem;
93148
font-weight: bold;
94149
text-align: center;
95-
margin: 1.25rem 0;
150+
margin: 1.5rem 0;
96151
color: var(--primary-color);
97-
padding: 0.625rem;
98-
border-radius: 8px;
152+
padding: 1rem;
153+
border-radius: 10px;
99154
background-color: rgba(var(--primary-color-rgb, 0, 102, 204), 0.05);
155+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
156+
transition: all 0.3s ease;
100157
}
101158
102159
button {
103160
width: 100%;
104161
background-color: var(--primary-color);
105162
color: white;
106163
border: none;
107-
border-radius: 6px;
108-
padding: 1rem;
109-
font-size: 1.125rem;
164+
border-radius: 8px;
165+
padding: 1.25rem;
166+
font-size: 1.25rem;
110167
font-weight: bold;
111168
cursor: pointer;
112-
transition: all 0.2s ease;
113-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
169+
transition: all 0.3s ease;
170+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
171+
margin-bottom: 1rem;
114172
}
115173
116174
button:hover {
117175
background-color: var(--primary-color-dark, #0052a3);
118-
transform: translateY(-2px);
119-
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
176+
transform: translateY(-3px);
177+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
120178
}
121179
122180
button:active {
123181
transform: translateY(0);
124-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
182+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
125183
}
126184
127185
button:disabled {
@@ -135,19 +193,74 @@ class StripePaymentForm extends HTMLElement {
135193
display: flex;
136194
align-items: center;
137195
justify-content: center;
138-
gap: 0.5rem;
139-
margin-top: 1.25rem;
196+
gap: 0.75rem;
197+
margin-top: 1.5rem;
140198
color: var(--text-light, #666);
141-
font-size: 0.875rem;
142-
padding: 0.625rem;
143-
border-radius: 6px;
199+
font-size: 0.9rem;
200+
padding: 1rem;
201+
border-radius: 8px;
144202
background-color: rgba(0, 0, 0, 0.03);
203+
border: 1px solid rgba(0, 0, 0, 0.05);
204+
}
205+
206+
.secure-badge svg {
207+
width: 1.25rem;
208+
height: 1.25rem;
209+
color: var(--success-color, #28a745);
210+
}
211+
212+
.payment-comparison {
213+
margin: 2rem 0;
214+
padding: 1.5rem;
215+
background-color: rgba(var(--primary-color-rgb, 0, 102, 204), 0.03);
216+
border-radius: 10px;
217+
border: 1px solid rgba(var(--primary-color-rgb, 0, 102, 204), 0.1);
218+
}
219+
220+
.comparison-title {
221+
text-align: center;
222+
font-weight: bold;
223+
margin-bottom: 1rem;
224+
color: var(--primary-color);
225+
}
226+
227+
.comparison-table {
228+
width: 100%;
229+
border-collapse: collapse;
230+
}
231+
232+
.comparison-table th, .comparison-table td {
233+
padding: 0.75rem;
234+
text-align: center;
235+
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
236+
}
237+
238+
.comparison-table th {
239+
font-weight: bold;
240+
color: var(--primary-color);
241+
}
242+
243+
.comparison-table tr:last-child td {
244+
border-bottom: none;
245+
font-weight: bold;
246+
}
247+
248+
.highlight {
249+
color: var(--success-color, #28a745);
250+
font-weight: bold;
145251
}
146252
147253
@media (max-width: 768px) {
148254
.plan-options {
149255
flex-direction: column;
150256
}
257+
258+
.plan-option.popular::before {
259+
top: 5px;
260+
right: -35px;
261+
padding: 3px 30px;
262+
font-size: 0.7rem;
263+
}
151264
}
152265
</style>
153266
@@ -162,13 +275,24 @@ class StripePaymentForm extends HTMLElement {
162275
<div class="plan-options">
163276
<div class="plan-option selected" id="monthly-plan">
164277
<input type="radio" name="plan" value="monthly" checked>
165-
<span>Monthly</span>
166-
<div>Billed monthly</div>
278+
<span class="plan-name">Monthly</span>
279+
<div class="plan-price">$5<small>/month</small></div>
280+
<ul class="plan-features">
281+
<li>Unlimited Conversions</li>
282+
<li>API Access</li>
283+
<li>Email Support</li>
284+
</ul>
167285
</div>
168-
<div class="plan-option" id="yearly-plan">
286+
<div class="plan-option popular" id="yearly-plan">
169287
<input type="radio" name="plan" value="yearly">
170-
<span>Yearly</span>
171-
<div>Save 50%</div>
288+
<span class="plan-name">Yearly</span>
289+
<div class="plan-price">$30<small>/year</small></div>
290+
<ul class="plan-features">
291+
<li>Save over 50%!</li>
292+
<li>Unlimited Conversions</li>
293+
<li>API Access</li>
294+
<li>Priority Support</li>
295+
</ul>
172296
</div>
173297
</div>
174298
</div>
@@ -177,6 +301,36 @@ class StripePaymentForm extends HTMLElement {
177301
$5.00/month
178302
</div>
179303
304+
<div class="payment-comparison">
305+
<div class="comparison-title">Why Choose Yearly?</div>
306+
<table class="comparison-table">
307+
<thead>
308+
<tr>
309+
<th></th>
310+
<th>Monthly</th>
311+
<th>Yearly</th>
312+
</tr>
313+
</thead>
314+
<tbody>
315+
<tr>
316+
<td>Price</td>
317+
<td>$5/month</td>
318+
<td>$2.50/month</td>
319+
</tr>
320+
<tr>
321+
<td>Annual Cost</td>
322+
<td>$60</td>
323+
<td>$30</td>
324+
</tr>
325+
<tr>
326+
<td>Savings</td>
327+
<td>-</td>
328+
<td class="highlight">$30 (50%)</td>
329+
</tr>
330+
</tbody>
331+
</table>
332+
</div>
333+
180334
<input type="hidden" id="selected-plan" name="selected-plan" value="monthly">
181335
182336
<button type="submit" id="payment-button">Subscribe with Stripe</button>
@@ -185,7 +339,7 @@ class StripePaymentForm extends HTMLElement {
185339
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
186340
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 6c1.4 0 2.8 1.1 2.8 2.5V11c.6 0 1.2.6 1.2 1.3v3.5c0 .6-.6 1.2-1.3 1.2H9.2c-.6 0-1.2-.6-1.2-1.3v-3.5c0-.6.6-1.2 1.2-1.2V9.5C9.2 8.1 10.6 7 12 7zm0 1.2c-.8 0-1.5.5-1.5 1.3V11h3V9.5c0-.8-.7-1.3-1.5-1.3z" />
187341
</svg>
188-
Secure payment via Stripe
342+
Secure payment via Stripe - Your payment information is encrypted and secure
189343
</div>
190344
</form>
191345
`;
@@ -232,21 +386,60 @@ class StripePaymentForm extends HTMLElement {
232386
const selectedPlanInput = this.shadowRoot.getElementById('selected-plan');
233387
const monthlyPlan = this.shadowRoot.getElementById('monthly-plan');
234388
const yearlyPlan = this.shadowRoot.getElementById('yearly-plan');
389+
const comparisonTable = this.shadowRoot.querySelector('.payment-comparison');
235390

236391
// Update price display
237392
if (plan === 'yearly') {
238393
priceDisplay.textContent = '$30.00/year';
239394
yearlyPlan.classList.add('selected');
240395
monthlyPlan.classList.remove('selected');
396+
397+
// Highlight the yearly column in the comparison table
398+
if (comparisonTable) {
399+
const yearlyColumn = comparisonTable.querySelectorAll('tr td:nth-child(3)');
400+
const monthlyColumn = comparisonTable.querySelectorAll('tr td:nth-child(2)');
401+
402+
yearlyColumn.forEach(cell => {
403+
if (!cell.classList.contains('highlight')) {
404+
cell.style.fontWeight = 'bold';
405+
}
406+
});
407+
408+
monthlyColumn.forEach(cell => {
409+
cell.style.fontWeight = 'normal';
410+
});
411+
}
241412
} else {
242413
priceDisplay.textContent = '$5.00/month';
243414
monthlyPlan.classList.add('selected');
244415
yearlyPlan.classList.remove('selected');
416+
417+
// Highlight the monthly column in the comparison table
418+
if (comparisonTable) {
419+
const yearlyColumn = comparisonTable.querySelectorAll('tr td:nth-child(3)');
420+
const monthlyColumn = comparisonTable.querySelectorAll('tr td:nth-child(2)');
421+
422+
monthlyColumn.forEach(cell => {
423+
cell.style.fontWeight = 'bold';
424+
});
425+
426+
yearlyColumn.forEach(cell => {
427+
if (!cell.classList.contains('highlight')) {
428+
cell.style.fontWeight = 'normal';
429+
}
430+
});
431+
}
245432
}
246433

247434
// Update selected plan input
248435
selectedPlanInput.value = plan;
249436

437+
// Add animation to price display
438+
priceDisplay.style.transform = 'scale(1.05)';
439+
setTimeout(() => {
440+
priceDisplay.style.transform = 'scale(1)';
441+
}, 300);
442+
250443
console.log(`Price display updated to: ${priceDisplay.textContent} for plan: ${plan}`);
251444
}
252445

0 commit comments

Comments
 (0)