@use 'sprucecss/scss/spruce' as *;
.subscribe-save {
@include layout-stack('m');
&__options {
border: 0;
margin: 0;
padding: 0;
@include layout-stack('xs');
}
&__legend {
color: color('heading');
font-size: config('font-size-base', $typography);
font-weight: 700;
margin-block-end: spacer('xs');
padding: 0;
}
&__option {
border: config('border-width-base', $display) solid color('border');
border-radius: radius('md');
&:has(> input:checked, > label > input:checked) {
background-color: color-alpha('primary', 0.04);
border-color: color('primary');
box-shadow: 0 0 0 1px color('primary');
}
}
> fieldset > label.subscribe-save__option,
&__label {
align-items: center;
cursor: pointer;
display: flex;
gap: spacer('s');
padding: spacer('s');
}
&__text {
align-items: center;
display: flex;
flex: 1 1 auto;
flex-wrap: wrap;
gap: spacer('xxs') spacer('xs');
strong {
color: color('heading');
}
}
&__price {
color: color('heading');
font-variant-numeric: tabular-nums;
font-weight: 700;
text-align: end;
del {
color: color('muted');
display: block;
font-size: config('font-size-sm', $typography);
font-weight: 400;
}
}
&__details {
border-block-start: config('border-width-base', $display) dashed color('border');
display: grid;
gap: spacer('xxs');
margin-inline: spacer('s');
padding-block: spacer('s');
.form-control {
max-inline-size: 16rem;
}
}
@supports selector(:has(*)) {
&__option--subscribe:not(:has(> label > input:checked)) &__details {
display: none;
}
}
&__perks {
color: color('muted');
font-size: config('font-size-sm', $typography);
list-style: none;
margin-block-start: spacer('xs');
padding: 0;
li {
align-items: center;
display: flex;
gap: spacer('xxs');
margin: 0;
&::before {
color: color('success', 'alert');
content: '✓';
font-weight: 700;
}
}
}
&__buy {
align-items: end;
display: grid;
gap: spacer('s');
grid-template-columns: 6rem minmax(0, 1fr);
}
&__quantity {
display: grid;
gap: spacer('xxs');
}
}
<form class="subscribe-save" action="#" method="post" data-subscribe-save data-price="24" data-discount="15">
<fieldset class="subscribe-save__options">
<legend class="subscribe-save__legend">Purchase option</legend>
<label class="form-check subscribe-save__option">
<input class="form-check__control" type="radio" name="purchase" value="once">
<span class="subscribe-save__text">
<strong>One-time purchase</strong>
</span>
<span class="subscribe-save__price">$24.00</span>
</label>
<div class="subscribe-save__option subscribe-save__option--subscribe">
<label class="form-check subscribe-save__label">
<input class="form-check__control" type="radio" name="purchase" value="subscribe" checked>
<span class="subscribe-save__text">
<strong>Subscribe & save 15%</strong>
<span class="badge badge--success">Best value</span>
</span>
<span class="subscribe-save__price"><span class="sr-only">Subscription price: </span>$20.40 <del><span class="sr-only">Regular price: </span>$24.00</del></span>
</label>
<div class="subscribe-save__details" data-subscribe-save-details>
<label class="form-label" for="subscribe-frequency">Deliver every</label>
<select class="form-control form-control--sm" id="subscribe-frequency" name="frequency">
<option value="2">2 weeks</option>
<option value="4" selected>4 weeks (most popular)</option>
<option value="6">6 weeks</option>
<option value="8">8 weeks</option>
</select>
<ul class="subscribe-save__perks" role="list">
<li>Free shipping on every delivery</li>
<li>Skip, pause or cancel anytime</li>
</ul>
</div>
</div>
</fieldset>
<div class="subscribe-save__buy">
<div class="subscribe-save__quantity">
<label class="form-label" for="subscribe-quantity">Quantity</label>
<select class="form-control" id="subscribe-quantity" name="quantity">
<option>1</option>
<option>2</option>
<option>3</option>
</select>
</div>
<button class="btn btn--primary btn--lg subscribe-save__submit" type="submit" data-subscribe-save-submit>Subscribe · $20.40 every 4 weeks</button>
</div>
</form>
(() => {
const money = (value) => `$${value.toFixed(2)}`;
document.querySelectorAll('[data-subscribe-save]').forEach((form) => {
const submit = form.querySelector('[data-subscribe-save-submit]');
const price = Number(form.dataset.price);
const discount = Number(form.dataset.discount);
const update = () => {
const { purchase, frequency, quantity } = form.elements;
const isSubscription = purchase.value === 'subscribe';
const total = price * Number(quantity.value) * (isSubscription ? 1 - discount / 100 : 1);
submit.textContent = isSubscription
? `Subscribe · ${money(total)} every ${frequency.value} weeks`
: `Add to cart · ${money(total)}`;
};
form.addEventListener('change', update);
update();
});
})();