<div class="c-collapsible o-collapsible o-collapsible--raw o-collapsible--raw">
<p class="c-collapsible__title o-collapsible__title js-collapsible-title" id="molecule-collapsible--default">Element title</p>
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Maxime recusandae eligendi beatae nesciunt sit. Officiis nulla maiores, alias minima, dolorum harum et earum molestias odio architecto tempore est consequuntur ullam.</p>
</div>
<div class="c-collapsible o-collapsible o-collapsible--raw {{ modifier }}">
{{#if tag }}
<{{tag}} class="c-collapsible__title o-collapsible__title js-collapsible-title" id="{{ id }}">{{ title }}</{{tag}}>
{{else}}
<p class="c-collapsible__title o-collapsible__title js-collapsible-title" id="{{ id }}">{{ title }}</p>
{{/if}}
{{#> @partial-block }}
<p>{{ text }}</p>
{{/ @partial-block }}
</div>
{
"name": "default",
"title": "Element title",
"text": "Lorem ipsum dolor sit, amet consectetur adipisicing elit. Maxime recusandae eligendi beatae nesciunt sit. Officiis nulla maiores, alias minima, dolorum harum et earum molestias odio architecto tempore est consequuntur ullam.",
"id": "molecule-collapsible--default",
"modifier": "o-collapsible--raw"
}
/*------------------------------------*\
Simple
\*------------------------------------*/
.c-collapsible--simple {
background-color: secondary(soft, 100);
border-radius: remify(16px);
margin-bottom: remify(24px);
border: remify(1px) solid primary(night, 10);
.c-collapsible__title {
color: primary(night, 100);
@include font-scale(level-2, regular);
cursor: pointer;
button {
display: flex;
padding: remify(12px) remify(24px);
}
button span.h2 {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
color: currentColor;
}
}
h3 {
.c-canvas__paper & {
font-size: 115%;
font-weight: fw(semibold);
}
}
h4 {
@include font-scale(level-3, semibold);
}
}
.c-collapsible--simple:hover,
.c-collapsible--simple:has([aria-expanded="true"]) {
.c-collapsible__title {
color: primary(sky, 120);
}
}
/*------------------------------------*\
Button
\*------------------------------------*/
.c-collapsible--btn {
border-bottom: none;
.c-form__alone--createpsw & {
flex-grow: 1;
}
.c-collapsible__title {
// Hack for Safari (web and mobile)
// See also in: 'src/views/01-atoms/ctas/atom-button/_button.scss'
// @supports (-webkit-appearance:none) {
// color: #fff;
// }
.c-form--sticker & {
margin-bottom: 0;
}
}
[aria-expanded="false"],
[aria-expanded="true"] {
&:after {
content: "\25be";
display: inline-block;
margin-left: remify(4px);
// transition: transform .3s ease;
}
}
[aria-expanded="true"] {
margin-bottom: remify(24px);
&:after {
transform: rotate(-180deg);
}
}
.c-collapsible__title button {
color: primary(sky, 120);
text-align: right;
display: block;
width: auto;
@extend .c-button;
@extend .c-button--ghost;
padding-left: remify(16px);
padding-right: remify(16px);
svg.arrow-up,
svg.arrow-down {
@extend .u-visuallyhidden;
}
.c-form__alone--createpsw & {
margin-top: 0;
margin-right: remify(24px);
}
}
}
/*------------------------------------*\
Password
\*------------------------------------*/
.c-collapsible--psw {
[aria-expanded="false"],
[aria-expanded="true"] {
&:after {
content: "\25be";
display: inline-block;
transition: transform .3s ease;
}
}
[aria-expanded="true"] {
margin-bottom: remify(24px);
&:after {
transform: rotate(-180deg);
}
}
}
/*------------------------------------*\
Invoice
\*------------------------------------*/
.c-collapsible--invoice {
.alert-msg {
font-size: 75%;
line-height: 1.5;
text-align: center;
position: relative;
top: remify(40px);
@include min-screen (bp(tablet)) {
width: 70%;
margin: 0 auto;
}
}
}
/*------------------------------------*\
Baloon
\*------------------------------------*/
.c-collapsible__content--baloon {
@include shadow(medium);
padding: remify(16px);
border-radius: remify(4px);
position: relative;
background-color: #F4F6F7;
&:before{
content: "";
position: absolute;
@include css-triangle("up", 10px, #F4F6F7);
top: remify(-20px);
left: 50%;
transform: translateX(-50%);
@include shadow(medium);
}
@include min-screen (bp(tablet)) {
padding: remify(24px);
}
}
/*------------------------------------*\
Faq
\*------------------------------------*/
.c-collapsible--faq {
// .c-collapsible__title button {
// border-radius: remify(8px);
// @include min-screen (bp(tablet)) {
// padding: remify(20px) remify(16px);
// }
// }
// .c-collapsible__title {
// font-size: 100%;
// @include min-screen (bp(tablet)) {
// font-size: 125%;
// }
// }
}
/*------------------------------------*\
Privacy
\*------------------------------------*/
.c-collapsible--privacy {
margin: remify(16px) 0;
// .c-collapsible__title {
// button {
// padding: remify(8px) remify(8px);
// }
// }
}
/*------------------------------------*\
Docs
\*------------------------------------*/
.c-collapsible__content {
.c-media {
margin-bottom: remify(16px);
}
}
// ES5
'use strict';
(function () {
var headings = document.querySelectorAll('.js-collapsible-title');
function isHTML(str) {
var a = document.createElement('div');
a.innerHTML = str;
for (var c = a.childNodes, i = c.length; i--;) {
if (c[i].nodeType === 1) return true;
}
return false;
}
Array.prototype.forEach.call(headings, function (heading) {
var headingcontent = heading.innerHTML;
// Se non c'è già un button nel titolo, iniettalo (vincolo: button solo via JS)
var alreadyButton = heading.querySelector('button.c-collapsible__button');
if (!(alreadyButton || (isHTML(headingcontent) && (window.jQuery && jQuery(headingcontent).is('button'))))) {
var triggerId = (heading.id ? heading.id + '-trigger' : 'collapsible-trigger-' + Math.random().toString(36).slice(2));
var panelId = (heading.id ? heading.id + '-panel' : 'collapsible-panel-' + Math.random().toString(36).slice(2));
heading.innerHTML =
'<button class="c-collapsible__button" type="button"' +
' id="' + triggerId + '"' +
' aria-expanded="false"' +
' aria-controls="' + panelId + '"' +
' data-opens-text="apri" data-closes-text="chiudi">' +
headingcontent +
'<svg class="arrow-down" viewBox="0 0 24 24" aria-hidden="true"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"></path></svg>' +
'<svg class="arrow-up" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"></path></svg>' +
'</button>';
}
// Raccoglie i nodi tra questo titolo e il prossimo titolo .js-collapsible-title
var getContent = function (elem) {
var elems = [];
while (elem.nextElementSibling && !elem.nextElementSibling.classList.contains('js-collapsible-title')) {
elems.push(elem.nextElementSibling);
elem = elem.nextElementSibling;
}
elems.forEach(function (node) {
if (node.parentNode) node.parentNode.removeChild(node);
});
return elems;
};
var contents = getContent(heading);
// Crea o individua il pannello
var wrapper = document.createElement('div');
var ensuredPanelId = (heading.id ? heading.id + '-panel' : 'collapsible-panel-' + Math.random().toString(36).slice(2));
wrapper.id = ensuredPanelId;
wrapper.classList.add('o-collapsible__content');
wrapper.setAttribute('role', 'region');
wrapper.hidden = true;
contents.forEach(function (node) { wrapper.appendChild(node); });
heading.parentNode.insertBefore(wrapper, heading.nextElementSibling);
// Button ↔ Panel: id/aria-controls + aria-labelledby
var btn = heading.querySelector('button.c-collapsible__button');
if (btn) {
// Assicura un id al button (se mancasse) e collega aria-controls al pannello
if (!btn.id) {
btn.id = (heading.id ? heading.id + '-trigger' : 'collapsible-trigger-' + Math.random().toString(36).slice(2));
}
btn.setAttribute('aria-controls', ensuredPanelId);
// 🔴 CHANGE PRINCIPALE: il pannello è etichettato DAL BUTTON, non dal titolo
wrapper.setAttribute('aria-labelledby', btn.id);
btn.onclick = function () {
var expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', (!expanded).toString());
wrapper.hidden = expanded;
};
}
});
// Apertura automatica se l’URL contiene l’ID del titolo (comportamento esistente)
if (window.jQuery) {
var $collapsible = jQuery('.o-collapsible');
$collapsible.each(function () {
var $this = jQuery(this);
var $title = $this.find('.js-collapsible-title');
var titleId = $title.attr('id') || '';
var href = (jQuery(location).attr('href') || '');
var $btn = $this.find('.c-collapsible__button');
var $content = $this.find('.o-collapsible__content');
if (titleId && typeof href.includes === 'function' && href.includes(titleId)) {
$btn.attr('aria-expanded', 'true');
$content.removeAttr('hidden');
jQuery('html, body').animate({
scrollTop: $this.offset().top - 100
}, 2000);
}
});
}
})();
You can copy and paste the code of this component wherever you want instead importing.