The following classes are added to the .sds-sectionForm__item element.
The JS snippet used is available under the Assets pane
<div class="sds-sectionForm__item sds-box -insetLg sds-stackMd">
<div class="sds-sectionForm__itemHeading sds-stackXs">
<h2 class="h3">Le projet</h2>
</div>
<div class="sds-sectionForm__itemBody sds-stackMd">
<div class="h3">Quel type de bien ?</div>
<div class="row row-sm row-cols-3">
<div class="col">
<div class="sds-spotSelect sds-showCustomIndicatorHover -centered">
<input type="radio" id="centeredSpotSelect-1" class="sds-spotSelect__radioInput sr-only" value="" name="radio-name">
<div data-scope-wrapper="box" data-scope="flat" class="sds-spotSelect__body">
<div class="sds-spotSelect__content">
<span class="sds-radioDot sds-spotSelect__checkItem" aria-hidden="true"></span>
<img src="../../media/illustrative-icons/sdsillu-housesaleb.svg" alt="">
<div class="sds-spotSelect__inner sds-stackMd">
<div class="sds-spotSelect__text">
<p><label class="sds-spotSelect__checkItemLabel" for="centeredSpotSelect-1">Acheter</label></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="sds-spotSelect sds-showCustomIndicatorHover -centered">
<input type="radio" id="centeredSpotSelect-2" class="sds-spotSelect__radioInput sr-only" checked value="" name="radio-name">
<div data-scope-wrapper="box" data-scope="flat" class="sds-spotSelect__body">
<div class="sds-spotSelect__content">
<span class="sds-radioDot sds-spotSelect__checkItem" aria-hidden="true"></span>
<img src="../../media/illustrative-icons/sdsillu-bulldozerb.svg" alt="">
<div class="sds-spotSelect__inner sds-stackMd">
<div class="sds-spotSelect__text">
<p><label class="sds-spotSelect__checkItemLabel" for="centeredSpotSelect-2">Construire</label></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="h3">Dans quel but ?</div>
<div class="row row-sm row-cols-3">
<div class="col">
<div class="sds-spotSelect sds-showCustomIndicatorHover -centered">
<input type="radio" id="centeredSpotSelect-1" class="sds-spotSelect__radioInput sr-only" value="" name="radio-name">
<div data-scope-wrapper="box" data-scope="flat" class="sds-spotSelect__body">
<div class="sds-spotSelect__content">
<span class="sds-radioDot sds-spotSelect__checkItem" aria-hidden="true"></span>
<img src="../../media/illustrative-icons/sdsillu-housesaleb.svg" alt="">
<div class="sds-spotSelect__inner sds-stackMd">
<div class="sds-spotSelect__text">
<p><label class="sds-spotSelect__checkItemLabel" for="centeredSpotSelect-1">Acheter</label></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="sds-spotSelect sds-showCustomIndicatorHover -centered">
<input type="radio" id="centeredSpotSelect-2" class="sds-spotSelect__radioInput sr-only" checked value="" name="radio-name">
<div data-scope-wrapper="box" data-scope="flat" class="sds-spotSelect__body">
<div class="sds-spotSelect__content">
<span class="sds-radioDot sds-spotSelect__checkItem" aria-hidden="true"></span>
<img src="../../media/illustrative-icons/sdsillu-bulldozerb.svg" alt="">
<div class="sds-spotSelect__inner sds-stackMd">
<div class="sds-spotSelect__text">
<p><label class="sds-spotSelect__checkItemLabel" for="centeredSpotSelect-2">Construire</label></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="h3">Ajoutez l'annonce immobilière (optionnel)</div>
<div class="row row-sm">
<div class="col-6">
<div class="form-group">
<label for="" class="sds-label -labelForm">
URL de l'annonce
</label>
<div class="sds-input">
<input id="" class="sds-input form-control" type="text" placeholder="https://www.athome.lu/appartement" value="">
</div>
</div>
</div>
</div>
</div>
<div class="sds-sectionForm__itemFooter">
<div class="sds-btnGroup">
<button type="button" class="sds-btn -btnSecondary -btnInverse">
<span class="sds-btn__text">Retour</span>
</button>
<button type="button" class="sds-btn -btnPrimary">
<span class="sds-btn__text">Continuer</span>
</button>
</div>
</div>
</div>
{% extends "@snet-section-form-frame" %}
{% block heading %}
<h2 class="h3">{{ headingTitle }}</h2>
{% endblock %}
{% block body %}
<div class="h3">Quel type de bien ?</div>
<div class="row row-sm row-cols-3">
{% for key, spotItem in spots %}
{% if spotItem %}
<div class="col">
{% render '@spot-select--centered',{
text: spotItem.text,
img: spotItem.img,
checked: spotItem.checked,
spotSelectID: spotItem.spotSelectID
}, true %}
</div>
{% endif %}
{% endfor %}
</div>
<div class="h3">Dans quel but ?</div>
<div class="row row-sm row-cols-3">
{% for key, spotItem in spots %}
{% if spotItem %}
<div class="col">
{% render '@spot-select--centered',{
text: spotItem.text,
img: spotItem.img,
checked: spotItem.checked,
spotSelectID: spotItem.spotSelectID
}, true %}
</div>
{% endif %}
{% endfor %}
</div>
<div class="h3">Ajoutez l'annonce immobilière (optionnel)</div>
<div class="row row-sm">
<div class="col-6">
{% render '@form-group',{
labelText: "URL de l'annonce",
placeholder: "https://www.athome.lu/appartement"
}, true %}
</div>
</div>
{% endblock %}
{% block footer %}
<div class="{{ namespace }}btnGroup">
{% if back %}
{% render '@btn-secondary-inverse',{text: "Retour"}, true %}
{% endif %}
{% render '@btn-primary',{text: "Continuer"}, true %}
</div>
{% endblock %}
export default class SectionForm {
constructor() {
this.scrollIndicators();
}
scrollIndicators() {
const scrollElement = document.querySelectorAll('.sds-sectionForm__itemBody');
function setShadows(element) {
let lastScrollTop = 0;
element.addEventListener("scroll", (e) => {
if (e.target.scrollTop === 0) {
element.parentNode.classList.remove("-shadowTop")
} else if (element.scrollTop < lastScrollTop){
// upscroll
element.parentNode.classList.add("-shadowTop")
element.parentNode.classList.add("-shadowBottom")
} else if (e.target.scrollTop > 0) {
element.parentNode.classList.add("-shadowTop")
}
// ending of scrollable area reached
lastScrollTop = element.scrollTop <= 0 ? 0 : element.scrollTop;
if (element.scrollHeight - element.scrollTop - element.clientHeight < 2) {
element.parentNode.classList.remove("-shadowBottom")
}
})
}
let ro = new ResizeObserver((entries, observer) => {
for (let entry of entries) {
if(entry.target.scrollHeight > entry.target.clientHeight){
entry.target.parentNode.classList.add("-shadowBottom");
setShadows(entry.target)
console.log("set shadows event")
} else if(entry.target.scrollHeight <= entry.target.clientHeight){
if(entry.target.parentNode.classList.contains("-shadowBottom")) {
entry.target.parentNode.classList.remove("-shadowBottom");
}
}
}
});
scrollElement.forEach((element, index) => {
ro.observe(element);
})
}
}
@use "sass:math";
.#{$namespace}sectionForm {
/* Save root element context for easy access if nesting is needed */
$self: &;
/* variables specific to current element */
$section-form-items-transition-duration: 0.45s;
$section-form-container-transition-duration: 0.25s;
/* properties of current element + media queries */
display: flex;
flex-direction: column;
//position: relative;
height: 100%;
margin-bottom: 0;
@include media-breakpoint-up(lg) {
flex-direction: column;
}
/* 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 */
&__item {
display: flex;
flex-direction: column;
position: relative;
height: 100%;
margin-bottom: 0;
@include spacer-component-stack("lg", true);
&.-hasStickyMobileBtn {
#{$self}__itemBody {
@include media-breakpoint-between(xs,sm) {
padding-bottom: map-deep-get($token-spacer-stack-max-map, "xl")*4;
}
}
}
&.-fullHeight {
height: auto;
#{$self}__itemBody {
overflow: visible;
}
}
#{$self}__itemHeading::before,
#{$self}__itemFooter::before {
content: "";
position: absolute;
left: -$box-lg-inset-spacing-desktop-global;
right: -$box-lg-inset-spacing-desktop-global;
height: map-deep-get($token-sizes-unit-map, "12");
background-color: transparent;
z-index: z("negative");
}
&.-shadowTop {
#{$self}__itemHeading::before {
top: calc(100% + map-deep-get($token-spacer-stack-max-map, "lg"));
opacity: 1;
z-index: z("low");
background-image: radial-gradient(farthest-side at 50% 0%, rgba($color-brand-secondary-20, 0.24) 0%, rgba($color-brand-secondary-20, 0) 100%);
}
}
&.-shadowBottom {
#{$self}__itemFooter::before {
bottom: calc(100% + map-deep-get($token-spacer-stack-max-map, "lg"));
opacity: 1;
z-index: z("low");
background-image: radial-gradient(farthest-side at 50% 100%, rgba($color-brand-secondary-20, 0.24) 0%, rgba($color-brand-secondary-20, 0) 100%);
}
}
}
// sectionForm__itemBody
&__itemBody {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
padding-bottom: map-deep-get($token-spacer-unit-map, "64");
/* necessary tweak because of the overflow hidden behaviour */
padding-left: $box-lg-inset-spacing-mobile-global;
padding-right: $box-lg-inset-spacing-mobile-global;
margin-left: -$box-lg-inset-spacing-mobile-global;
margin-right: -$box-lg-inset-spacing-mobile-global;
@include media-breakpoint-up(lg) {
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 0;
overscroll-behavior: none;
/* necessary tweak because of the overflow hidden behaviour */
padding-left: $box-lg-inset-spacing-desktop-global;
padding-right: $box-lg-inset-spacing-desktop-global;
margin-left: -$box-lg-inset-spacing-desktop-global;
margin-right: -$box-lg-inset-spacing-desktop-global;
}
}
&__itemHeading,
&__itemFooter {
@include media-breakpoint-up(lg) {
position: relative;
}
}
&__itemFooter {
display: flex;
justify-content: flex-end;
@include spacer-component-inline(sm);
position: fixed;
z-index: z("sticky");
bottom: 0;
left: 0;
right: 0;
background-color: inherit;
padding: $snet-frame-main-horiz-padding-mobile-global $snet-frame-main-horiz-padding-mobile-global calc(#{$snet-frame-main-horiz-padding-mobile-global} + env(safe-area-inset-bottom)) $snet-frame-main-horiz-padding-mobile-global;
border-top-left-radius: map-deep-get($token-radius-map, "16");
border-top-right-radius: map-deep-get($token-radius-map, "16");
box-shadow: map-deep-get($token-shadow-map, "sidebar");
transform: translateY(100%);
transition: opacity math.div($section-form-items-transition-duration, 2) ease-out, transform 0.1s linear;
@include media-breakpoint-up(lg) {
position: static;
padding: 0;
border-radius: 0;
box-shadow: none;
transform: none;
}
}
&__stickyFooterBtn {
position: absolute;
bottom: calc(100% + #{map-deep-get($token-spacer-unit-map, "8")});
left: 0;
right: 0;
text-align: center;
opacity: 0;
visibility: hidden;
transition: opacity 0.25s linear;
@include media-breakpoint-up(md) {
position: static;
transform: none;
opacity: 1;
visibility: visible;
}
&.-shown {
opacity: 1;
visibility: visible;
@include media-breakpoint-between(xs,sm) {
margin-right: 0 !important;
}
}
}
&__container {
flex-shrink: 0;
transition: transform $section-form-container-transition-duration ease-out;
width: 100%;
height: 100%;
top: 0;
left: 0;
@include media-breakpoint-up(lg) {
position: absolute;
left: 50%;
transform: translate(-50%,0) scale(1);
}
#{$self}__itemHeading,
#{$self}__itemBody,
#{$self}__itemFooter {
opacity: 0;
visibility: hidden;
transition: opacity $section-form-container-transition-duration $section-form-container-transition-duration ease-out, visibility 0 math.div($section-form-container-transition-duration, 2) linear;
transition-delay: $section-form-items-transition-duration;
}
&.-prev {
position: absolute;
transform: translate(calc(-100% + #{map-deep-get($token-spacer-inset-map, "sm")}),0);
@include media-breakpoint-up(lg) {
transform: translate(-50%,-96%) scale(0.90);
}
}
&.-isActive {
position: relative;
@include media-breakpoint-up(lg) {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%,0) scale(1);
}
#{$self}__itemHeading,
#{$self}__itemBody,
#{$self}__itemFooter {
opacity: 1;
visibility: visible;
transition: opacity $section-form-items-transition-duration math.div($section-form-items-transition-duration, 2) linear;
}
#{$self}__itemFooter {
transition: opacity math.div($section-form-items-transition-duration, 2) $section-form-items-transition-duration ease-out, transform math.div($section-form-items-transition-duration, 2) $section-form-items-transition-duration ease-out;
transform: translateY(0);
}
}
&.-next {
position: absolute;
transform: translate(calc(100% - #{map-deep-get($token-spacer-inset-map, "sm")}),0);
@include media-breakpoint-up(lg) {
transform: translate(-50%,96%) scale(0.90);
}
}
}
&__actionCardContainer {
margin-top: map-deep-get($token-spacer-unit-map, "24");
}
&__actionCard {
border: $border-width solid $border-color;
border-radius: map-deep-get($token-radius-map, "16");
padding: map-deep-get($token-spacer-inset-map, "lg");
background-color: map-deep-get($token-color-grayscale-map, "0");
}
&__divider {
width: 100%;
height: $border-width;
@include custom-prop-fallback("background-color", "sys-color-border-primary-moderate");
}
&__titlePretHyp {
margin-top: map-deep-get($token-spacer-unit-map, "48");
}
&__inputShadowAction {
display: flex;
align-items: center;
@include spacer-component-inline("md");
}
/* modifiers */
// sectionForm -recap
&.-recap {
#{$self}__itemHeading {
display: flex;
justify-content: center;
}
#{$self}__actionCardContainer {
margin-top: map-deep-get($token-spacer-unit-map, "64");
}
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}