Please refer to the Bootstrap doc for collapse elements for implementation
Implementation:Every timeline item is delimited by a white background. Its "trigger element" is a "section title" component, which toggles the "section item" content right below it.
If a timeline item should be open when arriving on the page, add the show class to the js-timeline__itemCollapse element, and set the "aria-expanded" attribute of the sds-sectionTitle__toggle element to true.
If there's no collapsible content present, you can get rid of the js-timeline__itemCollapse element, as well as of the sds-sectionTitle__toggleWrapper element.
Remember to correctly set the IDs on each js-timeline__itemCollapse and matching data-targets on sds-sectionTitle__toggle.
Items inside the collapse can have a detail element, sds-sectionItem__collapse, which is triggered by the js-sectionItem__toggle element. Every sds-sectionItem__collapse has a data-parent attribute that references the timeline's id.
If no detail is present for the section item, you can remove js-sectionItem__toggle as well as the sds-sectionItem__collapse elements.
<div id="timelineAccordion" class="sds-timeline">
<a href="" class="sds-box sds-timeline__item">
<div class="d-flex align-items-center justify-content-between">
<div class="sds-sectionTitle -isTimelineItem">
<div class="sds-sectionTitle__inner">
<div class="sds-sectionTitle__col">
<div class="sds-sectionTitle__textMain">
Mouvements futurs
</div>
</div>
</div>
</div>
<span class="sds-iconCircle -ghost" aria-hidden="true">
<span class="sds-icon sds-icon-chevronright"></span>
</span>
</div>
</a>
<div class="sds-emptyState sds-box -insetLg sds-timeline__item h-100">
<span class="sds-emptyState__icon sds-icon sds-icon-list-l"></span>
<div class="sds-stackXxs">
<p class="sds-emptyState__text sds-textSemiBold sds-textBodyLg">{Title}</p>
<p class="sds-emptyState__text sds-textSemiBold">{Subtitle}</p>
</div>
</div>
</div>
{% extends "@snet-timeline-frame" %}
{% block timelineContent %}
<a href="" class="{{ namespace }}box {{ namespace }}timeline__item">
<div class="d-flex align-items-center justify-content-between">
{% render "@snet-section-title",{text: "Mouvements futurs"} ,true %}
{% render "@icon-circle-regular--ghost",{
icon: "icon-chevronright"
},true %}
</div>
</a>
{% render '@snet-empty-state--no-result',{
icon: "icon-list-l",
text: "{Title}",
subText: "{Subtitle}",
textBodyLg: true,
classes: [namespace + "timeline__item","h-100"]
}, true %}
{% endblock %}
export default class Timeline {
constructor() {
this.hideTrigger()
}
hideTrigger () {
$(".sds-timeline__item .js-timeline__itemCollapse").each(function( index, element ) {
$(element).on("hide.bs.collapse", function (e) {
console.log("hide in")
$(e.target).find(".sds-sectionItem__collapse.show").collapse("hide");
});
})
$(".sds-timeline__collapseInner .collapse, .sds-timeline__item .js-timeline__itemCollapse").each(function( index, element ) {
$(element).on("show.bs.collapse", function (e) {
console.log("show in")
$(e.target).closest(".sds-sectionItem").addClass("-detailShown");
});
$(element).on("hide.bs.collapse", function (e) {
console.log("hide 2 in")
$(e.target).closest(".sds-sectionItem").removeClass("-detailShown");
});
})
}
}
@use "sass:math";
/* variables specific to current element */
$timeline-item-horiz-padding: $timeline-item-horiz-padding-global;
$timeline-item-vert-padding: $timeline-item-vert-padding-global;
$timeline-item-content-negative-margin: $timeline-item-content-negative-margin-global;
.#{$namespace}timeline {
/* Save root element context for easy access if nesting is needed */
$self: &;
/* properties of current element + media queries */
@include spacer-component-stack("md");
/* 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 */
// timeline__item
&__item {
// follows same logic as parent
@include spacer-component-inset-horiz-greater("md", "lg");
position: relative;
z-index: z("zero");
display: block;
&::before {
content: "";
width: $border-width*2;
position: absolute;
z-index: z("low");
bottom: 100%;
height: $timeline-item-vert-padding*3;
left: $timeline-item-horiz-padding + $section-item-col-date-width-global + $section-item-horiz-margin-global + math.div($section-item-col-dot-width-global, 2);
transform: translateX(-50%) translateY($timeline-item-vert-padding);
background-color: map-deep-get($token-color-brand-map, "secondary", "30");
}
&:first-child {
&::before {
height: $timeline-item-vert-padding;
left: $timeline-item-horiz-padding + $section-item-col-date-width-global + $section-item-horiz-margin-global + math.div($section-item-col-dot-width-global, 2);
}
}
&:not(:last-child) {
.#{$namespace}sectionItem.-isTimelineItem:last-child:only-child {
.#{$namespace}sectionItem__inner {
.#{$namespace}sectionItem__innerCol {
&.-dot {
&::before {
bottom: -($timeline-item-vert-padding) !important;
}
}
}
}
}
}
&:last-child {
.#{$namespace}sectionTitle {
&::before {opacity: 0;}
}
.#{$namespace}sectionItem.-isTimelineItem:last-child {
.#{$namespace}sectionItem__inner {
.#{$namespace}sectionItem__innerCol {
&.-dot {
//&::before {bottom: 50%;}
&::after {height: 0;}
}
}
}
}
#{$self}__collapseInner {
position: relative;
&::before {
content: "";
width: $border-width*2;
position: absolute;
z-index: z("low");
bottom: 100%;
height: $timeline-item-vert-padding;
left: $section-item-col-date-width-global + $section-item-horiz-margin-global + math.div($section-item-col-dot-width-global, 2);
transform: translateX(-50%) translateY($timeline-item-vert-padding);
background-color: map-deep-get($token-color-brand-map, "secondary", "30");
}
}
&.-empty {
&::before {
transform: translateX(-50%) translateY(0);
height: $timeline-item-vert-padding*2;
}
}
}
.#{$namespace}sectionTitle.-isTimelineItem,
.#{$namespace}sectionItem.-isTimelineItem {
margin-left: -($timeline-item-content-negative-margin);
margin-right: -($timeline-item-content-negative-margin);
}
.#{$namespace}sectionTitle.-isTimelineItem {
padding-left: map-deep-get($token-spacer-unit-map, "8");
padding-right: map-deep-get($token-spacer-unit-map, "8");
}
}
&__collapseInner {
padding-top: $timeline-item-vert-padding;
}
/* modifiers */
// timeline -firstItemNoLine
&.-firstItemNoLine {
// follows same logic as base element
#{$self}__item:first-of-type {
&::before {
content: none;
}
}
}
&.-hasEmptyItems {
display: flex;
flex-direction: column;
height: 100%;
}
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}