If content is to be aligned to the right, it has to be included in the "panelHeader__alignEnd" part of the component.
Include the headroom.min.js
JS in the libs
folder.
Add "-headroom to the panel header element. Nothing more is needed.
If a sidebar with the class "sds-stickSidebar" is present, it will respond to the panel header's scroll position.
You can use the javascript found in the assets panel to get an idea of how the plugin works.
You can find any and all information relating to it here
A usage example can be found in snet/pages/mouvements-cartes
<div class="sds-panelHeader">
<div class="sds-panelHeader__actionGroup">
<nav class="sds-linkTabs">
<ul class="sds-linkTabs__inner nav nav-tabs">
<li class="nav-item">
<a class="nav-link" href="">Ordres permanents</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="">Domiciliations</a>
</li>
</ul>
</nav>
</div>
<div class="sds-panelHeader__alignEnd">
<div class="sds-panelHeader__actionGroup">
<div class="dropdown">
<button type="button" class="sds-btn -iconBtn -btnSecondary" data-toggle="dropdown" aria-expanded="false" data-display="static">
<span class="sds-icon sds-icon-filter"></span>
</button>
<div aria-labelledby="" class="sds-actionMenu dropdown-menu dropdown-menu-right">
<div class="dropdown-item">
<div class="sds-checkbox custom-control custom-checkbox">
<input value="checkbox-value" type="checkbox" name="" class="sr-only custom-control-input " id="action-menu-checkbox-0-base"><span class="sds-checkboxDot sds-checkbox__shape" aria-hidden="true"></span>
<label class="custom-control-label" for="action-menu-checkbox-0-base">Tout</label>
<div class="sds-checkbox__error invalid-feedback">Error message</div>
</div>
</div>
<div class="dropdown-item">
<div class="sds-checkbox custom-control custom-checkbox">
<input value="checkbox-value" type="checkbox" name="" class="sr-only custom-control-input " id="action-menu-checkbox-1-base"><span class="sds-checkboxDot sds-checkbox__shape" aria-hidden="true"></span>
<label class="custom-control-label" for="action-menu-checkbox-1-base">Actif</label>
<div class="sds-checkbox__error invalid-feedback">Error message</div>
</div>
</div>
<div class="dropdown-item">
<div class="sds-checkbox custom-control custom-checkbox">
<input value="checkbox-value" type="checkbox" name="" class="sr-only custom-control-input " id="action-menu-checkbox-2-base"><span class="sds-checkboxDot sds-checkbox__shape" aria-hidden="true"></span>
<label class="custom-control-label" for="action-menu-checkbox-2-base">À valider</label>
<div class="sds-checkbox__error invalid-feedback">Error message</div>
</div>
</div>
<div class="dropdown-item">
<div class="sds-checkbox custom-control custom-checkbox">
<input value="checkbox-value" type="checkbox" name="" class="sr-only custom-control-input " id="action-menu-checkbox-3-base"><span class="sds-checkboxDot sds-checkbox__shape" aria-hidden="true"></span>
<label class="custom-control-label" for="action-menu-checkbox-3-base">Bloqué</label>
<div class="sds-checkbox__error invalid-feedback">Error message</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% extends "@snet-panel-header-frame" %}
{% block contentStart %}
<div class="{{ namespace }}panelHeader__actionGroup">
{% render "@snet-link-tabs",linkTabsOptions,true %}
</div>
{% endblock %}
{% block contentEnd %}
<div class="{{ namespace }}panelHeader__actionGroup">
<div class="dropdown">
{% render '@icon-btn-secondary',{
icon: "icon-filter",
attrs: {
"data-toggle": "dropdown",
"aria-expanded": "false",
"data-display": "static"
}
}, true %}
{% render "@snet-action-menu--checkboxes",{
classes: ["dropdown-menu-right"],
checkboxes: checkboxesMenu}
,true %}
</div>
</div>
{% endblock %}
export default class PanelHeader {
constructor() {
this.fireHeadroom()
}
fireHeadroom () {
let stickyHeader = document.querySelector(".-headroom");
if (CSS && CSS.supports && CSS.supports("position", "sticky")) {
if(stickyHeader) {
let options = {
// vertical offset in px before element is first unpinned
offset : document.querySelector('.sds-navTopbar').clientHeight + document.querySelector('.-headroom').clientHeight,
// or you can specify offset individually for up/down scroll
// scroll tolerance in px before state changes
tolerance : 0,
// or you can specify tolerance individually for up/down scroll
// css classes to apply
classes : {
// when element is initialised
initial : "-headroom",
// when scrolling up
pinned : "-headroomPinned",
// when scrolling down
unpinned : "-headroomUnpinned",
// when above offset
top : "-headroomTop",
// when below offset
notTop : "-headroomNotTop",
// when at bottom of scroll area
bottom : "-headroomBottom",
// when not at bottom of scroll area
notBottom : "-headroomNotBottom",
// when frozen method has been called
frozen: "-headroomFrozen"
},
// callback when pinned, `this` is headroom object
onPin : function() {
$('.sds-stickySidebar').css("top", document.querySelector(".sds-navTopbar").clientHeight + document.querySelector('.-headroom').clientHeight + 8);
$('.sds-reactsToPanelHeader')?.css("top", document.querySelector(".sds-navTopbar").clientHeight + document.querySelector('.-headroom').clientHeight);
},
// callback when unpinned, `this` is headroom object
onUnpin : function() {
$('.sds-stickySidebar').css("top", (document.querySelector(".sds-navTopbar").clientHeight) + 8)
$('.sds-reactsToPanelHeader')?.css("top", (document.querySelector(".sds-navTopbar").clientHeight))
},
// callback when above offset, `this` is headroom object
onTop : function() {
$('.sds-stickySidebar').css("top", document.querySelector(".sds-navTopbar").clientHeight + document.querySelector('.-headroom').clientHeight)
},
// callback when below offset, `this` is headroom object
onNotTop : function() {},
// callback when at bottom of page, `this` is headroom object
onBottom : function() {},
// callback when moving away from bottom of page, `this` is headroom object
onNotBottom : function() {}
};
let headroom = new Headroom(stickyHeader, options);
headroom.init();
}
} else {
console.log("no position: sticky; support");
}
}
}
@use "sass:math";
/* variables specific to current element */
$panel-header-padding-bottom: map-deep-get($token-spacer-inset-map, "sm");
.#{$namespace}panelHeader {
/* Save root element context for easy access if nesting is needed */
$self: &;
/* properties of current element + media queries */
min-height: map-deep-get($token-sizes-component-map, "panel-header-height");
display: flex;
align-items: flex-start;
flex-wrap: wrap;
@include spacer-component-inline("xl");
padding-top: map-deep-get($token-spacer-inset-map, "md");
padding-bottom: $panel-header-padding-bottom;
@include media-breakpoint-up(md){
padding-top: map-deep-get($token-spacer-inset-map, "lg");
}
/* 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 */
&__container {
margin: 0 auto !important;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
}
// panelHeader__back
&__back {
// follows same logic as parent
margin-right: map-deep-get($token-spacer-unit-map, "32");
flex-grow: 0;
}
&__alignEnd {
@include spacer-component-inline("xl");
display: flex;
align-items: center;
justify-content: flex-end;
margin-left: auto;
margin-bottom: map-deep-get($token-spacer-stack-max-map, "sm");
order: -1;
width: 100%;
@include media-breakpoint-up(lg){
order: 1;
width: auto;
margin-bottom: 0;
}
}
&__actionGroup {
@include spacer-component-inline("sm");
display: flex;
align-items: center;
min-height: 40px;
&.-alignEnd {
margin-left: auto;
}
&.-big {
margin-top: -(map-deep-get($token-spacer-unit-map, "12"));
}
&.-medium {
margin-top: -(map-deep-get($token-spacer-unit-map, "8"));
}
&.-timelineStart {
position: relative;
z-index: z("low");
margin-left: map-deep-get($design-tokens,"comp-icon-button-large-width") + map-deep-get($token-spacer-inline-map, "sm") + math.div(map-deep-get($token-spacer-inline-map, "sm"), 2);
align-self: stretch;
align-items: flex-start;
&::before {
content: "";
position: absolute;
z-index: z("negative");
top: 50%;
left: 50%;
transform: translateX(-50%);
bottom: -($panel-header-padding-bottom);
width: $border-width*2;
background-color: map-deep-get($token-color-brand-map, "secondary", "30");
}
}
}
.sds-searchGrowing {
}
//&__dropdownMenuFilters {
//
// top: map-deep-get($token-spacer-unit-map, "8") !important;
// left: -(map-deep-get($token-spacer-unit-map, "24")) !important;
//
//}
/* modifiers */
// panelHeader -altStyle
/* random parent element */
/*
*
* Syntax : .randomParentElt & {}
*
*/
/* Pseudo Classes */
&:hover {
@media (hover: hover) {
}
}
&:focus {
}
&:active {
}
&:focus,
&:active {
}
}