diff --git a/claro.libraries.yml b/claro.libraries.yml index b5d7c39..fedaf70 100644 --- a/claro.libraries.yml +++ b/claro.libraries.yml @@ -224,8 +224,15 @@ vertical-tabs: drupalSettings: verticalTabs: paneClasses: [] - # - vertical-tabs__pane + paneClassesFirst: + - vertical-tabs__item--first + paneClassesLast: + - vertical-tabs__item--last + paneClassesHidden: + - vertical-tab--hidden paneWrapperClasses: - vertical-tabs__items--processed + menuItemClassesHidden: + - vertical-tabs__menu-item--hidden dependencies: - claro/global-styling diff --git a/css/src/base/variables.css b/css/src/base/variables.css index f1c7206..36014e9 100644 --- a/css/src/base/variables.css +++ b/css/src/base/variables.css @@ -10,8 +10,8 @@ --color-whitesmoke-light: #fafbfd; --color-whitesmoke-o-40: rgba(243, 244, 249, 0.4); /* Secondary. */ - --color-lightgray: #d8d9e0; - --color-lightgray-o-80: rgba(216, 217, 224, 0.8); + --color-lightgray: #d4d4d8; + --color-lightgray-o-80: rgba(212, 212, 218, 0.8); --color-grayblue: #8e929c; --color-oldsilver: #82828c; --color-davysgrey: #545560; diff --git a/css/src/components/details.css b/css/src/components/details.css index 7475d1a..da93603 100644 --- a/css/src/components/details.css +++ b/css/src/components/details.css @@ -32,6 +32,8 @@ :root { --size-summary-border-radius: calc(var(--details-border-size-radius) - var(--details-border-size)); --size-summary-focus-border: 3px; + --summary-accordion-padding-vertical: calc(var(--space-l) + ((var(--space-m) - var(--space-l)) / 2)); + --summary-accordion-line-height: var(--space-l); } .claro-details { @@ -89,7 +91,8 @@ .claro-details__summary--accordion, .claro-details__summary--accordion-item, .claro-details__summary--vertical-tabs-item { - padding: var(--space-l) var(--space-l) var(--space-l) var(--details-desktop-wrapper-padding-start); /* LTR */ + padding: var(--summary-accordion-padding-vertical) var(--space-l) var(--summary-accordion-padding-vertical) var(--details-desktop-wrapper-padding-start); /* LTR */ + line-height: var(--summary-accordion-line-height); background: var(--color-white); } [dir="rtl"] .claro-details__summary--accordion, @@ -170,7 +173,7 @@ } /** - * Safari (at least version 12.1) cannot handle our details marker + * [1] Safari (at least version 12.1) cannot handle our details marker * transition properly. * * Every additional pointer triggered toggle event freezes the transition, @@ -211,16 +214,21 @@ pointer-events: none; } -.claro-details > .claro-details__summary--accordion-item::after { +.claro-details > .claro-details__summary--accordion-item::after, +.vertical-tabs__item > .claro-details__summary--vertical-tabs-item::after { border-radius: 0; } -.claro-details:first-child > .claro-details__summary--accordion-item::after { - border-radius: var(--details-border-size-radius) var(--details-border-size-radius) 0 0; +.claro-details:first-child > .claro-details__summary--accordion-item::after, +.vertical-tabs__item--first > .claro-details__summary--vertical-tabs-item::after { + border-top-right-radius: var(--details-border-size-radius); + border-top-left-radius: var(--details-border-size-radius); } -.claro-details:last-child > .claro-details__summary--accordion-item::after { - border-radius: 0 0 var(--details-border-size-radius) var(--details-border-size-radius); +.claro-details:last-child > .claro-details__summary--accordion-item::after, +.vertical-tabs__item--last > .claro-details__summary--vertical-tabs-item::after { + border-bottom-right-radius: var(--details-border-size-radius); + border-bottom-left-radius: var(--details-border-size-radius); } /** @@ -228,7 +236,8 @@ * radius if their accordion is expanded. */ .claro-details[open] > .claro-details__summary--accordion::after, -.claro-details[open] > .claro-details__summary--accordion-item::after { +.claro-details[open] > .claro-details__summary--accordion-item::after, +.vertical-tabs__item--last[open] > .claro-details__summary--vertical-tabs-item::after { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } @@ -241,7 +250,8 @@ } [open] .claro-details__summary--accordion, -[open] .claro-details__summary--accordion-item { +[open] .claro-details__summary--accordion-item, +[open] .claro-details__summary--vertical-tabs-item { color: var(--color-absolutezero); } @@ -249,7 +259,8 @@ .claro-details__summary:hover:focus::before, .claro-details[open] > .claro-details__summary:focus::before, .claro-details[open] > .claro-details__summary--accordion::before, -.claro-details[open] > .claro-details__summary--accordion-item::before { +.claro-details[open] > .claro-details__summary--accordion-item::before, +.claro-details[open] > .claro-details__summary--vertical-tabs-item::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M5.2109375,1.3144531 3.7890625,2.7226562 9.0917969,8.0761719 3.7890625,13.429688 5.2109375,14.837891 11.908203,8.0761719Z' fill='%230036B1'/%3E%3C/svg%3E"); } @@ -277,7 +288,8 @@ } .claro-details[open] > .claro-details__summary--accordion, -.claro-details[open] > .claro-details__summary--accordion-item { +.claro-details[open] > .claro-details__summary--accordion-item, +.claro-details[open] > .claro-details__summary--vertical-tabs-item { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } @@ -326,8 +338,7 @@ /* stylelint-disable-next-line unit-whitelist */ @media not all and (min-resolution: 0.001dpcm) { @media { - .claro-details__summary:focus::after, - .claro-details__summary:active::after { + .claro-details__summary::after { transition: none; } } @@ -420,11 +431,13 @@ } .collapse-processed > .claro-details__summary--accordion .details-title, -.collapse-processed > .claro-details__summary--accordion-item .details-title { - padding: var(--space-l) var(--space-l) var(--space-l) var(--details-desktop-wrapper-padding-start); /* LTR */ +.collapse-processed > .claro-details__summary--accordion-item .details-title, +.collapse-processed > .claro-details__summary--vertical-tabs-item .details-title { + padding: var(--summary-accordion-padding-vertical) var(--space-l) var(--summary-accordion-padding-vertical) var(--details-desktop-wrapper-padding-start); /* LTR */ } [dir="rtl"] .collapse-processed > .claro-details__summary--accordion .details-title, -[dir="rtl"] .collapse-processed > .claro-details__summary--accordion-item .details-title { +[dir="rtl"] .collapse-processed > .claro-details__summary--accordion-item .details-title, +[dir="rtl"] .collapse-processed > .claro-details__summary--vertical-tabs-item .details-title { padding-right: var(--details-desktop-wrapper-padding-start); padding-left: var(--space-l); } @@ -458,22 +471,26 @@ /* Accordion item modifiers for the focus box. */ -.collapse-processed > .claro-details__summary--accordion-item .details-title::after { +.collapse-processed > .claro-details__summary--accordion-item .details-title::after, +.vertical-tabs__item > .claro-details__summary--vertical-tabs-item .details-title::after { border-radius: 0; } -.collapse-processed:first-child > .claro-details__summary--accordion-item .details-title::after { +.collapse-processed:first-child > .claro-details__summary--accordion-item .details-title::after, +.vertical-tabs__item--first > .claro-details__summary--vertical-tabs-item .details-title::after { border-top-right-radius: var(--details-border-size-radius); border-top-left-radius: var(--details-border-size-radius); } -.collapse-processed:last-child > .claro-details__summary--accordion-item .details-title::after { +.collapse-processed:last-child > .claro-details__summary--accordion-item .details-title::after, +.vertical-tabs__item--last > .claro-details__summary--vertical-tabs-item .details-title::after { border-bottom-right-radius: var(--details-border-size-radius); border-bottom-left-radius: var(--details-border-size-radius); } .collapse-processed[open] > .claro-details__summary--accordion .details-title::after, -.collapse-processed[open] > .claro-details__summary--accordion-item .details-title::after { +.collapse-processed[open] > .claro-details__summary--accordion-item .details-title::after, +.vertical-tabs__item[open] > .claro-details__summary--vertical-tabs-item .details-title::after { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } @@ -486,13 +503,15 @@ * been solved. */ .claro-details__summary--accordion .summary, -.claro-details__summary--accordion-item .summary { +.claro-details__summary--accordion-item .summary, +.claro-details__summary--vertical-tabs-item .summary { display: none; } @media screen and (-ms-high-contrast: active) { .collapse-processed[open] > .claro-details__summary--accordion .details-title:not(:focus)::after, - .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after { + .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after, + .collapse-processed[open] > .claro-details__summary--vertical-tabs-item .details-title:not(:focus)::after { top: -1px; right: -1px; bottom: -1px; diff --git a/css/src/components/form--checkbox-radio--ie.css b/css/src/components/form--checkbox-radio--ie.css index 0efb739..2532528 100644 --- a/css/src/components/form--checkbox-radio--ie.css +++ b/css/src/components/form--checkbox-radio--ie.css @@ -9,7 +9,7 @@ width: 18px; height: 18px; background: var(--input-bg-color) no-repeat 50% 50%; - background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10'xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E"); background-size: 100% 100%; border-radius: 2px; box-shadow: 0 0 0 4px transparent; diff --git a/css/src/components/form--checkbox-radio.css b/css/src/components/form--checkbox-radio.css index e6555a7..599f989 100644 --- a/css/src/components/form--checkbox-radio.css +++ b/css/src/components/form--checkbox-radio.css @@ -65,7 +65,7 @@ width: 18px; height: 18px; background: var(--input-bg-color) no-repeat 50% 50%; - background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10'xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E"); background-size: 100% 100%; border-radius: 2px; box-shadow: 0 0 0 4px transparent; diff --git a/css/src/components/vertical-tabs.css b/css/src/components/vertical-tabs.css index acd4ca1..8a98a4c 100644 --- a/css/src/components/vertical-tabs.css +++ b/css/src/components/vertical-tabs.css @@ -4,14 +4,10 @@ */ :root { - --vtabs-trigger-border: 1px solid rgba(216, 217, 224, 0.8); + --vtabs-trigger-border: 1px solid var(--color-lightgray); --vtabs-invisible-border: 1px solid transparent; --shadow-trigger-active-vertical-tab: 0 2px 4px rgba(0, 0, 0, 0.1); - --vtabs-min-width: 15rem; /* 240px */ - --vtabs-narrow-details-padding: 1.266rem; /* ~20px */ - --vtabs-narrow-details-padding-disclosure: 2.8125rem; /* 45px */ - --vtabs-narrow-summary-line-height: 1.266rem; /* ~20px */ - --vtabs-active-tab-mask-width: 0.625rem; /* 10px */ + --vtabs-max-width: 20em; } .vertical-tabs__items { @@ -25,34 +21,45 @@ box-shadow: var(--details-box-shadow); } -.vertical-tabs { - display: flex; - flex-direction: column; +/** + * Styles for .vertical-tabs are needed only from medium and wide breakpoints. + */ +@media screen and (min-width: 38em) { + .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs, + body:not(.toolbar-tray-open) .vertical-tabs { + display: flex; + align-items: stretch; + flex-direction: row; + } } -@media screen and (min-width: 36em) { +@media screen and (min-width: 60em) { .vertical-tabs { + display: flex; + align-items: stretch; flex-direction: row; } } .vertical-tabs__item { - margin: 0 -1px; + margin: -1px -1px 0; border-radius: 0; } .vertical-tabs__item--first { - margin-top: -1px; border-top-right-radius: var(--details-accordion-border-size-radius); border-top-left-radius: var(--details-accordion-border-size-radius); } -.vertical-tabs__item + .vertical-tabs__item { - margin-top: -1px; +@media screen and (min-width: 38em) { + .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item, + .js body:not(.toolbar-tray-open) .vertical-tabs__item { + margin-top: 0; + } } -@media screen and (min-width: 36em) { - .vertical-tabs__item + .vertical-tabs__item { +@media screen and (min-width: 60em) { + .js .vertical-tabs__item { margin-top: 0; } } @@ -65,18 +72,30 @@ /* Tab menu. */ .vertical-tabs__menu { - list-style: none; - max-width: 40%; - min-width: var(--vtabs-min-width); - line-height: 1; - margin: 0; + position: relative; display: none; + flex: 0 0 40%; + margin: 0; + max-width: 20rem; + padding-top: 0.5rem; + border-top: 1px solid transparent; + line-height: 1; + list-style: none; + color: var(--color-text); + background: var(--color-white); } [dir="rtl"] .vertical-tabs__menu { - margin: 0; /* Overrides default [dir="rtl"] ul margin */ + margin: 0; +} + +@media screen and (min-width: 38em) { + .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__menu, + body:not(.toolbar-tray-open) .vertical-tabs__menu { + display: block; + } } -@media screen and (min-width: 36em) { +@media screen and (min-width: 60em) { .vertical-tabs__menu { display: block; } @@ -84,139 +103,225 @@ /* Tab menu item. */ .vertical-tabs__menu-item { - position: relative; + margin: -1rem -1px -0.5rem -0.5rem; /* LTR */ + padding: 0.5rem 0 0.5rem 0.5rem; /* LTR */ + overflow: hidden; +} +[dir="rtl"] .vertical-tabs__menu-item { + margin-right: -0.5rem; + margin-left: -1px; + padding-right: 0.5rem; + padding-left: 0; } -.vertical-tabs__menu-item + .vertical-tabs__menu-item { +.vertical-tabs__menu-item::after { + display: block; + position: absolute; + width: 100%; + border-top: 1px solid var(--color-white); + margin-top: -1px; + z-index: 2; +} + +.vertical-tabs__menu-item::before { + display: block; + position: absolute; + width: 100%; + border-top: 1px solid var(--color-lightgray); margin-top: -1px; + z-index: 1; +} + +.vertical-tabs__menu-item:not(.vertical-tabs__menu-item--hidden) ~ .vertical-tabs__menu-item::before { + content: ''; +} + +.vertical-tabs__menu-item.is-selected::before, +.vertical-tabs__menu-item:not(.vertical-tabs__menu-item--hidden) ~ .vertical-tabs__menu-item.is-selected::before { + content: none; +} + +/* Tab menu item selected. */ + +.vertical-tabs__menu-item.is-selected::after { + content: ''; +} + +.vertical-tabs__menu-item:focus { + outline: 0; + box-shadow: none; } /* Tab menu item anchor. */ -.vertical-tabs__menu-item a { +.vertical-tabs__menu-link { + position: relative; display: block; - padding: var(--space-s) var(--space-l); - line-height: var(--line-height); - border-top: var(--vtabs-trigger-border); - border-bottom: var(--vtabs-trigger-border); + padding: var(--space-s) var(--space-s) var(--space-s) calc(var(--space-l) - 4px); /* LTR */ + line-height: var(--line-height); /* ?? */ text-decoration: none; + border: 1px solid transparent; + margin-top: -1px; + border-width: 1px 0 1px 4px; /* LTR */ + border-radius: 2px 0 0 2px; /* LTR */ color: var(--color-text); - margin-left: 1px; /* LTR */ } -[dir="rtl"] .vertical-tabs__menu-item a { - margin-left: 0; - margin-right: 1px; +[dir="rtl"] .vertical-tabs__menu-link { + padding-right: calc(var(--space-l) - 4px); + padding-left: var(--space-s); + border-width: 1px 4px 1px 0; + border-radius: 0 2px 2px 0; } -.vertical-tabs__menu-item a:hover { + +.vertical-tabs__menu-link:hover { color: var(--color-absolutezero); background-color: var(--color-bgblue-hover); -} -.vertical-tabs__menu-item.first a { - border-top: var(--vtabs-invisible-border); -} -.vertical-tabs__menu-item.last a { - border-bottom: var(--vtabs-invisible-border); + text-decoration: none; } .vertical-tabs__menu-item-summary, -.vertical-tabs__summary-summary { +.vertical-tabs__details-summary-summary { display: block; font-size: var(--font-size-s); color: var(--color-davysgrey); font-weight: normal; } -/* Tab menu item selected. */ -.vertical-tabs__menu-item.is-selected { - box-shadow: var(--shadow-trigger-active-vertical-tab); +.vertical-tabs__menu-link:focus { + text-decoration: none; + box-shadow: none; + z-index: 4; } -.vertical-tabs__menu-item.is-selected a { +.vertical-tabs__menu-link:focus::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: -6px -9px; + border: 3px solid var(--color-focus); + border-radius: 2px; +} + +.is-selected .vertical-tabs__menu-link { color: var(--color-absolutezero); - background-color: white; + background-color: var(--color-white); + border-color: var(--color-lightgray) transparent; + box-shadow: var(--shadow-trigger-active-vertical-tab); + z-index: 3; } -[dir=rtl] .vertical-tabs__menu-item.is-selected a { +[dir=rtl] .is-selected .vertical-tabs__menu-link { border-radius: 0 var(--tabs-base-border) var(--base-border-radius) 0; } -.vertical-tabs__menu-item.is-selected a:hover { +.is-selected .vertical-tabs__menu-link:hover { background-color: var(--color-bgblue-hover); color: var(--color-absolutezero-hover); } -.vertical-tabs__menu-item.is-selected a::before { +.is-selected .vertical-tabs__menu-link::before { content: ''; position: absolute; - top: 0; - left: 0; /* LTR */ - bottom: 0; - height: 100%; + top: -1px; + right: 100%; /* LTR */ + bottom: -1px; border-left: 4px solid var(--color-absolutezero); /* LTR */ border-radius: var(--base-border-radius) 0 0 var(--base-border-radius); /* LTR */ } -[dir=rtl] .vertical-tabs__menu-item.is-selected a::before { - left: 0; - right: 0; - border-left: none; +[dir=rtl] .is-selected .vertical-tabs__menu-link::before { + right: auto; + left: 100%; + border-left: 0; border-right: 4px solid var(--color-absolutezero); border-radius: 0 var(--base-border-radius) var(--base-border-radius) 0; } -.vertical-tabs__menu-item.is-selected::after { - content: ''; - z-index: 100; - position: absolute; - top: 1px; - right: -8px; /* LTR */ - bottom: 1px; - border-right: var(--vtabs-active-tab-mask-width) solid var(--color-white); /* LTR */ -} -[dir=rtl] .vertical-tabs__menu-item.is-selected a::after { - right: 0; - left: -8px; - border-right: none; - border-left: var(--vtabs-active-tab-mask-width) solid var(--color-white); -} +@media screen and (-ms-high-contrast: active) { + .vertical-tabs__menu { + border-color: transparent; + } -.vertical-tabs__menu-item.is-selected.first a { - border-top: var(--vtabs-trigger-border); -} + .vertical-tabs__menu-link { + border-color: transparent; + } + + .is-selected .vertical-tabs__menu-link { + border-color: windowText transparent; + } + + .vertical-tabs__menu-link:focus::after { + border-color: transparent; + } -.vertical-tabs__menu-item.is-selected.last a { - border-bottom: var(--vtabs-trigger-border); + .is-selected .vertical-tabs__menu-link::before { + border-color: windowText; + } } -/* Tab panes. */ +/** + * Tab panes. + */ .vertical-tabs__items--processed { border: var(--vtabs-trigger-border); - border-radius: 0 var(--base-border-radius) var(--base-border-radius) var(--base-border-radius); /* LTR */ background-color: var(--color-white); box-shadow: var(--shadow-trigger-active-vertical-tab); - flex-grow: 1; + flex: 1 0 60%; z-index: 1; margin-top: 0; margin-bottom: 0; } -[dir="rtl"] .vertical-tabs__items--processed { - border-radius: var(--base-border-radius) 0 var(--base-border-radius) var(--base-border-radius); -} -@media screen and (min-width: 36em) { - .vertical-tabs__item { +@media screen and (min-width: 38em) { + .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item, + .js body:not(.toolbar-tray-open) .vertical-tabs__item { border: 0; margin: 0; } - .vertical-tabs__item.is-collapsed { + .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item > summary, + .js body:not(.toolbar-tray-open) .vertical-tabs__item > summary { display: none; } - .vertical-tabs__item > summary { + .js .toolbar-tray-open:not(.toolbar-vertical) .claro-details__wrapper--vertical-tabs-item, + .js body:not(.toolbar-tray-open) .claro-details__wrapper--vertical-tabs-item { + border-top: 0; + background-color: transparent; + } + + .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__items--processed, + .js body:not(.toolbar-tray-open) .vertical-tabs__items--processed { + border-radius: 0 var(--base-border-radius) var(--base-border-radius) var(--base-border-radius); /* LTR */ + } + + .js[dir="rtl"] .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__items--processed, + .js[dir="rtl"] body:not(.toolbar-tray-open) .vertical-tabs__items--processed { + border-radius: var(--base-border-radius) 0 var(--base-border-radius) var(--base-border-radius); + } +} + +@media screen and (min-width: 60em) { + .js .vertical-tabs__item { + border: 0; + margin: 0; + } + + .js .vertical-tabs__item > summary { display: none; } - .claro-details__wrapper--vertical-tabs-item { + .js .claro-details__wrapper--vertical-tabs-item { border-top: 0; - background: #fea; + background-color: transparent; + } + + .js .vertical-tabs__items--processed { + border-radius: 0 var(--base-border-radius) var(--base-border-radius) var(--base-border-radius); /* LTR */ + } + + .js[dir="rtl"] .vertical-tabs__items--processed { + border-radius: var(--base-border-radius) 0 var(--base-border-radius) var(--base-border-radius); } } @@ -224,8 +329,8 @@ * Set width to 100% so an input's size attribute does not cause the tabs to * exceed the width of the page. */ -.vertical-tabs__item .claro-details__content .form-element { - width: 100%; +.claro-details__content--vertical-tabs-item .form-element { + max-width: 100%; } /* @@ -233,60 +338,6 @@ * should get a max-width that resembles the width dictated by the default * size attribute. */ -.vertical-tabs__item .claro-details__content .form-element--type-text { +.claro-details__content--vertical-tabs-item .form-element--type-text { max-width: 31.25rem; } - -/** - * Styling for .vertical-tabs--default is for mobile and non-js users. The - * vertical-tabs--default is removed by Javascript when the viewport width is - * greater than or equal to drupalSettings.widthBreakpoint (when defined) or - * 640px (when drupalSettings.widthBreakpoint is not defined). - */ - -/* -.vertical-tabs--default > details { - margin-top: 0; - margin-bottom: 0; -} - -.vertical-tabs--default > details > summary { - padding: var(--vtabs-narrow-details-padding) var(--vtabs-narrow-details-padding) var(--vtabs-narrow-details-padding) var(--vtabs-narrow-details-padding-disclosure); -} - -.vertical-tabs--default > details[open] > summary { - color: var(--color-absolutezero); - background-color: var(--color-white); - padding-top: var(--space-s); - padding-bottom: var(--space-s); -} - -.vertical-tabs--default .claro-details__summary--accordion-item { - line-height: var(--vtabs-narrow-summary-line-height); -} - -.vertical-tabs--default > details:last-of-type { - border-bottom: 1px solid var(--color-lightgray-o-80); -} - -.vertical-tabs--default > details .claro-details__wrapper { - background-color: var(--color-whitesmoke); - margin: 0; - padding: 1em; -} - -.vertical-tabs__menu-item-summary--narrow, -.vertical-tabs--default span.summary { - display: block; - font-weight: normal; -} - -.vertical-tabs--default .claro-details__content--accordion-item, -.vertical-tabs--default .claro-details__content--accordion-item > .form-item { - margin: 0; -} */ - -.claro-details__summary--vertical-tabs-item:focus { - position: relative; - z-index: 1; -} diff --git a/js/claro.vertical-tabs.es6.js b/js/claro.vertical-tabs.es6.js index 04b1c64..ff551b0 100644 --- a/js/claro.vertical-tabs.es6.js +++ b/js/claro.vertical-tabs.es6.js @@ -48,11 +48,15 @@ */ Drupal.behaviors.claroVerticalTabs = { attach(context, settings) { - const verticalTabsSettings = { + const verticalTabsDefaults = { paneClasses: ['vertical-tabs__pane'], + paneClassesFirst: ['first'], + paneClassesLast: ['last'], + paneClassesHidden: ['vertical-tab--hidden'], paneWrapperClasses: ['vertical-tabs__panes'], + menuItemClassesHidden: [], }; - $.extend(verticalTabsSettings, settings.verticalTabs || {}); + const verticalTabsSettings = $.extend({}, verticalTabsDefaults, settings.verticalTabs || {}); /** * Binds a listener to handle fragment link clicks and URL hash changes. @@ -92,6 +96,7 @@ const verticalTab = new Drupal.verticalTab({ title: $that.find('> summary').text(), details: $that, + settings: verticalTabsSettings, }); /* eslint-enable new-cap */ tabList.append(verticalTab.item); @@ -119,8 +124,10 @@ } } if (tabFocus.length) { - tabFocus.data('verticalTab').focus(); - tabFocus.data('verticalTab').details.find('summary').trigger('click.detailsAria'); + tabFocus.data('verticalTab').focus(false); + // The core/misc/collapse.js won't be ready at this time, we have to + // open the details manually for non-upporting browsers. + // tabFocus.data('verticalTab').details.attr('open', true); } }); }, @@ -137,6 +144,8 @@ * The name of the tab. * @param {jQuery} settings.details * The jQuery object of the details element that is the tab pane. + * @param {jQuery} settings.settings + * The jQuery object of vertical tab settings. * * @fires event:summaryUpdated * @@ -144,6 +153,7 @@ */ Drupal.verticalTab = function verticalTab(settings) { const self = this; + this.settings = settings.settings; $.extend(this, settings, Drupal.theme('verticalTab', settings)); this.item.addClass('js-vertical-tabs-menu-item'); @@ -151,7 +161,7 @@ this.link.attr('href', `#${settings.details.attr('id')}`); this.detailsSummaryDescription = $(Drupal.theme.verticalTabDetailsDescription()) - .appendTo(this.details.children('summary')); + .appendTo(this.details.find('> summary')); this.link.on('click', (event) => { event.preventDefault(); @@ -159,12 +169,21 @@ }); this.details.on('toggle', (event) => { - if (event.target.open) { - this.link.trigger('click'); + // We will control this by summary clicks. + event.preventDefault(); + }); + + // For every browser, with or without details support. + this.details.find('> summary').on('click', (event) => { + event.preventDefault(); + self.details.attr('open', true); + if (self.details.hasClass('collapse-processed')) { + setTimeout(() => { + self.focus(); + }, 10); } - // If none of the details are opened, we have to reopen the current one. - else if (this.details.parent().find('details[open]').length === 0) { - this.details.find('summary').trigger('click'); + else { + self.focus(); } }); @@ -184,22 +203,29 @@ this.details .on('summaryUpdated', () => { self.updateSummary(); - }); + }).trigger('summaryUpdated'); }; Drupal.verticalTab.prototype = { /** * Displays the tab's content pane. + * + * @param {bool} triggerFocus + * Whether focus should be triggered for the summary element. */ - focus() { + focus(triggerFocus = true) { this.details .siblings('.js-vertical-tabs-pane') .each(function closeOtherTabs() { const tab = $(this).data('verticalTab'); if (tab.details.attr('open')) { tab.details - .children('summary') - .trigger('click'); + .removeAttr('open') + .find('> summary') + .attr({ + 'aria-expanded': 'false', + 'aria-pressed': 'false', + }); tab.item.removeClass('is-selected'); } }) @@ -207,8 +233,19 @@ .siblings(':hidden.vertical-tabs__active-tab') .val(this.details.attr('id')); - if (!this.details.attr('open')) { - this.details.children('summary').trigger('click'); + this.details + .attr('open', true) + .find('> summary') + .attr({ + 'aria-expanded': 'true', + 'aria-pressed': 'true', + }); + + if (triggerFocus) { + const $summary = this.details.find('> summary'); + if ($summary.is(':visible')) { + $summary.trigger('focus'); + } } this.item.addClass('is-selected'); @@ -235,21 +272,33 @@ */ tabShow() { // Display the tab. - this.item.show(); + this.item + .removeClass(this.settings.menuItemClassesHidden.join(' ')) + .show(); // Show the vertical tabs. this.item.closest('.js-form-type-vertical-tabs').show(); - // Update .first marker for items. We need recurse from parent to retain - // the actual DOM element order as jQuery implements sortOrder, but not - // as public method. - this.item + // Display the details element. + this.details + .removeClass(this.settings.paneClassesHidden.join(' ')) + .removeClass('js-vertical-tab-hidden') + .show(); + // Update first and last CSS classes for details. + this.details .parent() - .children('.js-vertical-tabs-menu-item') + .children('.js-vertical-tabs-pane') + .removeClass(this.settings.paneClassesFirst.join(' ')) + .removeClass(this.settings.paneClassesLast.join(' ')) .filter(':visible') - .eq(0); - // Display the details element. - this.details.removeClass('vertical-tab--hidden').show(); - // Focus this tab. - this.focus(); + .eq(0) + .addClass(this.settings.paneClassesFirst.join(' ')); + this.details + .parent() + .children('.js-vertical-tabs-pane') + .filter(':visible') + .eq(-1) + .addClass(this.settings.paneClassesLast.join(' ')); + // Make tab active, but without triggering focus. + this.focus(false); return this; }, @@ -261,25 +310,35 @@ */ tabHide() { // Hide this tab. - this.item.hide(); - // Update .first marker for items. We need recurse from parent to retain - // the actual DOM element order as jQuery implements sortOrder, but not - // as public method. this.item + .addClass(this.settings.menuItemClassesHidden.join(' ')) + .hide(); + // Hide the details element. + this.details + .addClass(this.settings.paneClassesHidden.join(' ')) + .addClass('js-vertical-tab-hidden') + .hide(); + // Update first and last CSS classes for details. + this.details .parent() - .children('.js-vertical-tabs-menu-item') - .removeClass('first') + .children('.js-vertical-tabs-pane') + .removeClass(this.settings.paneClassesFirst.join(' ')) + .removeClass(this.settings.paneClassesLast.join(' ')) .filter(':visible') .eq(0) - .addClass('first'); - // Hide the details element. - this.details.addClass('vertical-tab--hidden').hide(); + .addClass(this.settings.paneClassesFirst.join(' ')); + this.details + .parent() + .children('.js-vertical-tabs-pane') + .filter(':visible') + .eq(-1) + .addClass(this.settings.paneClassesLast.join(' ')); // Focus the first visible tab (if there is one). const $firstTab = this.details - .siblings('.js-vertical-tabs-pane:not(.vertical-tab--hidden)') + .siblings('.js-vertical-tabs-pane:not(.js-vertical-tab-hidden)') .eq(0); if ($firstTab.length) { - $firstTab.data('verticalTab').focus(); + $firstTab.data('verticalTab').focus(false); } // Hide the vertical tabs (if no tabs remain). else { @@ -307,7 +366,7 @@ Drupal.theme.verticalTab = (settings) => { const tab = {}; tab.item = $('
  • ') - .append((tab.link = $('') + .append((tab.link = $('') .append((tab.title = $('').text(settings.title))) .append((tab.summary = $(''))))); return tab; @@ -338,7 +397,7 @@ * A string representing the DOM fragment. */ Drupal.theme.verticalTabDetailsDescription = () => - ''; + ''; /** * Themes the active vertical tab menu item message. diff --git a/js/claro.vertical-tabs.js b/js/claro.vertical-tabs.js index 7588f76..61b947a 100644 --- a/js/claro.vertical-tabs.js +++ b/js/claro.vertical-tabs.js @@ -14,11 +14,15 @@ Drupal.behaviors.claroVerticalTabs = { attach: function attach(context, settings) { - var verticalTabsSettings = { + var verticalTabsDefaults = { paneClasses: ['vertical-tabs__pane'], - paneWrapperClasses: ['vertical-tabs__panes'] + paneClassesFirst: ['first'], + paneClassesLast: ['last'], + paneClassesHidden: ['vertical-tab--hidden'], + paneWrapperClasses: ['vertical-tabs__panes'], + menuItemClassesHidden: [] }; - $.extend(verticalTabsSettings, settings.verticalTabs || {}); + var verticalTabsSettings = $.extend({}, verticalTabsDefaults, settings.verticalTabs || {}); $('body').once('vertical-tabs-fragments').on('formFragmentLinkClickOrHashChange.verticalTabs', handleFragmentLinkClickOrHashChange); @@ -40,7 +44,8 @@ var verticalTab = new Drupal.verticalTab({ title: $that.find('> summary').text(), - details: $that + details: $that, + settings: verticalTabsSettings }); tabList.append(verticalTab.item); @@ -59,24 +64,22 @@ } } if (tabFocus.length) { - tabFocus.data('verticalTab').focus(); - tabFocus.data('verticalTab').details.find('summary').trigger('click.detailsAria'); + tabFocus.data('verticalTab').focus(false); } }); } }; Drupal.verticalTab = function verticalTab(settings) { - var _this = this; - var self = this; + this.settings = settings.settings; $.extend(this, settings, Drupal.theme('verticalTab', settings)); this.item.addClass('js-vertical-tabs-menu-item'); this.link.attr('href', '#' + settings.details.attr('id')); - this.detailsSummaryDescription = $(Drupal.theme.verticalTabDetailsDescription()).appendTo(this.details.children('summary')); + this.detailsSummaryDescription = $(Drupal.theme.verticalTabDetailsDescription()).appendTo(this.details.find('> summary')); this.link.on('click', function (event) { event.preventDefault(); @@ -84,11 +87,19 @@ }); this.details.on('toggle', function (event) { - if (event.target.open) { - _this.link.trigger('click'); - } else if (_this.details.parent().find('details[open]').length === 0) { - _this.details.find('summary').trigger('click'); - } + event.preventDefault(); + }); + + this.details.find('> summary').on('click', function (event) { + event.preventDefault(); + self.details.attr('open', true); + if (self.details.hasClass('collapse-processed')) { + setTimeout(function () { + self.focus(); + }, 10); + } else { + self.focus(); + } }); this.link.on('keydown', function (event) { @@ -102,21 +113,34 @@ this.details.on('summaryUpdated', function () { self.updateSummary(); - }); + }).trigger('summaryUpdated'); }; Drupal.verticalTab.prototype = { focus: function focus() { + var triggerFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + this.details.siblings('.js-vertical-tabs-pane').each(function closeOtherTabs() { var tab = $(this).data('verticalTab'); if (tab.details.attr('open')) { - tab.details.children('summary').trigger('click'); + tab.details.removeAttr('open').find('> summary').attr({ + 'aria-expanded': 'false', + 'aria-pressed': 'false' + }); tab.item.removeClass('is-selected'); } }).end().siblings(':hidden.vertical-tabs__active-tab').val(this.details.attr('id')); - if (!this.details.attr('open')) { - this.details.children('summary').trigger('click'); + this.details.attr('open', true).find('> summary').attr({ + 'aria-expanded': 'true', + 'aria-pressed': 'true' + }); + + if (triggerFocus) { + var $summary = this.details.find('> summary'); + if ($summary.is(':visible')) { + $summary.trigger('focus'); + } } this.item.addClass('is-selected'); @@ -130,27 +154,29 @@ this.summary.html(summary); }, tabShow: function tabShow() { - this.item.show(); + this.item.removeClass(this.settings.menuItemClassesHidden.join(' ')).show(); this.item.closest('.js-form-type-vertical-tabs').show(); - this.item.parent().children('.js-vertical-tabs-menu-item').filter(':visible').eq(0); + this.details.removeClass(this.settings.paneClassesHidden.join(' ')).removeClass('js-vertical-tab-hidden').show(); - this.details.removeClass('vertical-tab--hidden').show(); + this.details.parent().children('.js-vertical-tabs-pane').removeClass(this.settings.paneClassesFirst.join(' ')).removeClass(this.settings.paneClassesLast.join(' ')).filter(':visible').eq(0).addClass(this.settings.paneClassesFirst.join(' ')); + this.details.parent().children('.js-vertical-tabs-pane').filter(':visible').eq(-1).addClass(this.settings.paneClassesLast.join(' ')); - this.focus(); + this.focus(false); return this; }, tabHide: function tabHide() { - this.item.hide(); + this.item.addClass(this.settings.menuItemClassesHidden.join(' ')).hide(); - this.item.parent().children('.js-vertical-tabs-menu-item').removeClass('first').filter(':visible').eq(0).addClass('first'); + this.details.addClass(this.settings.paneClassesHidden.join(' ')).addClass('js-vertical-tab-hidden').hide(); - this.details.addClass('vertical-tab--hidden').hide(); + this.details.parent().children('.js-vertical-tabs-pane').removeClass(this.settings.paneClassesFirst.join(' ')).removeClass(this.settings.paneClassesLast.join(' ')).filter(':visible').eq(0).addClass(this.settings.paneClassesFirst.join(' ')); + this.details.parent().children('.js-vertical-tabs-pane').filter(':visible').eq(-1).addClass(this.settings.paneClassesLast.join(' ')); - var $firstTab = this.details.siblings('.js-vertical-tabs-pane:not(.vertical-tab--hidden)').eq(0); + var $firstTab = this.details.siblings('.js-vertical-tabs-pane:not(.js-vertical-tab-hidden)').eq(0); if ($firstTab.length) { - $firstTab.data('verticalTab').focus(); + $firstTab.data('verticalTab').focus(false); } else { this.item.closest('.js-form-type-vertical-tabs').hide(); } @@ -160,7 +186,7 @@ Drupal.theme.verticalTab = function (settings) { var tab = {}; - tab.item = $('
  • ').append(tab.link = $('').append(tab.title = $('').text(settings.title)).append(tab.summary = $(''))); + tab.item = $('
  • ').append(tab.link = $('').append(tab.title = $('').text(settings.title)).append(tab.summary = $(''))); return tab; }; @@ -173,7 +199,7 @@ }; Drupal.theme.verticalTabDetailsDescription = function () { - return ''; + return ''; }; Drupal.theme.verticalTabActiveTabIndicator = function () {