The row-cols-#{$breakpoint}-#{$size} bootstrap classes are set on the sds-spotSelectList element. By using the row-cols classes, we can retain bootstrap's row/col flexibility inside the module, without having to adapt the col-* classes.
The row class always needs to be set by default. row-xs and row-sm classes can be added as modifiers as well to adapt the gutter width between columns.
Add the classes sds-groupedFramedChoice__firstItem and sds-groupedFramedChoice__lastItem to the LI elements for their child elements to retain their border-radius when sibling elements are not visible.
The error state is handled like so:
The framed choice radio variant never has its error message shown inside the framed choice component, instead it is only ever applied to a group context.
If no heading were to precede the radio group, you can remove the fieldset and legend elements. It is not advised to do so as it could lead to accessibility concerns.
<fieldset class="sds-stackMd">
<legend class="h3">Grouped framed choice</legend>
<ul class="sds-groupedFramedChoice list-unstyled row row-cols-md-2">
<li class="sds-groupedFramedChoice__item col">
<div class="sds-framedChoice sds-showCustomIndicatorHover">
<input name="framedChoiceInput" type="radio" id="groupedFramedChoice-1" class="sds-framedChoice__input sr-only is-invalid" aria-invalid="true" aria-describedby="">
<div class="sds-framedChoice__body" data-scope-wrapper="box" data-scope="flat">
<div class="sds-framedChoice__content sds-staticGapMd">
<div class="sds-framedChoice__inputShape d-flex">
<span class="sds-radioDot " aria-hidden="true"></span>
</div>
<div class="sds-framedChoice__media">
<div class="sds-media -mediaSm">
<img src="../../media/spuerkeess-site/components/product/cards/sdsillu-product-card-classic.png" alt="">
</div>
</div>
<div class="flex-grow-1">
<div class="sds-staticStackXxs">
<p class="h4">
<label for="groupedFramedChoice-1" class="stretched-link">John Doe</label>
</p>
<p>
<label for="groupedFramedChoice-1" class="stretched-link">Test</label>
</p>
</div>
</div>
<div class="sds-aboveClickArea">
<button type="button" class="sds-infoDot" data-toggle="modal" data-target="#">
<span class="sds-icon sds-icon-infocircleborder"></span>
<span class="sr-only">Show more info</span>
</button>
</div>
</div>
</div>
</div>
</li>
<li class="sds-groupedFramedChoice__item col">
<div class="sds-framedChoice sds-showCustomIndicatorHover">
<input name="framedChoiceInput" type="radio" id="groupedFramedChoice-2" class="sds-framedChoice__input sr-only is-invalid" aria-invalid="true" aria-describedby="">
<div class="sds-framedChoice__body" data-scope-wrapper="box" data-scope="flat">
<div class="sds-framedChoice__content sds-staticGapMd">
<div class="sds-framedChoice__inputShape d-flex">
<span class="sds-radioDot " aria-hidden="true"></span>
</div>
<div class="sds-framedChoice__media">
<div class="sds-media -mediaSm">
<img src="../../media/spuerkeess-site/components/product/cards/sdsillu-product-card-classic.png" alt="">
</div>
</div>
<div class="flex-grow-1">
<div class="sds-staticStackXxs">
<p class="h4">
<label for="groupedFramedChoice-2" class="stretched-link">John Doe</label>
</p>
<p>
<label for="groupedFramedChoice-2" class="stretched-link">Test</label>
</p>
</div>
</div>
<div class="sds-aboveClickArea">
<button type="button" class="sds-infoDot" data-toggle="modal" data-target="#">
<span class="sds-icon sds-icon-infocircleborder"></span>
<span class="sr-only">Show more info</span>
</button>
</div>
</div>
</div>
</div>
</li>
<li class="sds-groupedFramedChoice__item col">
<div class="sds-framedChoice sds-showCustomIndicatorHover">
<input name="framedChoiceInput" type="radio" id="groupedFramedChoice-3" class="sds-framedChoice__input sr-only is-invalid" aria-invalid="true" aria-describedby="">
<div class="sds-framedChoice__body" data-scope-wrapper="box" data-scope="flat">
<div class="sds-framedChoice__content sds-staticGapMd">
<div class="sds-framedChoice__inputShape d-flex">
<span class="sds-radioDot " aria-hidden="true"></span>
</div>
<div class="sds-framedChoice__media">
<div class="sds-media -mediaSm">
<img src="../../media/spuerkeess-site/components/product/cards/sdsillu-product-card-classic.png" alt="">
</div>
</div>
<div class="flex-grow-1">
<div class="sds-staticStackXxs">
<p class="h4">
<label for="groupedFramedChoice-3" class="stretched-link">John Doe</label>
</p>
<p>
<label for="groupedFramedChoice-3" class="stretched-link">Test</label>
</p>
</div>
</div>
<div class="sds-aboveClickArea">
<button type="button" class="sds-infoDot" data-toggle="modal" data-target="#">
<span class="sds-icon sds-icon-infocircleborder"></span>
<span class="sr-only">Show more info</span>
</button>
</div>
</div>
</div>
</div>
</li>
<li class="sds-groupedFramedChoice__item col">
<div class="sds-framedChoice sds-showCustomIndicatorHover">
<input name="framedChoiceInput" type="radio" id="groupedFramedChoice-4" class="sds-framedChoice__input sr-only is-invalid" aria-invalid="true" aria-describedby="">
<div class="sds-framedChoice__body" data-scope-wrapper="box" data-scope="flat">
<div class="sds-framedChoice__content sds-staticGapMd">
<div class="sds-framedChoice__inputShape d-flex">
<span class="sds-radioDot " aria-hidden="true"></span>
</div>
<div class="sds-framedChoice__media">
<div class="sds-media -mediaSm">
<img src="../../media/spuerkeess-site/components/product/cards/sdsillu-product-card-classic.png" alt="">
</div>
</div>
<div class="flex-grow-1">
<div class="sds-staticStackXxs">
<p class="h4">
<label for="groupedFramedChoice-4" class="stretched-link">John Doe</label>
</p>
<p>
<label for="groupedFramedChoice-4" class="stretched-link">Test</label>
</p>
</div>
</div>
<div class="sds-aboveClickArea">
<button type="button" class="sds-infoDot" data-toggle="modal" data-target="#">
<span class="sds-icon sds-icon-infocircleborder"></span>
<span class="sr-only">Show more info</span>
</button>
</div>
</div>
</div>
</div>
</li>
<li class="sds-groupedFramedChoice__item col">
<div class="sds-framedChoice sds-showCustomIndicatorHover">
<input name="framedChoiceInput" type="radio" id="groupedFramedChoice-5" class="sds-framedChoice__input sr-only is-invalid" aria-invalid="true" aria-describedby="">
<div class="sds-framedChoice__body" data-scope-wrapper="box" data-scope="flat">
<div class="sds-framedChoice__content sds-staticGapMd">
<div class="sds-framedChoice__inputShape d-flex">
<span class="sds-radioDot " aria-hidden="true"></span>
</div>
<div class="sds-framedChoice__media">
<div class="sds-media -mediaSm">
<img src="../../media/spuerkeess-site/components/product/cards/sdsillu-product-card-classic.png" alt="">
</div>
</div>
<div class="flex-grow-1">
<div class="sds-staticStackXxs">
<p class="h4">
<label for="groupedFramedChoice-5" class="stretched-link">John Doe</label>
</p>
<p>
<label for="groupedFramedChoice-5" class="stretched-link">Test</label>
</p>
</div>
</div>
<div class="sds-aboveClickArea">
<button type="button" class="sds-infoDot" data-toggle="modal" data-target="#">
<span class="sds-icon sds-icon-infocircleborder"></span>
<span class="sr-only">Show more info</span>
</button>
</div>
</div>
</div>
</div>
</li>
</ul>
</fieldset>
<fieldset class="{{ namespace }}stackMd">
<legend class="h3">Grouped framed choice</legend>
<ul class="{{ namespace }}groupedFramedChoice list-unstyled row{% for mod in rowModifiers %} {{ mod }}{% endfor %}{% for mod in rowClasses %} {{ mod }}{% endfor %}{% if error %} is-invalid{% endif %}">
{% for i in range(0,5) %}
<li class="{{ namespace }}groupedFramedChoice__item col">
{% render "@framed-choice", {
error: true,
hintID: "groupeFramedChoiceErrorMessage",
id: "groupedFramedChoice-" + loop.index
}, true %}
</li>
{% endfor %}
</ul>
{% if error %}
<div class="invalid-feedback">
{% render "@hint--error",{
text: "error message",
attrs: {
"id": "groupeFramedChoiceErrorMessage"
}
},true %}
</div>
{% endif %}
</fieldset>
/* variables specific to current element */
$element-specific-variables: "";
.#{$namespace}groupedFramedChoice {
/* Save root element context for easy access if nesting is needed */
$self: &;
/* properties of current element + media queries */
/* Pseudo Elements */
&::before {
}
&::after {
}
/*
Include elements that are linked to the current element but have to reside at the root level of the stylesheet
(e.g: keyframes)
*/
@at-root {
}
/* children - write selector in full in comments in order to facilitate search */
// groupedFramedChoice__childElement
&__item {
// follows same logic as parent
}
&__item {
border-radius: 0;
&#{$self}__firstItem,
&:first-of-type {
border-top-left-radius: var(--comp-framed-choice-border-radius);
border-top-right-radius: var(--comp-framed-choice-border-radius);
}
&#{$self}__lastItem,
&:last-of-type {
border-bottom-left-radius: var(--comp-framed-choice-border-radius);
border-bottom-right-radius: var(--comp-framed-choice-border-radius);
}
> * {
border-radius: inherit;
}
& + & {
> * {
@include custom-prop-fallback("margin-top","comp-framed-choice-border-width","true","false","true")
}
}
}
&.row,
&.row-sm,
&.row-xs {
margin-bottom: 0;
> [class*="col"] {
margin-bottom: 0;
flex-basis: 100%;
}
}
@each $breakpoint in map-keys(map-remove($grid-breakpoints, "xs")) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@include media-breakpoint-up($breakpoint, $grid-breakpoints) {
@if $grid-row-columns > 0 {
&[class*="row-cols#{$infix}"] {
margin-bottom: -(map-deep-get($token-spacer-grid-map, "gutter"));
> [class*="col"] {
margin-bottom: map-deep-get($token-spacer-grid-map, "gutter");
}
@each $key, $value in map-remove($token-spacer-grid-map, "gutter") {
&.row-#{$key} {
margin-bottom: -($value);
> [class*="col"] {
margin-bottom: $value;
}
}
}
}
&[class*="row-cols#{$infix}"] {
#{$self}__item {
border-radius: var(--comp-framed-choice-border-radius);
> * {
margin-top: 0 !important;
}
}
}
}
}
}
/* modifiers */
// groupedFramedChoice -altStyle
&.-altStyle {
// follows same logic as base element
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}