The SVG variant has a different structure. The data-toggle="radios" attribute and btn-group-toggle class are removed and each button has an aria-pressed attribute that needs to be set to true through javascript.
Add is-invalid to the sds-captcha__inner element to show the error message.
Hints are added depending on the type of elements present in the component. See the "text words" and "text large" examples for variations of hints displays.
<div class="sds-captcha">
<div class="sds-captcha__inner">
<button type="button" class="sds-badgeSelector sds-captcha__selectorShape" aria-pressed="true">
<img src="../../media/snet/components/recaptcha/DHxiFL13zv.svg" alt="">
</button>
<button type="button" class="sds-badgeSelector sds-captcha__selectorShape" aria-pressed="false">
<img src="../../media/snet/components/recaptcha/gYb6gEJ7s0.svg" alt="">
</button>
<button type="button" class="sds-badgeSelector sds-captcha__selectorShape" aria-pressed="false">
<img src="../../media/snet/components/recaptcha/h4bdB8o8Vh.svg" alt="">
</button>
<button type="button" class="sds-badgeSelector sds-captcha__selectorShape" aria-pressed="false">
<img src="../../media/snet/components/recaptcha/LmZme1QA4o.svg" alt="">
</button>
<button type="button" class="sds-badgeSelector sds-captcha__selectorShape" aria-pressed="false">
<img src="../../media/snet/components/recaptcha/s39JkVLwcN.svg" alt="">
</button>
</div>
<div class="sds-captcha__error invalid-feedback">
captcha error message
</div>
</div>
<div class="{{ namespace }}captcha{% for mod in modifiers %} {{ mod }}{% endfor %}{% for mod in classes %} {{ mod }}{% endfor %}">
<div class="{{ namespace }}captcha__inner{% if error %} is-invalid{% endif %}">
{% for key, item in formElementButtons %}
{% render "@badge-selector",{
eltType: "button",
svg: item.svg,
classes: item.classes,
icon: item.icon,
attrs: {
"aria-pressed": item.pressed or "false"
}
},true %}
{% endfor %}
</div>
<div class="{{ namespace }}captcha__error invalid-feedback">
captcha error message
</div>
</div>
/* variables specific to current element */
$element-specific-variables: "";
.#{$namespace}captcha {
/* 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 */
// recaptcha__childElement
&__selectorShape {
// follows same logic as parent
cursor: pointer;
flex-grow: 1;
/* if button */
&[aria-pressed="true"] {
@include custom-prop-fallback("color", "comp-button-secondary-text-color");
@include custom-prop-fallback("border-color", "comp-button-secondary-text-color");
}
/* if nps */
&[class*="-nps"] {
@include custom-prop-fallback("color", "sys-color-background-primary-160");
input[type="radio"]:checked + & {
outline: $border-width*2 solid;
@include custom-prop-fallback("outline-color","comp-button-secondary-text-color");
outline-offset: $border-width*2;
box-shadow: none !important;
}
}
@each $key, $value in $token-color-nps-map {
$classname: camelize(nps-#{$key});
&.-#{$classname} {
background-color: #{$value};
@if $key == "0" or $key == "1" or $key == "2" {
@include custom-prop-fallback("color", "sys-color-text-neutral-inverse",true,true);
}
}
}
}
&__inner {
@include spacer-component-inline("sm");
display: inline-flex;
}
#{$self}__innerWrapper {
width: fit-content;
}
&__item {
display: flex;
}
INPUT:focus + #{$self}__selectorShape,
INPUT:checked + #{$self}__selectorShape {
@include custom-prop-fallback("border-color", "comp-button-secondary-text-color");
@include custom-prop-fallback("color", "comp-button-secondary-text-color");
}
/* modifiers */
// recaptcha -isDisabled
[disabled] + #{$self}__selectorShape {
@include custom-prop-fallback("color","sys-color-text-neutral-vivid",true,true);
pointer-events: none;
cursor: not-allowed;
}
&__error {
padding-left: 0;
}
&__hint {
margin-top: map-deep-get($token-spacer-stack-max-map, "xxs");
@include custom-prop-fallback("color", "sys-color-text-primary-muted");
display: flex;
justify-content: space-between;
}
&__hint + &__inner {
@include media-breakpoint-between(xs,xs) {
margin-top: map-deep-get($token-spacer-unit-map, "2");
}
}
&.-wrap {
#{$self}__inner {
@include media-breakpoint-up("sm") {
flex-wrap: wrap;
margin-bottom: -(#{map-deep-get($token-spacer-stack-max-map, "sm")});
> * {
margin-bottom: #{map-deep-get($token-spacer-stack-max-map, "sm")};
}
}
}
}
&.-itemsAlignedBlockStart {
@include media-breakpoint-between(xs, xs) {
display: block;
}
#{$self}__selectorShape {
display: flex;
justify-content: flex-start;
}
}
&.-blockDisplay {
@include media-breakpoint-between(xs, xs) {
display: block;
}
#{$self}__innerWrapper {
width: auto;
@include media-breakpoint-up(sm) {
width: fit-content;
}
}
#{$self}__inner {
@include media-breakpoint-between(xs, xs) {
display: block;
}
@include spacer-component-stack("sm");
@include media-breakpoint-up(sm) {
@include unset-spacer-component-stack();
}
> * {
@include media-breakpoint-between(xs, xs) {
display: block;
width: 100%;
margin-right: 0 !important;
}
}
}
}
&.-wrapItems {
#{$self}__inner {
flex-wrap: wrap;
@include unset-spacer-component-inline();
gap: map-deep-get($token-spacer-inline-map, "sm");
}
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}
/* variables specific to current element */
$element-specific-variables: "";
.#{$namespace}recaptcha {
/* Save root element context for easy access if nesting is needed */
$self: &;
/* properties of current element + media queries */
width: max-content;
/* 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 */
// recaptcha__childElement
&__selectorShape {
// follows same logic as parent
cursor: pointer;
/* if button */
&[aria-pressed="true"] {
border: $border-width*2 solid;
color: map-deep-get($token-color-brand-map, "secondary", "100");
}
}
&__inner {
@include spacer-component-inline("sm");
}
INPUT:checked + #{$self}__selectorShape {
box-shadow: inset 0 0 0 $border-width*2 map-deep-get($token-color-brand-map, "secondary", "100") !important;
color: map-deep-get($token-color-brand-map, "secondary", "100");
}
/* modifiers */
// recaptcha -isDisabled
[disabled] + #{$self}__selectorShape {
color: map-deep-get($token-color-brand-map, "fade", "100") !important;
pointer-events: none;
cursor: not-allowed;
}
&__error {
padding-left: 0;
}
&__hint {
margin-top: map-deep-get($token-spacer-stack-max-map, "xxs");
color: map-deep-get($token-color-brand-map, "secondary", "60");
display: flex;
justify-content: space-between;
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}