@use 'sprucecss/scss/spruce' as *;
.form-size-option {
@include layout-stack('xs');
border: 0;
margin: 0;
min-inline-size: 0;
padding: 0;
&__label {
color: color('label', 'form');
font-family: config('font-family', $form-label, false);
font-size: config('font-size', $form-label, false);
font-weight: config('font-weight', $form-label, false);
padding: 0;
}
&__selected {
color: color('muted');
font-weight: 400;
}
&__inner {
display: flex;
flex-wrap: wrap;
gap: spacer('xs');
}
&__guide {
font-size: config('font-size-sm', $typography, false);
}
}
.form-size {
$this: &;
display: flex;
position: relative;
&__control {
@include visually-hidden;
&:checked + #{$this}__label {
background-color: color('primary-background', 'btn');
border-color: color('primary-background', 'btn');
color: color('primary-foreground', 'btn');
}
&:focus-visible + #{$this}__label {
@include short-ring('button', 'primary');
}
&:disabled + #{$this}__label {
background-image: linear-gradient(to top right, transparent calc(50% - 1px), color('border') calc(50% - 1px) calc(50% + 1px), transparent calc(50% + 1px));
color: color('muted');
cursor: not-allowed;
}
}
&__label {
@include transition($property: 'background-color, border-color, color');
align-items: center;
background-color: color('background', 'form');
border: config('border-width-base', $display) solid color('border', 'form');
border-radius: config('border-radius', $btn, false);
color: color('label', 'form');
cursor: pointer;
display: flex;
font-size: config('font-size-sm', $typography, false);
font-weight: 700;
justify-content: center;
min-block-size: 2.75rem;
min-inline-size: 2.75rem;
padding-inline: spacer('xs');
}
&:hover &__control:not(:checked, :disabled) + &__label {
border-color: color('primary');
}
}
<fieldset class="form-size-option" data-option-group>
<legend class="form-size-option__label">
Size: <span class="form-size-option__selected" data-option-selected>M</span>
</legend>
<div class="form-size-option__inner">
<label class="form-size">
<input class="form-size__control" type="radio" value="xs" name="size" data-label="XS"/>
<span class="form-size__label">XS</span>
</label>
<label class="form-size">
<input class="form-size__control" type="radio" value="s" name="size" data-label="S" disabled/>
<span class="form-size__label">S</span>
<span class="sr-only">(sold out)</span>
</label>
<label class="form-size">
<input class="form-size__control" type="radio" value="m" name="size" data-label="M" checked/>
<span class="form-size__label">M</span>
</label>
<label class="form-size">
<input class="form-size__control" type="radio" value="l" name="size" data-label="L"/>
<span class="form-size__label">L</span>
</label>
<label class="form-size">
<input class="form-size__control" type="radio" value="xl" name="size" data-label="XL"/>
<span class="form-size__label">XL</span>
</label>
<label class="form-size">
<input class="form-size__control" type="radio" value="xxl" name="size" data-label="XXL" disabled/>
<span class="form-size__label">XXL</span>
<span class="sr-only">(sold out)</span>
</label>
</div>
<p class="form-size-option__help"><a class="form-size-option__guide" href="#">Size guide</a></p>
</fieldset>
document.querySelectorAll('[data-option-group]').forEach((group) => {
const output = group.querySelector('[data-option-selected]');
group.addEventListener('change', (event) => {
output.textContent = event.target.dataset.label;
});
});