See "img upload" in sidebar snet/molecules for variants, or go to info panel and look for it in "references" (@snet-img-upload)
Refer to modal frame found in view tab for complete structure without content.
A modal's default size is 640px
Modifier classes for modals
A modal with a content loading component behaves as follows:
<div class="sds-modal modal fade -showFromRight -bodySecondary06" id="panierModal" aria-labelledby="panierModalTitle" aria-modal="true" role="dialog" tabindex="-1">
<div class="sds-modal__dialog modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="sds-modal__content modal-content">
<div class="sds-modal__header modal-header">
<div class="sds-modal__title modal-title" id="panierModalTitle">Commandes</div>
<button type="button" class="sds-btn -iconBtn -btnSecondary -ghost sds-modal__close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" class="sds-icon sds-icon-close"></span>
</button>
</div>
<div class="sds-modal__body modal-body">
<div class="sds-stackLg">
<div class="sds-box -insetLg sds-stackLg">
<div class="row row-sm align-items-center no-bottom-gutter">
<div class="col">
<div class="h4">A signer</div>
</div>
<div class="col-auto flex-shrink-0">
<div class="d-flex align-items-center sds-staticInlineMd">
<div class="sds-textHelper">Expire dans 7 jours</div>
<ul class="sds-btnGroup">
<li>
<button type="button" class="sds-btn -iconBtn -btnSecondary">
<span aria-hidden="true" class="sds-icon sds-icon-trash"></span>
</button>
</li>
<li>
<button type="button" class="sds-btn -btnSecondary">
<span class="sds-icon sds-icon-sign"></span>
<span class="sds-btn__text">
Signer
</span>
</button>
</li>
</ul>
</div>
</div>
</div>
<div class="row row-xs align-items-center no-bottom-gutter">
<div class="col-3">
<img class="img-fluid" src="https://design.spuerkeess.lu/media/illustrations/svg750x560/hero/sdsillu-packagefull.svg" alt="">
</div>
<div class="col">
<div class="sds-staticStackXxs">
<h5 class="h5">
Zebra Premium
</h5>
<div class="sds-textHelper sds-metaColor">
8,50 € / mois
</div>
</div>
</div>
</div>
</div>
<div id="timelineAccordion" class="sds-timeline -firstItemNoLine">
<div class="sds-box sds-timeline__item">
<div class="sds-sectionTitle -isTimelineItem">
<div class="sds-sectionTitle__inner">
<div class="sds-sectionTitle__col">
<div class="sds-sectionTitle__textMain">
{ Month }
</div>
</div>
</div>
<div class="sds-sectionTitle__toggleWrapper">
<button type="button" class="sds-btn -iconBtn -btnSecondary -btnSmall sds-sectionTitle__toggle stretched-link" data-toggle="collapse" data-target="#timelineCollapse-0" aria-expanded="true">
<span aria-hidden="true" class="sds-icon sds-icon-plus"></span>
<div class="sr-only">Toggle transactions list</div>
</button>
</div>
</div>
<div class="collapse show" id="timelineCollapse-0">
<div class="sds-timeline__collapseInner">
<div class="sds-sectionItemTimeline">
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sds-box sds-timeline__item">
<div class="sds-sectionTitle -isTimelineItem">
<div class="sds-sectionTitle__inner">
<div class="sds-sectionTitle__col">
<div class="sds-sectionTitle__textMain">
{ Month }
</div>
</div>
</div>
<div class="sds-sectionTitle__toggleWrapper">
<button type="button" class="sds-btn -iconBtn -btnSecondary -btnSmall sds-sectionTitle__toggle stretched-link" data-toggle="collapse" data-target="#timelineCollapse-1" aria-expanded="true">
<span aria-hidden="true" class="sds-icon sds-icon-plus"></span>
<div class="sr-only">Toggle transactions list</div>
</button>
</div>
</div>
<div class="collapse show" id="timelineCollapse-1">
<div class="sds-timeline__collapseInner">
<div class="sds-sectionItemTimeline">
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sds-box sds-timeline__item">
<div class="sds-sectionTitle -isTimelineItem">
<div class="sds-sectionTitle__inner">
<div class="sds-sectionTitle__col">
<div class="sds-sectionTitle__textMain">
{ Month }
</div>
</div>
</div>
<div class="sds-sectionTitle__toggleWrapper">
<button type="button" class="sds-btn -iconBtn -btnSecondary -btnSmall sds-sectionTitle__toggle stretched-link" data-toggle="collapse" data-target="#timelineCollapse-2" aria-expanded="true">
<span aria-hidden="true" class="sds-icon sds-icon-plus"></span>
<div class="sr-only">Toggle transactions list</div>
</button>
</div>
</div>
<div class="collapse show" id="timelineCollapse-2">
<div class="sds-timeline__collapseInner">
<div class="sds-sectionItemTimeline">
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="sds-sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="sds-sectionItem__inner">
<div class="sds-sectionItem__innerCol -date">
<div class="sds-sectionItem__textMeta sds-textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="sds-sectionItem__innerCol -dot">
<div class="sds-sectionItem__dotWrapper">
<span class="sds-iconCircle sds-sectionItem__statusIcon" aria-hidden="true">
<span class="sds-icon sds-icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="sds-sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="sds-sectionItem__textMeta sds-textHelper">{ Additional Info }</p>
</div>
</div>
<div class="sds-sectionItem__innerCol">
<div class="sds-sectionItem__statusText sds-textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% extends "@snet-modal-base-frame" %}
{% block header %}
<div class="{{ namespace }}modal__title modal-title" id="{{ modalTitleID }}">{{ title }}</div>
{% endblock %}
{% block body %}
<div class="{{ namespace }}stackLg">
<div class="{{ namespace }}box -insetLg {{ namespace }}stackLg">
<div class="row row-sm align-items-center no-bottom-gutter">
<div class="col">
<div class="h4">A signer</div>
</div>
<div class="col-auto flex-shrink-0">
<div class="d-flex align-items-center {{ namespace }}staticInlineMd">
<div class="{{ namespace }}textHelper">Expire dans 7 jours</div>
<ul class="{{ namespace }}btnGroup">
<li>
{% render "@icon-btn-secondary",{
icon: "icon-trash"
},true %}
</li>
<li>
{% render "@btn-secondary--icon-left",{
icon: "icon-sign",
text: "Signer"
},true %}
</li>
</ul>
</div>
</div>
</div>
<div class="row row-xs align-items-center no-bottom-gutter">
<div class="col-3">
<img class="img-fluid" src="https://design.spuerkeess.lu/media/illustrations/svg750x560/hero/sdsillu-packagefull.svg" alt="">
</div>
<div class="col">
<div class="{{ namespace }}staticStackXxs">
{% render "@heading--h5",{
text: "Zebra Premium"
},true %}
<div class="{{ namespace }}textHelper {{ namespace }}metaColor">
8,50 € / mois
</div>
</div>
</div>
</div>
</div>
<div id="timelineAccordion" class="{{ namespace }}timeline -firstItemNoLine">
{% for i in range(0,3) %}
<div class="{{ namespace }}box {{ namespace }}timeline__item">
{% render "@snet-section-title",
{
text: "{ Month }",
toggle: true,
toggleOptions: {
"data-toggle": "collapse",
"data-target": "#timelineCollapse-"+i,
"aria-expanded": "true"
}
},true %}
<div class="collapse show" id="timelineCollapse-{{ i }}">
<div class="{{ namespace }}timeline__collapseInner">
<div class="{{ namespace }}sectionItemTimeline">
{% if loop.first %}
<div class="{{ namespace }}sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="{{ namespace }}sectionItem__inner">
<div class="{{ namespace }}sectionItem__innerCol -date">
<div class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -dot">
<div class="{{ namespace }}sectionItem__dotWrapper">
<span class="{{ namespace }}iconCircle {{ namespace }}sectionItem__statusIcon" aria-hidden="true">
<span class="{{ namespace }}icon {{ namespace }}icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">{ Additional Info }</p>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol">
<div class="{{ namespace }}sectionItem__statusText {{ namespace }}textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
{% else %}
{% for i in range(0,5) %}
<div class="{{ namespace }}sectionItem -isTimelineItem -statusPositive -isStatic">
<div class="{{ namespace }}sectionItem__inner">
<div class="{{ namespace }}sectionItem__innerCol -date">
<div class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -dot">
<div class="{{ namespace }}sectionItem__dotWrapper">
<span class="{{ namespace }}iconCircle {{ namespace }}sectionItem__statusIcon" aria-hidden="true">
<span class="{{ namespace }}icon {{ namespace }}icon-checkcircleborder"></span>
</span>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">{ Additional Info }</p>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol">
<div class="{{ namespace }}sectionItem__statusText {{ namespace }}textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
<div class="{{ namespace }}sectionItem -isTimelineItem -statusNegative -isStatic">
<div class="{{ namespace }}sectionItem__inner">
<div class="{{ namespace }}sectionItem__innerCol -date">
<div class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">
{DD.MM.YYYY}
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -dot">
<div class="{{ namespace }}sectionItem__dotWrapper">
<span class="{{ namespace }}iconCircle {{ namespace }}sectionItem__statusIcon" aria-hidden="true">
<span class="{{ namespace }}icon {{ namespace }}icon-crosscircleborder"></span>
</span>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol -grow -content">
<div>
<p>{ Product }</p>
<p class="{{ namespace }}sectionItem__textMeta {{ namespace }}textHelper">{ Additional Info }</p>
</div>
</div>
<div class="{{ namespace }}sectionItem__innerCol">
<div class="{{ namespace }}sectionItem__statusText {{ namespace }}textSemiBold">
{ Status }
</div>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
export default class ModalTrap {
constructor() {
// select all modals with the dialog role and modal classe.
// this ensures that only modals with the right attributes are selected
this.modals = document.querySelectorAll("[role='dialog'].modal");
// select all modal trigger buttons that don't have a data-dismiss attribute
// buttons with data-dismiss and data-toggle are typically only used within modals to trigger another modal
// we want to exclude these from the selection
this.modalToggles = document.querySelectorAll("[data-toggle='modal']:not([data-dismiss='modal'])");
// list of focusable elements inside a modal
this.focusableElements = [
"a[href]",
"button:not([disabled])",
"textarea:not([disabled])",
"input:not([disabled])",
"select:not([disabled])",
"[tabindex]:not([tabindex='-1'])"
];
// this will ensure that any modal with the dialog-scrollable modifier gets the intended behaviour
// all other modals will get ignored
this.modalScrollBody = ".modal-dialog-scrollable .modal-body"
// modal trigger element with same data-target value as id of triggered modal
this.modalTriggerElement = null;
// Used to store keydown handlers per modal
this.focusHandlers = new WeakMap();
this.init();
}
init() {
// loop over all modal trigger buttons
this.modalToggles.forEach(btn => {
// if data target value is erroneous or doesn't match any modal ID, return false
const targetSelector = btn.getAttribute('data-target');
if ((targetSelector === "#") || (!targetSelector)) return;
// on modal trigger interaction, set the modal trigger element's value to that of its DOM representation
// and store it
btn.addEventListener('click', (e) => {
e.preventDefault();
this.modalTriggerElement = e.target;
});
});
// loop over all modals
this.modals.forEach(modal => {
const closeBtn = modal.querySelector('.sds-modal__close');
// when a modal shown event is fired:
$(modal).on('shown.bs.modal', (e) => {
// check if a close button exists and focus it if so
if (closeBtn) {
closeBtn.focus();
}
else {
// if no close is present focus first focusable element instead
let focusableElements = this.getFocusableElements(modal);
let first = focusableElements[0];
first.focus()
}
// check for a scrollable body element inside the modal
// set focus trap inside modal while open
this.checkScrollabilityAndSetFocusTrap(modal);
/*
* if the modal gets shown through the bootstrap method instead of
* through a trigger element interaction, store the value of the trigger element
* so it can be focused when closing the modal
*
* this will ensure that no matter how the modal is shown,
* there's always an element to put the focus back on when closed
*
* closing a modal after navigating from modal to modal will also put the focus back on
* the initial modal trigger element or corresponding modal's trigger element, if applicable
* for this purpose, modal trigger elements inside modals that have the data-dismiss="modal" attribute are ignored
*/
let lastFocusedElement = document.querySelector("[data-toggle='modal']:not([data-dismiss='modal'])[data-target='#"+ e.target.getAttribute("id") +"']");
if (lastFocusedElement) {
this.modalTriggerElement = lastFocusedElement;
}
});
$(modal).on('hidden.bs.modal', (e) => {
// if it exists focus the modal's trigger element upon closing the modal
if (this.modalTriggerElement) {
this.modalTriggerElement.focus();
}
});
});
}
checkScrollabilityAndSetFocusTrap(modal) {
const modalBodySelector = this.modalScrollBody;
// check if the modal scrollable modifier is applied to the current modal
// if not, the last element to receive focus will be the modal itself
const modalBody = modal.querySelector(modalBodySelector) ? modal.querySelector(modalBodySelector) : modal;
// add or remove tabindex depending on whether the modal body area is scrollable
function setScrollability () {
const isScrollable = modalBody.scrollHeight > modalBody.clientHeight;
if (isScrollable) {
// Ensure it's focusable
if (!modalBody.hasAttribute('tabindex')) {
modalBody.setAttribute('tabindex', '0');
}
} else {
if (modalBody.hasAttribute('tabindex')) {
modalBody.removeAttribute('tabindex');
}
}
}
// check if modal body is scriollable or not on page load
setScrollability();
// Initial trap
this.trapFocus(modal);
// Observe scrollability changes
const observer = new ResizeObserver(() => {
// check if modal body becomes scrollable on resize
setScrollability();
this.trapFocus(modal);
});
// Required to detect resizing/scrollability
observer.observe(modalBody);
}
// trap the kesyboard focus navigfation inside the modal while it is shown
trapFocus(modal) {
const focusable = this.getFocusableElements(modal);
// abort if no focusable elements are found inside modal
if (!focusable.length) return;
// define first and last focusable elements inside modal
const first = focusable[0];
const last = focusable[focusable.length - 1];
// Remove old handler if exists
if (this.focusHandlers.has(modal)) {
modal.removeEventListener('keydown', this.focusHandlers.get(modal));
}
// move focus from first to last and vice-versa when using tab or shift+tab
const handleKeydown = (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
};
modal.addEventListener('keydown', handleKeydown);
this.focusHandlers.set(modal, handleKeydown);
}
// function to get list of focusable elements in modal
getFocusableElements(container) {
// stringify list of focusable element to pass it to querySelectorAll
const selector = this.focusableElements.join();
return container.querySelectorAll(selector);
}
}