From d6efdc59ffa66d7013e665b1a50c20bf2b4e730f Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 13 Jun 2026 17:57:46 -0400 Subject: [PATCH] [tabs] Update tabs. --- public/assets/scaffolding-min.js | 220 +++- public/assets/scaffolding.css | 1376 ++++++++++++++++++++- public/patterns/core/tabs/index.html | 724 ++++++++--- src/pg/patterns/core/tabs/_tabs-jquery.js | 27 - src/pg/patterns/core/tabs/_tabs.js | 496 +++++--- src/pg/patterns/core/tabs/_tabs.scss | 292 +++-- src/pg/patterns/core/tabs/tabs.css | 185 ++- 7 files changed, 2777 insertions(+), 543 deletions(-) delete mode 100644 src/pg/patterns/core/tabs/_tabs-jquery.js diff --git a/public/assets/scaffolding-min.js b/public/assets/scaffolding-min.js index cce41e9..7c50c30 100644 --- a/public/assets/scaffolding-min.js +++ b/public/assets/scaffolding-min.js @@ -3194,9 +3194,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ init: function() { return /* binding */ init; } /* harmony export */ }); -/* DS2 core (c) 2024 Alexander McIlwraith - Released under Creative Commons Attribution-ShareAlike 4.0 International - */ +/* DS2 core (c) 2024-2026 Alexander McIlwraith + Released under Creative Commons Attribution-ShareAlike 4.0 International +*/ // create a pure JS mouse click event var click = new MouseEvent('click', { @@ -3204,70 +3204,67 @@ var click = new MouseEvent('click', { bubbles: false, cancelable: true }); + +// wait for an element to appear in the DOM var waitForElement = function waitForElement(selector) { return new Promise(function (resolve) { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } - var observer = new MutationObserver(function (mutations) { + var observer = new MutationObserver(function () { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); - - // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); }; + +// Tab logic +var tabNamespace = "#tab:"; var chooseTab = function chooseTab(tab) { - var siblings = Array.from(tab.parentNode.children); + var siblings = Array.from(tab.closest('[role="tablist"]').querySelectorAll('[role="tab"]')); siblings.forEach(function (sibling) { return sibling.classList.remove("selected"); }); tab.classList.add("selected"); - var tabPanels = Array.from(tab.parentNode.parentNode.children); + var tabGroup = tab.closest("tabset, .tab-group"); + var tabPanels = Array.from(tabGroup.querySelectorAll('[role="tabpanel"]')); tabPanels.forEach(function (panel) { return panel.classList.remove("open"); }); var tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel"); document.getElementById(tabPanelId).classList.add("open"); }; -var pushState = 0; +var pushStateCount = 0; var tabsetCount = 0; function init() { var container = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; var spacer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; - var args = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; container.querySelectorAll(".tab-group, tabset").forEach(function (tabGroup) { - if (tabGroup.querySelector("[role=tablist]") === null) { + if (tabGroup.querySelector('[role="tablist"]') === null) { + var _ul$querySelector; if (tabGroup.getAttribute("id") == null) { - tabGroup.setAttribute("id", "tab-group-" + tabsetCount); - tabsetCount++; + tabGroup.setAttribute("id", "tab-group-".concat(tabsetCount++)); } var tabgroup = tabGroup.getAttribute("id"); var tablist = ""; Array.from(tabGroup.children).forEach(function (child) { - // is details? - var dtls = child.nodeName == "DETAILS" ? true : false; - - // get the tab text - var tab = dtls ? child.querySelector("summary").innerHTML : child.getAttribute("tab") || child.getAttribute("data-tab"); - - // if the tab text is not blank - if (tab !== null) { - var tabID = tab.replace(/\W+/g, "-").toLowerCase(); - - // define the tab panel content - var tabPanel = null; - if (dtls) { + var _child$querySelector; + var isDetails = child.nodeName === "DETAILS"; + var tabLabel = isDetails ? (_child$querySelector = child.querySelector("summary")) === null || _child$querySelector === void 0 ? void 0 : _child$querySelector.innerHTML : child.getAttribute("tab") || child.getAttribute("data-tab"); + if (tabLabel !== null) { + var tabID = tabLabel.replace(/\W+/g, "-").toLowerCase(); + var tabPanel; + if (isDetails) { tabPanel = child; tabPanel.setAttribute("open", ""); } else { - tabPanel = document.createElement('div'); + tabPanel = document.createElement("div"); tabPanel.appendChild(child.cloneNode(true)); } tabPanel.id = "tab-panel-".concat(tabgroup, "-").concat(tabID); @@ -3276,75 +3273,166 @@ function init() { tabPanel.setAttribute("tabindex", "0"); tabPanel.setAttribute("aria-labelledby", "tab-".concat(tabgroup, "-").concat(tabID)); child.parentNode.replaceChild(tabPanel, child); - tablist += "
  • ").concat(tab, "
  • "); + tablist += "
  • \n\t\t\t\t\t\t\t").concat(tabLabel, "\n\t\t\t\t\t\t
  • "); } else { child.classList.add("tab-hidden"); } }); - var ul = document.createElement('ul'); + var ul = document.createElement("ul"); ul.setAttribute("role", "tablist"); tabGroup.insertBefore(ul, tabGroup.firstChild); - ul.innerHTML = spacer != true ? "".concat(tablist) : "".concat(tablist, "
  • "); + var wrapper = document.createElement("div"); + wrapper.className = "tab-scroll-wrapper"; + var scroller = document.createElement("div"); + scroller.className = "tab-scroll"; + var leftArrow = document.createElement("div"); + leftArrow.className = "tab-scroll-arrow left"; + leftArrow.setAttribute("aria-hidden", "true"); + leftArrow.innerHTML = "\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t"; + var rightArrow = document.createElement("div"); + rightArrow.className = "tab-scroll-arrow right"; + rightArrow.setAttribute("aria-hidden", "true"); + rightArrow.innerHTML = "\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t"; + ul.parentNode.insertBefore(wrapper, ul); + wrapper.appendChild(scroller); + wrapper.appendChild(leftArrow); + wrapper.appendChild(rightArrow); + scroller.appendChild(ul); + var updateScrollState = function updateScrollState() { + var isOverflowing = scroller.scrollWidth > scroller.clientWidth; + wrapper.classList.toggle("is-overflowing", isOverflowing); + var atStart = scroller.scrollLeft <= 1; + var atEnd = scroller.scrollLeft + scroller.clientWidth >= scroller.scrollWidth - 2; + leftArrow.classList.toggle("hidden", !isOverflowing || atStart); + rightArrow.classList.toggle("hidden", !isOverflowing || atEnd); + wrapper.classList.toggle("show-left", isOverflowing && !atStart); + wrapper.classList.toggle("show-right", isOverflowing && !atEnd); + }; + var scrollAmount = 15; // smaller = smoother per frame + var scrollInterval = 16; // ~60fps + + var scrollTimer = null; + var startScrolling = function startScrolling(direction) { + if (scrollTimer) return; + var speed = 0.1; + scrollTimer = setInterval(function () { + speed = Math.min(speed + 0.01, 5); // ramp up + scroller.scrollBy({ + left: direction * scrollAmount * speed, + behavior: "auto" + }); + }, scrollInterval); + }; + var stopScrolling = function stopScrolling() { + clearInterval(scrollTimer); + scrollTimer = null; + }; + leftArrow.addEventListener("mousedown", function () { + return startScrolling(-1); + }); + leftArrow.addEventListener("mouseup", stopScrolling); + leftArrow.addEventListener("mouseleave", stopScrolling); + leftArrow.addEventListener("touchstart", function () { + return startScrolling(-1); + }); + leftArrow.addEventListener("touchend", stopScrolling); + rightArrow.addEventListener("mousedown", function () { + return startScrolling(1); + }); + rightArrow.addEventListener("mouseup", stopScrolling); + rightArrow.addEventListener("mouseleave", stopScrolling); + rightArrow.addEventListener("touchstart", function () { + return startScrolling(1); + }); + rightArrow.addEventListener("touchend", stopScrolling); + var ARROW_ZONE = 40; + wrapper.addEventListener("contextmenu", function (e) { + var isOverflowing = wrapper.classList.contains("is-overflowing"); + if (!isOverflowing) return; + var rect = wrapper.getBoundingClientRect(); + var isLeftZone = e.clientX < rect.left + ARROW_ZONE; + var isRightZone = e.clientX > rect.right - ARROW_ZONE; + if (isLeftZone || isRightZone) { + e.preventDefault(); + } + }); + var scrollClickAmount = 150; + leftArrow.addEventListener("click", function () { + scroller.scrollBy({ + left: -scrollClickAmount, + behavior: "smooth" + }); + }); + rightArrow.addEventListener("click", function () { + scroller.scrollBy({ + left: scrollClickAmount, + behavior: "smooth" + }); + }); + scroller.addEventListener("scroll", updateScrollState); + window.addEventListener("resize", updateScrollState); + updateScrollState(); + ul.innerHTML = spacer !== true ? tablist : "".concat(tablist, "
  • "); + requestAnimationFrame(updateScrollState); + setTimeout(updateScrollState, 50); + ul.innerHTML = spacer !== true ? tablist : "".concat(tablist, "
  • "); + + // Tab ordering if (tabGroup.hasAttribute("order") || tabGroup.hasAttribute("data-order")) { var order = (tabGroup.getAttribute("order") || tabGroup.getAttribute("data-order")).split(","); var items = Array.from(ul.getElementsByTagName("li")); items.sort(function (a, b) { - console.log("here"); var aa = order.indexOf(a.textContent.trim()); var bb = order.indexOf(b.textContent.trim()); - - // Check if both items exist in orderArray - if (aa === -1) return 1; // Move to the end if not found - if (bb === -1) return -1; // Move to the end if not found - - return aa - bb; // Sort based on the defined order + if (aa === -1) return 1; + if (bb === -1) return -1; + return aa - bb; }); - ul.innerHTML = ''; + ul.innerHTML = ""; items.forEach(function (item) { return ul.appendChild(item); }); + chooseTab(items[0]); } + + // Tab event handlers tabGroup.querySelectorAll('[role="tab"]').forEach(function (tab) { tab.addEventListener("click", function (evt) { - if (pushState == 0) { - window.history.pushState({ - rand: Math.random(), - pushState: pushState, - tab: tab.parentNode.firstChild.getAttribute("id") - }, "", "#".concat(tab.parentNode.firstChild.getAttribute("id"))); - pushState++; - } + var tabId = tab.getAttribute("id"); + var hash = "".concat(tabNamespace).concat(tabId); chooseTab(evt.currentTarget); window.history.pushState({ - rand: Math.random(), - pushState: pushState, - tab: tab.getAttribute("id") - }, "", "#".concat(tab.getAttribute("id"))); - pushState++; + tab: tabId + }, "", "".concat(location.pathname).concat(location.search).concat(hash)); + pushStateCount++; }); tab.addEventListener("keypress", function (e) { - e.preventDefault(); - if (e.which == 32 || e.which == 13) { + if (e.which === 32 || e.which === 13) { + e.preventDefault(); e.currentTarget.dispatchEvent(click); } }); }); - ul.querySelector("li").classList.add("selected"); - } - if (document.location.hash != "" && document.location.hash.substring(0, 5) == "#tab-") { - waitForElement(document.location.hash).then(function (el) { - //el.scrollIntoView(); - el.focus(); - el.dispatchEvent(click); - }); + (_ul$querySelector = ul.querySelector("li")) === null || _ul$querySelector === void 0 || _ul$querySelector.classList.add("selected"); } }); + + // Initial hash handling (tabs only) + if (location.hash.startsWith(tabNamespace)) { + var tabId = location.hash.replace(tabNamespace, ""); + waitForElement("#".concat(tabId)).then(function (el) { + el.focus(); + el.dispatchEvent(click); + }); + } + + // History navigation (tabs only) window.addEventListener("popstate", function (e) { - e.preventDefault(); - if (e.state != null) { - chooseTab(document.querySelector("#".concat(e.state.tab))); - } else { - history.go(-1); + var _e$state; + if (!location.hash.startsWith(tabNamespace)) return; + if ((_e$state = e.state) !== null && _e$state !== void 0 && _e$state.tab) { + var tab = document.querySelector("#".concat(e.state.tab)); + if (tab) chooseTab(tab); } }); } diff --git a/public/assets/scaffolding.css b/public/assets/scaffolding.css index c2cdd36..cc85870 100644 --- a/public/assets/scaffolding.css +++ b/public/assets/scaffolding.css @@ -1 +1,1375 @@ -:root{--colour-blue:#2e51a1;--colour-blue-l:#5c7abf;--colour-blue-xl:#b2c3ec;--colour-blue-d:#133176;--colour-blue-xd:#031235;--colour-grey:#7f7f7f;--colour-grey-l:#b2b2b2;--colour-grey-xl:#d8d8d8;--colour-grey-xxl:#f0f0f0;--colour-white:#fff;--colour-page:#fff;--colour-light:#fff;--colour-grey-d:#4c4c4c;--colour-grey-xd:#4c4c4c;--colour-black:#000;--colour-dark:#000}h1[class^=status]:after,h2[class^=status]:after,span[class^=status]:after{border-radius:50%;border:1px solid #CCC;content:" ";display:inline-block;height:1.5rem;margin-left:0.5rem;position:relative;top:2px;width:1.5rem}.status-not-started:after{background-color:transparent}.status-in-progress:after{background-color:#f0b031}.status-complete:after{background-color:#2e51a1}.status-deprecated:after{background-color:#da2c5b}code[class*=language-],pre[class*=language-]{color:black;background:none;text-shadow:0 1px white;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:0.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:0.1em;border-radius:0.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:slategray}.token.punctuation{color:#999}.token.namespace{opacity:0.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,0.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#DD4A68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:bold}.token.italic{font-style:italic}.token.entity{cursor:help}div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:0.3em;right:0.2em;-webkit-transition:opacity 0.3s ease-in-out;transition:opacity 0.3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:none;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:0.8em;padding:0 0.5em;background:#f5f2f0;background:rgba(224,224,224,0.2);-webkit-box-shadow:0 2px 0 0 rgba(0,0,0,0.2);box-shadow:0 2px 0 0 rgba(0,0,0,0.2);border-radius:0.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:0.8em;text-align:right}#copystatus{left:50%;position:absolute;z-index:100}#copystatus div{border-radius:1rem;border:1px solid green;left:-50%;padding:1rem;position:relative;white-space:nowrap}#copystatus div:after{clear:both;content:" ";display:block}#copystatus div.succeeded{background-color:white;border-color:black;color:black}#copystatus div.failed{background-color:white;border-color:#f00;color:#f00}color-samples{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;gap:1rem;margin-bottom:1rem}@media (max-width:992px){color-samples{display:-ms-grid;display:grid;-ms-grid-columns:(1fr)[2];grid-template-columns:repeat(2,1fr);max-width:100%;width:100%}}@media (max-width:576px){color-samples{-ms-grid-columns:auto;grid-template-columns:auto;width:100%;max-width:100%}}color-samples color-sample{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0.5rem;border:1px solid #CCC;display:-ms-grid;display:grid;font-family:inherit;gap:0.5rem;grid-template-areas:"name name name hex hex hex" "name name name rgb rgb rgb" "acc acc acc acc acc acc" "lighter lighter lighter darker darker darker" "notes notes notes notes notes notes";-ms-grid-columns:1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr;grid-template-columns:repeat(6,1fr);-ms-grid-rows:1.5rem 0.5rem 1.5rem 0.5rem 10rem 0.5rem max-content 0.5rem max-content 0.5rem max-content;grid-template-rows:repeat(2,1.5rem) 10rem repeat(3,-webkit-max-content);grid-template-rows:repeat(2,1.5rem) 10rem repeat(3,max-content);padding:1rem;width:20rem;max-width:318px}@media (max-width:992px){color-samples color-sample{width:100%;max-width:100%}}color-samples color-sample name{-ms-grid-row:1;-ms-grid-row-span:3;-ms-grid-column:1;-ms-grid-column-span:5;-ms-grid-row-align:start;align-self:start;font-size:1.25rem;grid-area:name}color-samples color-sample name span{cursor:pointer}color-samples color-sample rgb{-ms-grid-row:3;-ms-grid-column:7;-ms-grid-column-span:5;grid-area:rgb;white-space:nowrap}color-samples color-sample hex{-ms-grid-row:1;-ms-grid-column:7;-ms-grid-column-span:5;grid-area:hex;white-space:nowrap}color-samples color-sample>accessibility{border-bottom:1px solid #ccc;border-top:1px solid #ccc}color-samples color-sample accessibility{-ms-grid-row:5;-ms-grid-column:1;-ms-grid-column-span:11;grid-area:acc;-ms-grid-row:3;grid-row:3;padding:0.5rem 0;display:-ms-grid;display:grid;gap:0.5rem;-ms-grid-columns:(1fr)[3];grid-template-columns:repeat(3,1fr);-ms-grid-rows:(-webkit-max-content)[3];-ms-grid-rows:(max-content)[3];grid-template-rows:repeat(3,-webkit-max-content);grid-template-rows:repeat(3,max-content)}color-samples color-sample accessibility .result{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0.5rem;display:-ms-grid;display:grid;-ms-grid-columns:(1fr)[2];grid-template-columns:repeat(2,1fr);border:1px solid #ccc;padding:0 1rem;text-align:center}color-samples color-sample accessibility .result.accwaa,color-samples color-sample accessibility .result.accwaaa{background-color:white;color:black}color-samples color-sample accessibility .result.accbaa,color-samples color-sample accessibility .result.accbaaa{background-color:black;color:white}color-samples color-sample accessibility .result span:nth-child(2){font-size:2rem}color-samples color-sample accessibility .aa,color-samples color-sample accessibility .aaa{-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;display:block;font-size:0.75rem}color-samples color-sample accessibility .acchb{-ms-grid-column:2;grid-column:2}color-samples color-sample accessibility .acchb,color-samples color-sample accessibility .acchw{display:-ms-grid;display:grid;grid-tempate-columns:auto;-ms-grid-rows:(-webkit-max-content)[2];-ms-grid-rows:(max-content)[2];grid-template-rows:repeat(2,-webkit-max-content);grid-template-rows:repeat(2,max-content);-ms-grid-row-align:start;align-self:start;text-align:center;padding:0}color-samples color-sample accessibility .acchb span,color-samples color-sample accessibility .acchw span{-ms-grid-row:1;grid-row:1;grid-column:1/-1;font-size:0.9rem}color-samples color-sample accessibility .acchb small,color-samples color-sample accessibility .acchw small{text-align:center;-ms-grid-row:2;grid-row:2;grid-column:1/-1;font-size:0.75rem}color-samples color-sample sample-block{-ms-grid-row-align:start;align-self:start;-ms-grid-column-span:3;grid-column:span 3;-ms-grid-row:4;grid-row:4}color-samples color-sample sample-block color-pill{display:-ms-grid;display:grid;grid-gap:0.5rem;-ms-grid-columns:20px -webkit-max-content auto;-ms-grid-columns:20px max-content auto;grid-template-columns:20px -webkit-max-content auto;grid-template-columns:20px max-content auto}color-samples color-sample sample-block color-pill :first-child{-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;border-radius:5px;border:1px solid #CCC;display:inline-block;height:10px;width:20px}color-samples color-sample sample-block color-pill span{cursor:pointer}color-samples color-sample sample-block color-pill span .tooltip-tc{padding:0.5rem;width:20rem;max-width:318px;height:10.5rem;display:-ms-grid;display:grid;gap:0.5rem;-ms-grid-columns:(1fr)[3];grid-template-columns:repeat(3,1fr);-ms-grid-rows:(-webkit-max-content)[3];-ms-grid-rows:(max-content)[3];grid-template-rows:repeat(3,-webkit-max-content);grid-template-rows:repeat(3,max-content)}color-samples color-sample sample-block color-pill span .tooltip-tc .result{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0.5rem;display:-ms-grid;display:grid;-ms-grid-columns:(1fr)[2];grid-template-columns:repeat(2,1fr);border:1px solid #ccc;padding:0 1rem;text-align:center}color-samples color-sample sample-block color-pill span .tooltip-tc .result.accwaa,color-samples color-sample sample-block color-pill span .tooltip-tc .result.accwaaa{background-color:white;color:black}color-samples color-sample sample-block color-pill span .tooltip-tc .result.accbaa,color-samples color-sample sample-block color-pill span .tooltip-tc .result.accbaaa{background-color:black;color:white}color-samples color-sample sample-block color-pill span .tooltip-tc .result span{border:none}color-samples color-sample sample-block color-pill span .tooltip-tc .result span:nth-child(2){font-size:2rem}color-samples color-sample sample-block color-pill span .tooltip-tc .aa,color-samples color-sample sample-block color-pill span .tooltip-tc .aaa{-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;display:block;font-size:0.75rem}color-samples color-sample sample-block color-pill span .tooltip-tc .acchb{-ms-grid-column:2;grid-column:2}color-samples color-sample sample-block color-pill span .tooltip-tc .acchb,color-samples color-sample sample-block color-pill span .tooltip-tc .acchw{border:none;display:block;width:100%;-ms-grid-row-align:stretch;-ms-grid-column-align:stretch;place-self:stretch}color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span,color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span{border:none;font-size:0.9rem;width:100%}color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span:after,color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span:before,color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span:after,color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span:before{display:none}color-samples color-sample sample-block color-pill span .tooltip-tc .acchb small,color-samples color-sample sample-block color-pill span .tooltip-tc .acchw small{font-size:0.75rem;text-align:center}color-samples color-sample notes{border-top:1px solid #ccc;grid-column:1/-1;padding-top:0.5rem}[role=tooltip]{background:#fff;border-radius:0.5rem;color:#000;display:none;-webkit-filter:drop-shadow(0 3px 3px hsla(0,0%,0%,0.15)) drop-shadow(0 12px 12px hsla(0,0%,0%,0.15));filter:drop-shadow(0 3px 3px hsla(0,0%,0%,0.15)) drop-shadow(0 12px 12px hsla(0,0%,0%,0.15));font-size:1rem;font-weight:400;inline-size:-webkit-max-content;inline-size:-moz-max-content;inline-size:max-content;line-height:initial;margin:0;max-inline-size:25rem;opacity:0;padding:0.75rem 1.5rem;pointer-events:none;position:absolute;text-align:start;-webkit-transform:translate(var(--tooltip-x,0)) translateY(var(--tooltip-y,0));-ms-transform:translate(var(--tooltip-x,0)) translateY(var(--tooltip-y,0));transform:translate(var(--tooltip-x,0)) translateY(var(--tooltip-y,0));-webkit-transition:opacity 0.2s ease,-webkit-transform 0.2s ease;transition:opacity 0.2s ease,-webkit-transform 0.2s ease;transition:opacity 0.2s ease,transform 0.2s ease;transition:opacity 0.2s ease,transform 0.2s ease,-webkit-transform 0.2s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:filter;z-index:10}[role=tooltip]:before{clip-path:inset(50%);clip:rect(1px,1px,1px,1px);content:"; Has tooltip: ";height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}[role=tooltip]:after{background:#fff;content:"";inset:0;-webkit-mask:var(--tooltip-pointer);mask:var(--tooltip-pointer);position:absolute;z-index:-1}[role=tooltip]:is([tip-position=top],[tip-position=block-start],:not([tip-position]),[tip-position=bottom],[tip-position=block-end]){text-align:center}[role=tooltip]:is([tip-position=top],[tip-position=block-start],:not([tip-position])){inset-inline-start:50%;inset-block-end:calc(100% + 0.75rem + 1rem);--tooltip-x:calc(50% * -1)}[role=tooltip]:is([tip-position=top],[tip-position=block-start],:not([tip-position])):after{--tooltip-pointer:conic-gradient(from -30deg at bottom,rgba(0,0,0,0),#000 1deg 60deg,rgba(0,0,0,0) 61deg) bottom/100% 50% no-repeat;inset-block-end:-1rem;-webkit-border-after:1rem solid transparent;border-block-end:1rem solid transparent}[role=tooltip]:is([tip-position=right],[tip-position=inline-end]){inset-inline-start:calc(100% + 1.5rem + 1rem);inset-block-end:50%;--tooltip-y:50%}[role=tooltip]:is([tip-position=right],[tip-position=inline-end]):after{--tooltip-pointer:conic-gradient(from 60deg at left,rgba(0,0,0,0),#000 1deg 60deg,rgba(0,0,0,0) 61deg) left/50% 100% no-repeat;inset-inline-start:-1rem;-webkit-border-start:1rem solid transparent;border-inline-start:1rem solid transparent}[role=tooltip]:is([tip-position=bottom],[tip-position=block-end]){inset-inline-start:50%;inset-block-start:calc(100% + 0.75rem + 1rem);--tooltip-x:calc(50% * -1)}[role=tooltip]:is([tip-position=bottom],[tip-position=block-end]):after{--tooltip-pointer:conic-gradient(from 150deg at top,rgba(0,0,0,0),#000 1deg 60deg,rgba(0,0,0,0) 61deg) top/100% 50% no-repeat;inset-block-start:-1rem;-webkit-border-before:1rem solid transparent;border-block-start:1rem solid transparent}[role=tooltip]:is([tip-position=left],[tip-position=inline-start]){inset-inline-end:calc(100% + 1.5rem + 1rem);inset-block-end:50%;--tooltip-y:50%}[role=tooltip]:is([tip-position=left],[tip-position=inline-start]):after{--tooltip-pointer:conic-gradient(from -120deg at right,rgba(0,0,0,0),#000 1deg 60deg,rgba(0,0,0,0) 61deg) right/50% 100% no-repeat;inset-inline-end:-1rem;-webkit-border-end:1rem solid transparent;border-inline-end:1rem solid transparent}@media (prefers-color-scheme:dark){[role=tooltip]{background:#1f2127;color:#fff;-webkit-filter:drop-shadow(0 3px 3px hsla(0,0%,0%,0.5)) drop-shadow(0 12px 12px hsla(0,0%,0%,0.5));filter:drop-shadow(0 3px 3px hsla(0,0%,0%,0.5)) drop-shadow(0 12px 12px hsla(0,0%,0%,0.5))}[role=tooltip]:after{background:#1f2127}}:has(>[role=tooltip]){position:relative}:has(>[role=tooltip]):is(:hover,:focus-visible,:active)>[role=tooltip]{display:block;opacity:1;-webkit-transition-delay:300ms;transition-delay:300ms}@media (prefers-reduced-motion:no-preference){:has(>[role=tooltip]:is([tip-position=top],[tip-position=block-start],:not([tip-position]))):not(:hover):not(:active) [role=tooltip]{--tooltip-y:3px}:has(>[role=tooltip]:is([tip-position=right],[tip-position=inline-end])):not(:hover):not(:active) [role=tooltip]{--tooltip-x:calc(-1 * -3px * -1)}:has(>[role=tooltip]:is([tip-position=bottom],[tip-position=block-end])):not(:hover):not(:active) [role=tooltip]{--tooltip-y:-3px}:has(>[role=tooltip]:is([tip-position=left],[tip-position=inline-start])):not(:hover):not(:active) [role=tooltip]{--tooltip-x:calc(-1 * 3px * -1)}}sticky-note-wrapper{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid transparent;border-radius:50%;display:inline-block;height:0.5rem;position:relative;width:0.5rem}sticky-note-wrapper *{-webkit-box-sizing:border-box;box-sizing:border-box}sticky-note-wrapper sticky-note{cursor:-webkit-grab;cursor:grab;display:-ms-grid;display:grid;float:left;font-size:1rem;height:13rem;left:0;place-items:stretch;position:absolute;top:0;width:13rem;z-index:100}sticky-note-wrapper sticky-note:active{cursor:-webkit-grabbing;cursor:grabbing;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}sticky-note-wrapper sticky-note.right{float:right}sticky-note-wrapper sticky-note>div{-ms-grid-row:1;grid-row:1;-ms-grid-column:1;grid-column:1}sticky-note-wrapper sticky-note>div:first-child{background-color:rgba(0,0,0,0.25);-webkit-box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);box-shadow:-2px 2px 15px 0 rgba(0,0,0,0.5);display:-ms-grid;display:grid;margin:2rem 1rem 0.25rem 0.36rem;width:calc(100% - 1rem)}sticky-note-wrapper sticky-note>div:nth-child(2){clip-path:url(#stickyClip);display:-ms-grid;display:grid;font-family:"Kalam",cursive;font-style:1rem;font-weight:300;line-height:1.25rem;padding:1rem;place-items:center;text-align:center}sticky-note-wrapper sticky-note>div:nth-child(2)>*{font-family:"Kalam",cursive!important;font-style:normal!important;font-weight:300!important}@media screen and (max-width:1024px){sticky-note-wrapper sticky-note>div:nth-child(2){max-width:13rem;min-width:13rem;width:1rem}}@media screen and (max-width:768px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:1.75rem;max-width:21rem;min-height:21rem}}@media screen and (max-width:640px){sticky-note-wrapper sticky-note>div:nth-child(2){font-size:2.5rem;max-width:26rem;min-height:26rem}}sticky-note-wrapper sticky-note>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(rgb(255,255,221.2)),color-stop(2%,#ffffd3),color-stop(12%,#ffffd3),color-stop(75%,rgb(255,255,200.8)),to(rgb(255,255,185.5)));background:linear-gradient(180deg,rgb(255,255,221.2) 0%,#ffffd3 2%,#ffffd3 12%,rgb(255,255,200.8) 75%,rgb(255,255,185.5) 100%)}sticky-note-wrapper sticky-note.blue>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(rgb(156.5265625,220.9484375,235.6734375)),color-stop(2%,#94daea),color-stop(12%,#94daea),color-stop(75%,rgb(139.4734375,215.0515625,232.3265625)),to(rgb(126.68359375,210.62890625,229.81640625)));background:linear-gradient(180deg,rgb(156.5265625,220.9484375,235.6734375) 0%,#94daea 2%,#94daea 12%,rgb(139.4734375,215.0515625,232.3265625) 75%,rgb(126.68359375,210.62890625,229.81640625) 100%)}sticky-note-wrapper sticky-note.pink>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(rgb(250.3493150685,123.8506849315,147.104109589)),color-stop(2%,#fa728b),color-stop(12%,#fa728b),color-stop(75%,rgb(249.6506849315,104.1493150685,130.895890411)),to(rgb(249.1267123288,89.3732876712,118.7397260274)));background:linear-gradient(180deg,rgb(250.3493150685,123.8506849315,147.104109589) 0%,#fa728b 2%,#fa728b 12%,rgb(249.6506849315,104.1493150685,130.895890411) 75%,rgb(249.1267123288,89.3732876712,118.7397260274) 100%)}sticky-note-wrapper sticky-note.green>div:nth-child(2){background:-webkit-gradient(linear,left top,left bottom,from(rgb(196.6333333333,251.5666666667,200.925)),color-stop(2%,#bbfbc0),color-stop(12%,#bbfbc0),color-stop(75%,rgb(177.3666666667,250.4333333333,183.075)),to(rgb(162.9166666667,249.5833333333,169.6875)));background:linear-gradient(180deg,rgb(196.6333333333,251.5666666667,200.925) 0%,#bbfbc0 2%,#bbfbc0 12%,rgb(177.3666666667,250.4333333333,183.075) 75%,rgb(162.9166666667,249.5833333333,169.6875) 100%)}sticky-note-wrapper:has(sticky-note:hover){background-color:#ffffd3;border:1px solid black}sticky-note-wrapper:has(sticky-note.yellow:hover){background-color:#ffffd3}sticky-note-wrapper:has(sticky-note.blue:hover){background-color:#94daea}sticky-note-wrapper:has(sticky-note.pink:hover){background-color:#fa728b}sticky-note-wrapper:has(sticky-note.green:hover){background-color:#bbfbc0}div.status-report p.heading,div.status-report td[colspan="2"]{font-size:1.125rem;font-weight:bolder!important;grid-column:1/-1;margin:2rem 0 0.5rem 0;padding-top:1.5rem!important}div.status-report td:not([colspan="2"]) span{display:-ms-grid;display:grid;-ms-grid-columns:auto 1rem;grid-template-columns:auto 1rem;margin:0 1rem 0 0}div.status-report td:not([colspan="2"]) span span[class^=status]:after{height:1rem!important;width:1rem!important;margin-right:1rem}div.status-report td:not([colspan="2"]) a{margin:0 1rem 0 0}div.status-report td:not([colspan="2"]).indent a{margin:0 1rem 0 1.5rem}*{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-family:Helvetica,Arial,sans-serif;font-size:14pt}@media (max-width:768px){html{font-size:16pt}}html.show-breakpoints body:after,html.show-breakpoints body:before{background-color:#555;color:white;content:"bigger than extra large";display:-ms-grid;display:grid;font-family:sans-serif;font-size:25px;-ms-grid-columns:auto;grid-template-columns:auto;padding:25px;place-content:center}@media (max-width:1200px){html.show-breakpoints body:after,html.show-breakpoints body:before{content:"extra large"}}@media (max-width:992px){html.show-breakpoints body:after,html.show-breakpoints body:before{content:"large"}}@media (max-width:768px){html.show-breakpoints body:after,html.show-breakpoints body:before{content:"medium"}}@media (max-width:576px){html.show-breakpoints body:after,html.show-breakpoints body:before{content:"small"}}article[data-status=deprecated]:not(.show-deprecated){display:none}body{margin:0;padding:0}body a.skip{position:absolute;left:-9999px}body .container{display:-ms-grid;display:grid;-ms-grid-columns:auto (22rem)[2] auto;grid-template-columns:auto repeat(2,22rem) auto;margin:0 auto;width:100vw}body .container header{display:-ms-grid;display:grid;-ms-grid-rows:1.75rem 3.5rem;grid-template-rows:1.75rem 3.5rem;-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;overflow:hidden}body .container header svg{grid-column:1/-1;grid-row:1/-1;-ms-grid-row-align:stretch;-ms-grid-column-align:stretch;place-self:stretch}body .container header svg text{-webkit-transform:translate(-1rem,7.25rem);-ms-transform:translate(-1rem,7.25rem);transform:translate(-1rem,7.25rem);font-size:10rem;font-weight:1000;font-family:sans-serif;fill:var(--colour-grey-xxl)}body .container header>div{-ms-grid-row:2;grid-row:2;grid-column:1/-1;display:-ms-grid;display:grid;grid-column-gap:1rem;-ms-grid-columns:auto -webkit-max-content -webkit-max-content;-ms-grid-columns:auto max-content max-content;grid-template-columns:auto -webkit-max-content -webkit-max-content;grid-template-columns:auto max-content max-content}body .container header>div .header-title h1{margin:0;padding:0 1rem}body .container header>div .header-title h1 a,body .container header>div .header-title h1 a:visited{border-bottom:none;color:var(--colour-black);font-family:sans-serif;font-size:2.5rem;font-size:32px;font-weight:700;margin:0;padding:0;text-decoration:none}body .container nav{background-color:var(--colour-blue);-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;display:none}body .container nav ul{margin:1rem 0}body .container nav ul li{display:inline-block;margin-right:1rem}body .container nav a{color:var(--colour-white);text-decoration:none}@media (min-width:768px){body .container nav{display:initial}}body .container p.info-switches{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-ms-grid;display:grid;gap:0.25rem;-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;-ms-grid-row:3;grid-row:3;-ms-grid-columns:auto (-webkit-max-content)[2];-ms-grid-columns:auto (max-content)[2];grid-template-columns:auto repeat(2,-webkit-max-content);grid-template-columns:auto repeat(2,max-content);text-align:right}body .container p.info-switches [role=switch]{display:-ms-inline-grid;display:inline-grid;border:1px solid #2e51a1;background-color:#d8d8d8;border-radius:0.75rem;height:1.5rem;width:3rem;-webkit-transition:all 500ms;transition:all 500ms}body .container p.info-switches [role=switch]>span{display:inline-block;background-color:white;border-radius:50%;margin:2%;width:calc(1.5rem - 2%);-webkit-transition:all 500ms;transition:all 500ms}body .container p.info-switches [role=switch][aria-checked=true]{background-color:#2e51a1}body .container p.info-switches [role=switch][aria-checked=true]>span{margin-left:calc(1.5rem - 5%)}body .container p.info-switches label{text-align:left}body .container main{display:block;grid-column:1/-1;-ms-grid-row:4;grid-row:4}@media (max-width:768px){body .container main{-ms-grid-row:3;grid-row:3;padding:0}}@supports (grid-area:auto){body .container main{display:grid;grid-template-columns:1rem repeat(2,auto) 1rem}@media (min-width:768px){body .container main{grid-template-columns:auto repeat(2,22rem) auto}}}body .container main h1,body .container main h2,body .container main h3,body .container main h4,body .container main h5,body .container main h6{-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4}body .container main article{-ms-grid-column:2;-ms-grid-column-span:2;grid-column:2/4;margin-top:2rem;min-width:0}body .container main article.status-deprecated{display:none}body .container main article .tab-group,body .container main article tabset{margin:2rem 0 1rem 0}body .container main article .tab-group [role=tablist],body .container main article tabset [role=tablist]{display:-webkit-box;display:-ms-flexbox;display:flex;margin:0;padding:0}body .container main article .tab-group [role=tablist] li.separator,body .container main article tabset [role=tablist] li.separator{border-bottom:1px solid #7f7f7f;display:inline-block;margin:0.45rem 0 0 0;width:100%}body .container main article .tab-group [role=tablist] li[role=tab],body .container main article tabset [role=tablist] li[role=tab]{background-color:#FFF;border-left:1px solid #7f7f7f;border-right:1px solid #7f7f7f;border-radius:0.5rem 0.5rem 0 0;border-top:1px solid #7f7f7f;cursor:pointer;display:inline;margin:0;padding:1rem 1.5rem 0.14rem 1.5rem;z-index:2}body .container main article .tab-group [role=tablist] li[role=tab]:last-of-type,body .container main article tabset [role=tablist] li[role=tab]:last-of-type{border-right:1px solid #7f7f7f}body .container main article .tab-group [role=tablist] li[role=tab]:not(.selected),body .container main article tabset [role=tablist] li[role=tab]:not(.selected){background-color:#f0f0f0;border-bottom:1px solid #7f7f7f}body .container main article .tab-group [role=tablist] li[role=tab] span,body .container main article tabset [role=tablist] li[role=tab] span{display:block;margin:0 0 0.5rem 0}body .container main article .tab-group .tab-hidden,body .container main article tabset .tab-hidden{display:none}body .container main article .tab-group [role=tabpanel],body .container main article tabset [role=tabpanel]{background-color:#FFF;border:1px solid #7f7f7f;border-top:none;padding:1rem;z-index:1}body .container main article .tab-group [role=tabpanel]:not(.open),body .container main article tabset [role=tabpanel]:not(.open){display:none}body .container main article .tab-group pre,body .container main article tabset pre{background-color:var(--colour-black-5);font-size:0.8rem}body .container main article .tab-group pre code:not(.inline),body .container main article tabset pre code:not(.inline){display:block;width:100%}body .container main article p.switch{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-ms-grid;display:grid;grid-gap:0.5rem;-ms-grid-columns:-webkit-max-content auto;-ms-grid-columns:max-content auto;grid-template-columns:-webkit-max-content auto;grid-template-columns:max-content auto}body .container main article p.switch [role=switch]{display:-ms-inline-grid;display:inline-grid;border:1px solid #2e51a1;background-color:#d8d8d8;border-radius:0.75rem;height:1.5rem;width:3rem;-webkit-transition:all 500ms;transition:all 500ms}body .container main article p.switch [role=switch]>span{display:inline-block;background-color:white;border-radius:50%;margin:2%;width:calc(1.5rem - 2%);-webkit-transition:all 500ms;transition:all 500ms}body .container main article p.switch [role=switch][aria-checked=true]{background-color:#2e51a1}body .container main article p.switch [role=switch][aria-checked=true]>span{margin-left:calc(1.5rem - 5%)} \ No newline at end of file +/* ---------------------------------------------------------- + * Variables + */ +/* Core Code + + This file is generates _core.scss using information in ../pg/_config.pug. + Please make your changes in your _config.pug file so that they are not + overwritten. +*/ +:root { + --colour-blue: #2e51a1; + --colour-blue-l: #5c7abf; + --colour-blue-xl: #b2c3ec; + --colour-blue-d: #133176; + --colour-blue-xd: #031235; + --colour-grey: #7f7f7f; + --colour-grey-l: #b2b2b2; + --colour-grey-xl: #d8d8d8; + --colour-grey-xxl: #f0f0f0; + --colour-white: #fff; + --colour-page: #fff; + --colour-light: #fff; + --colour-grey-d: #4c4c4c; + --colour-grey-xd: #4c4c4c; + --colour-black: #000; + --colour-dark: #000; +} + +h1[class^=status]::after, h2[class^=status]::after, span[class^=status]::after { + border-radius: 50%; + border: 1px solid #CCC; + content: " "; + display: inline-block; + height: 1.5rem; + margin-left: 0.5rem; + position: relative; + top: 2px; + width: 1.5rem; +} + +.status-not-started::after { + background-color: transparent; +} + +.status-in-progress::after { + background-color: #f0b031; +} + +.status-complete::after { + background-color: #2e51a1; +} + +.status-deprecated::after { + background-color: #da2c5b; +} + +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*=language-], +pre[class*=language-] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*=language-]::-moz-selection, pre[class*=language-] ::-moz-selection, +code[class*=language-]::-moz-selection, code[class*=language-] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*=language-]::-moz-selection, pre[class*=language-] ::-moz-selection, code[class*=language-]::-moz-selection, code[class*=language-] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*=language-]::selection, pre[class*=language-] ::selection, +code[class*=language-]::selection, code[class*=language-] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*=language-], + pre[class*=language-] { + text-shadow: none; + } +} +/* Code blocks */ +pre[class*=language-] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; +} + +:not(pre) > code[class*=language-], +pre[class*=language-] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*=language-] { + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.token.namespace { + opacity: 0.7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + /* This background color was intended by the author of this theme. */ + background: hsla(0, 0%, 100%, 0.5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +div.code-toolbar { + position: relative; +} + +div.code-toolbar > .toolbar { + position: absolute; + z-index: 10; + top: 0.3em; + right: 0.2em; + -webkit-transition: opacity 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +div.code-toolbar:hover > .toolbar { + opacity: 1; +} + +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { + display: inline-block; +} + +div.code-toolbar > .toolbar > .toolbar-item > a { + cursor: pointer; +} + +div.code-toolbar > .toolbar > .toolbar-item > button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { + color: #bbb; + font-size: 0.8em; + padding: 0 0.5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + -webkit-box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); + border-radius: 0.5em; +} + +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { + color: inherit; + text-decoration: none; +} + +pre[class*=language-].line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre[class*=language-].line-numbers > code { + position: relative; + white-space: inherit; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.line-numbers-rows > span { + display: block; + counter-increment: linenumber; +} + +.line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; +} + +/* Position Options + - top / block-start + - right / inline-end + - bottom / block-end + - left / inline-start +*/ +#copystatus { + left: 50%; + position: absolute; + z-index: 100; +} +#copystatus div { + border-radius: 1rem; + border: 1px solid green; + left: -50%; + padding: 1rem; + position: relative; + white-space: nowrap; +} +#copystatus div::after { + clear: both; + content: " "; + display: block; +} +#copystatus div.succeeded { + background-color: white; + border-color: black; + color: black; +} +#copystatus div.failed { + background-color: white; + border-color: #f00; + color: #f00; +} + +color-samples { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + gap: 1rem; + margin-bottom: 1rem; +} +@media (max-width: 992px) { + color-samples { + display: -ms-grid; + display: grid; + -ms-grid-columns: (1fr)[2]; + grid-template-columns: repeat(2, 1fr); + max-width: 100%; + width: 100%; + } +} +@media (max-width: 576px) { + color-samples { + -ms-grid-columns: auto; + grid-template-columns: auto; + width: 100%; + max-width: 100%; + } +} +color-samples color-sample { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 0.5rem; + border: 1px solid #CCC; + display: -ms-grid; + display: grid; + font-family: inherit; + gap: 0.5rem; + grid-template-areas: "name name name hex hex hex" "name name name rgb rgb rgb" "acc acc acc acc acc acc" "lighter lighter lighter darker darker darker" "notes notes notes notes notes notes"; + -ms-grid-columns: 1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr 0.5rem 1fr; + grid-template-columns: repeat(6, 1fr); + -ms-grid-rows: 1.5rem 0.5rem 1.5rem 0.5rem 10rem 0.5rem max-content 0.5rem max-content 0.5rem max-content; + grid-template-rows: repeat(2, 1.5rem) 10rem repeat(3, -webkit-max-content); + grid-template-rows: repeat(2, 1.5rem) 10rem repeat(3, max-content); + padding: 1rem; + width: 20rem; + max-width: 318px; +} +@media (max-width: 992px) { + color-samples color-sample { + width: 100%; + max-width: 100%; + } +} +color-samples color-sample name { + -ms-grid-row: 1; + -ms-grid-row-span: 3; + -ms-grid-column: 1; + -ms-grid-column-span: 5; + -ms-grid-row-align: start; + align-self: start; + font-size: 1.25rem; + grid-area: name; +} +color-samples color-sample name span { + cursor: pointer; +} +color-samples color-sample rgb { + -ms-grid-row: 3; + -ms-grid-column: 7; + -ms-grid-column-span: 5; + grid-area: rgb; + white-space: nowrap; +} +color-samples color-sample hex { + -ms-grid-row: 1; + -ms-grid-column: 7; + -ms-grid-column-span: 5; + grid-area: hex; + white-space: nowrap; +} +color-samples color-sample > accessibility { + border-bottom: 1px solid #ccc; + border-top: 1px solid #ccc; +} +color-samples color-sample accessibility { + -ms-grid-row: 5; + -ms-grid-column: 1; + -ms-grid-column-span: 11; + grid-area: acc; + -ms-grid-row: 3; + grid-row: 3; + padding: 0.5rem 0; + display: -ms-grid; + display: grid; + gap: 0.5rem; + -ms-grid-columns: (1fr)[3]; + grid-template-columns: repeat(3, 1fr); + -ms-grid-rows: (-webkit-max-content)[3]; + -ms-grid-rows: (max-content)[3]; + grid-template-rows: repeat(3, -webkit-max-content); + grid-template-rows: repeat(3, max-content); +} +color-samples color-sample accessibility .result { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 0.5rem; + display: -ms-grid; + display: grid; + -ms-grid-columns: (1fr)[2]; + grid-template-columns: repeat(2, 1fr); + border: 1px solid #ccc; + padding: 0 1rem; + text-align: center; +} +color-samples color-sample accessibility .result.accwaa, color-samples color-sample accessibility .result.accwaaa { + background-color: white; + color: black; +} +color-samples color-sample accessibility .result.accbaa, color-samples color-sample accessibility .result.accbaaa { + background-color: black; + color: white; +} +color-samples color-sample accessibility .result span:nth-child(2) { + font-size: 2rem; +} +color-samples color-sample accessibility .aa, color-samples color-sample accessibility .aaa { + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + display: block; + font-size: 0.75rem; +} +color-samples color-sample accessibility .acchb { + -ms-grid-column: 2; + grid-column: 2; +} +color-samples color-sample accessibility .acchb, color-samples color-sample accessibility .acchw { + display: -ms-grid; + display: grid; + grid-tempate-columns: auto; + -ms-grid-rows: (-webkit-max-content)[2]; + -ms-grid-rows: (max-content)[2]; + grid-template-rows: repeat(2, -webkit-max-content); + grid-template-rows: repeat(2, max-content); + -ms-grid-row-align: start; + align-self: start; + text-align: center; + padding: 0; +} +color-samples color-sample accessibility .acchb span, color-samples color-sample accessibility .acchw span { + -ms-grid-row: 1; + grid-row: 1; + grid-column: 1/-1; + font-size: 0.9rem; +} +color-samples color-sample accessibility .acchb small, color-samples color-sample accessibility .acchw small { + text-align: center; + -ms-grid-row: 2; + grid-row: 2; + grid-column: 1/-1; + font-size: 0.75rem; +} +color-samples color-sample sample-block { + -ms-grid-row-align: start; + align-self: start; + -ms-grid-column-span: 3; + grid-column: span 3; + -ms-grid-row: 4; + grid-row: 4; +} +color-samples color-sample sample-block color-pill { + display: -ms-grid; + display: grid; + grid-gap: 0.5rem; + -ms-grid-columns: 20px -webkit-max-content auto; + -ms-grid-columns: 20px max-content auto; + grid-template-columns: 20px -webkit-max-content auto; + grid-template-columns: 20px max-content auto; +} +color-samples color-sample sample-block color-pill :nth-child(1) { + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + border-radius: 5px; + border: 1px solid #CCC; + display: inline-block; + height: 10px; + width: 20px; +} +color-samples color-sample sample-block color-pill span { + cursor: pointer; +} +color-samples color-sample sample-block color-pill span .tooltip-tc { + padding: 0.5rem; + width: 20rem; + max-width: 318px; + height: 10.5rem; + display: -ms-grid; + display: grid; + gap: 0.5rem; + -ms-grid-columns: (1fr)[3]; + grid-template-columns: repeat(3, 1fr); + -ms-grid-rows: (-webkit-max-content)[3]; + -ms-grid-rows: (max-content)[3]; + grid-template-rows: repeat(3, -webkit-max-content); + grid-template-rows: repeat(3, max-content); +} +color-samples color-sample sample-block color-pill span .tooltip-tc .result { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-radius: 0.5rem; + display: -ms-grid; + display: grid; + -ms-grid-columns: (1fr)[2]; + grid-template-columns: repeat(2, 1fr); + border: 1px solid #ccc; + padding: 0 1rem; + text-align: center; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .result.accwaa, color-samples color-sample sample-block color-pill span .tooltip-tc .result.accwaaa { + background-color: white; + color: black; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .result.accbaa, color-samples color-sample sample-block color-pill span .tooltip-tc .result.accbaaa { + background-color: black; + color: white; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .result span { + border: none; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .result span:nth-child(2) { + font-size: 2rem; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .aa, color-samples color-sample sample-block color-pill span .tooltip-tc .aaa { + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; + display: block; + font-size: 0.75rem; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .acchb { + -ms-grid-column: 2; + grid-column: 2; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .acchb, color-samples color-sample sample-block color-pill span .tooltip-tc .acchw { + border: none; + display: block; + width: 100%; + -ms-grid-row-align: stretch; + -ms-grid-column-align: stretch; + place-self: stretch; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span, color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span { + border: none; + font-size: 0.9rem; + width: 100%; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span::after, color-samples color-sample sample-block color-pill span .tooltip-tc .acchb span::before, color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span::after, color-samples color-sample sample-block color-pill span .tooltip-tc .acchw span::before { + display: none; +} +color-samples color-sample sample-block color-pill span .tooltip-tc .acchb small, color-samples color-sample sample-block color-pill span .tooltip-tc .acchw small { + font-size: 0.75rem; + text-align: center; +} +color-samples color-sample notes { + border-top: 1px solid #ccc; + grid-column: 1/-1; + padding-top: 0.5rem; +} + +tooltip { + background: #fff; + border-radius: 0.5rem; + color: #000; + display: none; + -webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15)); + filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.15)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.15)); + font-size: 1rem; + font-weight: 400; + inline-size: -webkit-max-content; + inline-size: -moz-max-content; + inline-size: max-content; + line-height: initial; + margin: 0; + max-inline-size: 25rem; + opacity: 0; + padding: 0.75rem 1.5rem; + pointer-events: none; + position: absolute; + text-align: start; + -webkit-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); + -ms-transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); + transform: translate(var(--tooltip-x, 0)) translateY(var(--tooltip-y, 0)); + -webkit-transition: opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: opacity 0.2s ease, -webkit-transform 0.2s ease; + transition: opacity 0.2s ease, transform 0.2s ease; + transition: opacity 0.2s ease, transform 0.2s ease, -webkit-transform 0.2s ease; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + will-change: filter; + z-index: 10; +} +tooltip::before { + clip-path: inset(50%); + clip: rect(1px, 1px, 1px, 1px); + content: "; Has tooltip: "; + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +tooltip::after { + background: #fff; + content: ""; + inset: 0; + -webkit-mask: var(--tooltip-pointer); + mask: var(--tooltip-pointer); + position: absolute; + z-index: -1; +} +tooltip:is([tip-position=top], +[tip-position=block-start], +:not([tip-position]), +[tip-position=bottom], +[tip-position=block-end]) { + text-align: center; +} +tooltip:is([tip-position=top], +[tip-position=block-start], +:not([tip-position])) { + inset-inline-start: 50%; + inset-block-end: calc(100% + 0.75rem + 1rem); + --tooltip-x: calc(50% * -1); +} +tooltip:is([tip-position=top], +[tip-position=block-start], +:not([tip-position]))::after { + --tooltip-pointer: conic-gradient(from -30deg at bottom, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) bottom/100% 50% no-repeat; + inset-block-end: -1rem; + -webkit-border-after: 1rem solid transparent; + border-block-end: 1rem solid transparent; +} +tooltip:is([tip-position=right], +[tip-position=inline-end]) { + inset-inline-start: calc(100% + 1.5rem + 1rem); + inset-block-end: 50%; + --tooltip-y: 50%; +} +tooltip:is([tip-position=right], +[tip-position=inline-end])::after { + --tooltip-pointer: conic-gradient(from 60deg at left, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) left/50% 100% no-repeat; + inset-inline-start: -1rem; + -webkit-border-start: 1rem solid transparent; + border-inline-start: 1rem solid transparent; +} +tooltip:is([tip-position=bottom], +[tip-position=block-end]) { + inset-inline-start: 50%; + inset-block-start: calc(100% + 0.75rem + 1rem); + --tooltip-x: calc(50% * -1); +} +tooltip:is([tip-position=bottom], +[tip-position=block-end])::after { + --tooltip-pointer: conic-gradient(from 150deg at top, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) top/100% 50% no-repeat; + inset-block-start: -1rem; + -webkit-border-before: 1rem solid transparent; + border-block-start: 1rem solid transparent; +} +tooltip:is([tip-position=left], +[tip-position=inline-start]) { + inset-inline-end: calc(100% + 1.5rem + 1rem); + inset-block-end: 50%; + --tooltip-y: 50%; +} +tooltip:is([tip-position=left], +[tip-position=inline-start])::after { + --tooltip-pointer: conic-gradient(from -120deg at right, rgba(0, 0, 0, 0), #000 1deg 60deg, rgba(0, 0, 0, 0) 61deg) right/50% 100% no-repeat; + inset-inline-end: -1rem; + -webkit-border-end: 1rem solid transparent; + border-inline-end: 1rem solid transparent; +} +@media (prefers-color-scheme: dark) { + tooltip { + background: #1f2127; + color: #fff; + -webkit-filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5)); + filter: drop-shadow(0 3px 3px hsla(0, 0%, 0%, 0.5)) drop-shadow(0 12px 12px hsla(0, 0%, 0%, 0.5)); + } + tooltip::after { + background: #1f2127; + } +} + +:has(> tool-tip) { + position: relative; +} +:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip { + display: block; + opacity: 1; + -webkit-transition-delay: 300ms; + transition-delay: 300ms; +} + +@media (prefers-reduced-motion: no-preference) { + :has(> tool-tip:is([tip-position=top], [tip-position=block-start], :not([tip-position]))):not(:hover):not(:active) tool-tip { + --tooltip-y: 3px; + } + :has(> tool-tip:is([tip-position=right], [tip-position=inline-end])):not(:hover):not(:active) tool-tip { + --tooltip-x: calc(-1 * -3px * -1); + } + :has(> tool-tip:is([tip-position=bottom], [tip-position=block-end])):not(:hover):not(:active) tool-tip { + --tooltip-y: -3px; + } + :has(> tool-tip:is([tip-position=left], [tip-position=inline-start])):not(:hover):not(:active) tool-tip { + --tooltip-x: calc(-1 * 3px * -1); + } +} +sticky-note-wrapper { + -webkit-box-sizing: border-box; + box-sizing: border-box; + border: 1px solid transparent; + border-radius: 50%; + display: inline-block; + height: 0.5rem; + position: relative; + width: 0.5rem; +} +sticky-note-wrapper * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +sticky-note-wrapper sticky-note { + cursor: -webkit-grab; + cursor: grab; + display: -ms-grid; + display: grid; + float: left; + font-size: 1rem; + height: 13rem; + left: 0; + place-items: stretch; + position: absolute; + top: 0; + width: 13rem; + z-index: 100; +} +sticky-note-wrapper sticky-note:active { + cursor: -webkit-grabbing; + cursor: grabbing; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +sticky-note-wrapper sticky-note.right { + float: right; +} +sticky-note-wrapper sticky-note > div { + -ms-grid-row: 1; + grid-row: 1; + -ms-grid-column: 1; + grid-column: 1; +} +sticky-note-wrapper sticky-note > div:nth-child(1) { + background-color: rgba(0, 0, 0, 0.25); + -webkit-box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5); + box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5); + display: -ms-grid; + display: grid; + margin: 2rem 1rem 0.25rem 0.36rem; + width: calc(100% - 1rem); +} +sticky-note-wrapper sticky-note > div:nth-child(2) { + clip-path: url(#stickyClip); + display: -ms-grid; + display: grid; + font-family: "Kalam", cursive; + font-style: 1rem; + font-weight: 300; + line-height: 1.25rem; + padding: 1rem; + place-items: center; + text-align: center; +} +sticky-note-wrapper sticky-note > div:nth-child(2) > * { + font-family: "Kalam", cursive !important; + font-style: normal !important; + font-weight: 300 !important; +} +@media screen and (max-width: 1024px) { + sticky-note-wrapper sticky-note > div:nth-child(2) { + max-width: 13rem; + min-width: 13rem; + width: 1rem; + } +} +@media screen and (max-width: 768px) { + sticky-note-wrapper sticky-note > div:nth-child(2) { + font-size: 1.75rem; + max-width: 21rem; + min-height: 21rem; + } +} +@media screen and (max-width: 640px) { + sticky-note-wrapper sticky-note > div:nth-child(2) { + font-size: 2.5rem; + max-width: 26rem; + min-height: 26rem; + } +} +sticky-note-wrapper sticky-note > div:nth-child(2) { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(255, 255, 221.2)), color-stop(2%, #ffffd3), color-stop(12%, #ffffd3), color-stop(75%, rgb(255, 255, 200.8)), to(rgb(255, 255, 185.5))); + background: linear-gradient(180deg, rgb(255, 255, 221.2) 0%, #ffffd3 2%, #ffffd3 12%, rgb(255, 255, 200.8) 75%, rgb(255, 255, 185.5) 100%); +} +sticky-note-wrapper sticky-note.blue > div:nth-child(2) { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(156.5265625, 220.9484375, 235.6734375)), color-stop(2%, #94daea), color-stop(12%, #94daea), color-stop(75%, rgb(139.4734375, 215.0515625, 232.3265625)), to(rgb(126.68359375, 210.62890625, 229.81640625))); + background: linear-gradient(180deg, rgb(156.5265625, 220.9484375, 235.6734375) 0%, #94daea 2%, #94daea 12%, rgb(139.4734375, 215.0515625, 232.3265625) 75%, rgb(126.68359375, 210.62890625, 229.81640625) 100%); +} +sticky-note-wrapper sticky-note.pink > div:nth-child(2) { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(250.3493150685, 123.8506849315, 147.104109589)), color-stop(2%, #fa728b), color-stop(12%, #fa728b), color-stop(75%, rgb(249.6506849315, 104.1493150685, 130.895890411)), to(rgb(249.1267123288, 89.3732876712, 118.7397260274))); + background: linear-gradient(180deg, rgb(250.3493150685, 123.8506849315, 147.104109589) 0%, #fa728b 2%, #fa728b 12%, rgb(249.6506849315, 104.1493150685, 130.895890411) 75%, rgb(249.1267123288, 89.3732876712, 118.7397260274) 100%); +} +sticky-note-wrapper sticky-note.green > div:nth-child(2) { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(196.6333333333, 251.5666666667, 200.925)), color-stop(2%, #bbfbc0), color-stop(12%, #bbfbc0), color-stop(75%, rgb(177.3666666667, 250.4333333333, 183.075)), to(rgb(162.9166666667, 249.5833333333, 169.6875))); + background: linear-gradient(180deg, rgb(196.6333333333, 251.5666666667, 200.925) 0%, #bbfbc0 2%, #bbfbc0 12%, rgb(177.3666666667, 250.4333333333, 183.075) 75%, rgb(162.9166666667, 249.5833333333, 169.6875) 100%); +} +sticky-note-wrapper:has(sticky-note:hover) { + background-color: #ffffd3; + border: 1px solid black; +} +sticky-note-wrapper:has(sticky-note.yellow:hover) { + background-color: #ffffd3; +} +sticky-note-wrapper:has(sticky-note.blue:hover) { + background-color: #94daea; +} +sticky-note-wrapper:has(sticky-note.pink:hover) { + background-color: #fa728b; +} +sticky-note-wrapper:has(sticky-note.green:hover) { + background-color: #bbfbc0; +} + +div.status-report p.heading, div.status-report td[colspan="2"] { + font-size: 1.125rem; + font-weight: bolder !important; + grid-column: 1/-1; + margin: 2rem 0 0.5rem 0; + padding-top: 1.5rem !important; +} +div.status-report td:not([colspan="2"]) span { + display: -ms-grid; + display: grid; + -ms-grid-columns: auto 1rem; + grid-template-columns: auto 1rem; + margin: 0 1rem 0 0; +} +div.status-report td:not([colspan="2"]) span span[class^=status]::after { + height: 1rem !important; + width: 1rem !important; + margin-right: 1rem; +} +div.status-report td:not([colspan="2"]) a { + margin: 0 1rem 0 0; +} +div.status-report td:not([colspan="2"]).indent a { + margin: 0 1rem 0 1.5rem; +} + +* { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-family: Helvetica, Arial, sans-serif; + font-size: 14pt; +} +@media (max-width: 768px) { + html { + font-size: 16pt; + } +} +html.show-breakpoints body::before, html.show-breakpoints body::after { + background-color: #555; + color: white; + content: "bigger than extra large"; + display: -ms-grid; + display: grid; + font-family: sans-serif; + font-size: 25px; + -ms-grid-columns: auto; + grid-template-columns: auto; + padding: 25px; + place-content: center; +} +@media (max-width: 1200px) { + html.show-breakpoints body::before, html.show-breakpoints body::after { + content: "extra large"; + } +} +@media (max-width: 992px) { + html.show-breakpoints body::before, html.show-breakpoints body::after { + content: "large"; + } +} +@media (max-width: 768px) { + html.show-breakpoints body::before, html.show-breakpoints body::after { + content: "medium"; + } +} +@media (max-width: 576px) { + html.show-breakpoints body::before, html.show-breakpoints body::after { + content: "small"; + } +} + +article[data-status=deprecated]:not(.show-deprecated) { + display: none; +} + +body { + margin: 0; + padding: 0; +} +body a.skip { + position: absolute; + left: -9999px; +} +body .container { + display: -ms-grid; + display: grid; + -ms-grid-columns: auto (22rem)[2] auto; + grid-template-columns: auto repeat(2, 22rem) auto; + margin: 0 auto; + width: 100vw; +} +body .container header { + display: -ms-grid; + display: grid; + -ms-grid-rows: 1.75rem 3.5rem; + grid-template-rows: 1.75rem 3.5rem; + -ms-grid-column: 2; + -ms-grid-column-span: 2; + grid-column: 2/4; + overflow: hidden; +} +body .container header svg { + grid-column: 1/-1; + grid-row: 1/-1; + -ms-grid-row-align: stretch; + -ms-grid-column-align: stretch; + place-self: stretch; +} +body .container header svg text { + -webkit-transform: translate(-1rem, 7.25rem); + -ms-transform: translate(-1rem, 7.25rem); + transform: translate(-1rem, 7.25rem); + font-size: 10rem; + font-weight: 1000; + font-family: sans-serif; + fill: var(--colour-grey-xxl); +} +body .container header > div { + -ms-grid-row: 2; + grid-row: 2; + grid-column: 1/-1; + display: -ms-grid; + display: grid; + grid-column-gap: 1rem; + -ms-grid-columns: auto -webkit-max-content -webkit-max-content; + -ms-grid-columns: auto max-content max-content; + grid-template-columns: auto -webkit-max-content -webkit-max-content; + grid-template-columns: auto max-content max-content; +} +body .container header > div .header-title h1 { + margin: 0; + padding: 0 1rem; +} +body .container header > div .header-title h1 a, body .container header > div .header-title h1 a:visited { + border-bottom: none; + color: var(--colour-black); + font-family: sans-serif; + font-size: 2.5rem; + font-size: 32px; + font-weight: 700; + margin: 0; + padding: 0; + text-decoration: none; +} +body .container nav { + background-color: var(--colour-blue); + -ms-grid-column: 2; + -ms-grid-column-span: 2; + grid-column: 2/4; + display: none; +} +body .container nav ul { + margin: 1rem 0; +} +body .container nav ul li { + display: inline-block; + margin-right: 1rem; +} +body .container nav a { + color: var(--colour-white); + text-decoration: none; +} +@media (min-width: 768px) { + body .container nav { + display: initial; + } +} +body .container p.info-switches { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -ms-grid; + display: grid; + gap: 0.25rem; + -ms-grid-column: 2; + -ms-grid-column-span: 2; + grid-column: 2/4; + -ms-grid-row: 3; + grid-row: 3; + -ms-grid-columns: auto (-webkit-max-content)[2]; + -ms-grid-columns: auto (max-content)[2]; + grid-template-columns: auto repeat(2, -webkit-max-content); + grid-template-columns: auto repeat(2, max-content); + text-align: right; +} +body .container p.info-switches [role=switch] { + display: -ms-inline-grid; + display: inline-grid; + border: 1px solid #2e51a1; + background-color: #d8d8d8; + border-radius: 0.75rem; + height: 1.5rem; + width: 3rem; + -webkit-transition: all 500ms; + transition: all 500ms; +} +body .container p.info-switches [role=switch] > span { + display: inline-block; + background-color: white; + border-radius: 50%; + margin: 2%; + width: calc(1.5rem - 2%); + -webkit-transition: all 500ms; + transition: all 500ms; +} +body .container p.info-switches [role=switch][aria-checked=true] { + background-color: #2e51a1; +} +body .container p.info-switches [role=switch][aria-checked=true] > span { + margin-left: calc(1.5rem - 5%); +} +body .container p.info-switches label { + text-align: left; +} +body .container main { + display: block; + grid-column: 1/-1; + -ms-grid-row: 4; + grid-row: 4; +} +@media (max-width: 768px) { + body .container main { + -ms-grid-row: 3; + grid-row: 3; + padding: 0; + } +} +@supports (grid-area: auto) { + body .container main { + display: grid; + grid-template-columns: 1rem repeat(2, auto) 1rem; + } + @media (min-width: 768px) { + body .container main { + grid-template-columns: auto repeat(2, 22rem) auto; + } + } +} +body .container main h1, body .container main h2, body .container main h3, body .container main h4, body .container main h5, body .container main h6 { + -ms-grid-column: 2; + -ms-grid-column-span: 2; + grid-column: 2/4; +} +body .container main article { + -ms-grid-column: 2; + -ms-grid-column-span: 2; + grid-column: 2/4; + margin-top: 2rem; + min-width: 0; +} +body .container main article.status-deprecated { + display: none; +} +body .container main article tabset, body .container main article .tab-group { + margin: 2rem 0 1rem 0; +} +body .container main article tabset [role=tablist] li.selected, body .container main article .tab-group [role=tablist] li.selected { + background-color: var(--colour-green); + color: var(--colour-white); +} +body .container main article tabset > ul, +body .container main article tabset .tab-scroll > ul, body .container main article .tab-group > ul, +body .container main article .tab-group .tab-scroll > ul { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + margin: 0; + padding: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +body .container main article tabset > ul li.separator, +body .container main article tabset .tab-scroll > ul li.separator, body .container main article .tab-group > ul li.separator, +body .container main article .tab-group .tab-scroll > ul li.separator { + border-bottom: 1px solid #7f7f7f; + border-left: 1px solid #7f7f7f; + display: inline-block; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + margin: 0.45rem 0 0 0; + width: auto; +} +body .container main article tabset .tab-hidden, body .container main article .tab-group .tab-hidden { + display: none; +} +body .container main article tabset [role=tab], body .container main article .tab-group [role=tab] { + background-color: #FFF; + border-left: 1px solid #7f7f7f; + border-radius: 0.5rem 0.5rem 0 0; + border-top: 1px solid #7f7f7f; + cursor: pointer; + display: block; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + margin: 0; + max-width: 100vw; + overflow: hidden; + padding: 1rem 1.5rem 0.14rem 1.5rem; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: normal; + word-break: break-word; +} +body .container main article tabset [role=tab]:last-of-type, body .container main article .tab-group [role=tab]:last-of-type { + border-right: 1px solid #7f7f7f; +} +body .container main article tabset [role=tab]:not(.selected), body .container main article .tab-group [role=tab]:not(.selected) { + background-color: #f0f0f0; + border-bottom: 1px solid #7f7f7f; +} +body .container main article tabset [role=tab] span, body .container main article .tab-group [role=tab] span { + display: block; + margin: 0 0 0.5rem 0; +} +body .container main article tabset [role=tabpanel], body .container main article .tab-group [role=tabpanel] { + background-color: #FFF; + border: 1px solid #7f7f7f; + border-top: none; + padding: 1rem; + z-index: 1; +} +body .container main article tabset [role=tabpanel]:not(.open), body .container main article .tab-group [role=tabpanel]:not(.open) { + display: none; +} +body .container main article tabset [role=tabpanel] pre, body .container main article .tab-group [role=tabpanel] pre { + background-color: var(--colour-black-5); + font-size: 0.8rem; +} +body .container main article tabset [role=tabpanel] pre code:not(.inline), body .container main article .tab-group [role=tabpanel] pre code:not(.inline) { + display: block; + width: 100%; +} +body .container main article .tab-scroll { + width: 100%; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +body .container main article .tab-scroll::-webkit-scrollbar { + display: none; +} +body .container main article .tab-scroll > ul { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + min-width: 100%; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; +} +body .container main article .tab-scroll-wrapper { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +body .container main article .tab-scroll-wrapper::before, body .container main article .tab-scroll-wrapper::after { + content: ""; + position: absolute; + top: 0; + width: 2.5rem; + height: 100%; + pointer-events: none; + z-index: 2; + opacity: 0; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} +body .container main article .tab-scroll-wrapper::before { + background: radial-gradient(circle at left center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%); + border-top-right-radius: 2.5rem; + border-bottom-right-radius: 2.5rem; + left: 0; +} +body .container main article .tab-scroll-wrapper::after { + right: 0; + background: radial-gradient(circle at right center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%); + border-top-left-radius: 2.5rem; + border-bottom-left-radius: 2.5rem; +} +body .container main article .tab-scroll-wrapper.is-overflowing::before, body .container main article .tab-scroll-wrapper.is-overflowing::after { + opacity: 0; + -webkit-transition: opacity 0.15s ease-out; + transition: opacity 0.15s ease-out; + -webkit-transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1); + transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1); +} +body .container main article .tab-scroll-wrapper.is-overflowing.show-left::before { + opacity: 1; +} +body .container main article .tab-scroll-wrapper.is-overflowing.show-right::after { + opacity: 1; +} +body .container main article .tab-scroll-wrapper .tab-scroll-arrow { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: none; + height: 100%; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + position: absolute; + top: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: 2.5rem; + z-index: 3; +} +body .container main article .tab-scroll-wrapper .tab-scroll-arrow path { + fill: #7f7f7f; +} +body .container main article .tab-scroll-wrapper .tab-scroll-arrow.left { + left: 0; +} +body .container main article .tab-scroll-wrapper .tab-scroll-arrow.right { + right: 0; +} +body .container main article .tab-scroll-wrapper .tab-scroll-arrow.hidden { + display: none !important; + pointer-events: none; + visibility: hidden; +} +body .container main article .tab-scroll-wrapper.is-overflowing .tab-scroll-arrow { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +body .container main article p.switch { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + display: -ms-grid; + display: grid; + grid-gap: 0.5rem; + -ms-grid-columns: -webkit-max-content auto; + -ms-grid-columns: max-content auto; + grid-template-columns: -webkit-max-content auto; + grid-template-columns: max-content auto; +} +body .container main article p.switch [role=switch] { + display: -ms-inline-grid; + display: inline-grid; + border: 1px solid #2e51a1; + background-color: #d8d8d8; + border-radius: 0.75rem; + height: 1.5rem; + width: 3rem; + -webkit-transition: all 500ms; + transition: all 500ms; +} +body .container main article p.switch [role=switch] > span { + display: inline-block; + background-color: white; + border-radius: 50%; + margin: 2%; + width: calc(1.5rem - 2%); + -webkit-transition: all 500ms; + transition: all 500ms; +} +body .container main article p.switch [role=switch][aria-checked=true] { + background-color: #2e51a1; +} +body .container main article p.switch [role=switch][aria-checked=true] > span { + margin-left: calc(1.5rem - 5%); +} \ No newline at end of file diff --git a/public/patterns/core/tabs/index.html b/public/patterns/core/tabs/index.html index 9bb9f5b..b47664d 100644 --- a/public/patterns/core/tabs/index.html +++ b/public/patterns/core/tabs/index.html @@ -42,45 +42,70 @@
    tabset, .tab-group {
     	margin: 2rem 0 1rem 0;
     }
    -tabset [role=tablist], .tab-group [role=tablist] {
    +tabset [role=tablist] li.selected, .tab-group [role=tablist] li.selected {
    +	background-color: var(--colour-green);
    +	color: var(--colour-white);
    +}
    +tabset > ul,
    +tabset .tab-scroll > ul, .tab-group > ul,
    +.tab-group .tab-scroll > ul {
     	display: -webkit-box;
     	display: -ms-flexbox;
     	display: flex;
     	margin: 0;
     	padding: 0;
    +	-webkit-user-select: none;
    +	   -moz-user-select: none;
    +	    -ms-user-select: none;
    +	        user-select: none;
     }
    -tabset [role=tablist] li.separator, .tab-group [role=tablist] li.separator {
    +tabset > ul li.separator,
    +tabset .tab-scroll > ul li.separator, .tab-group > ul li.separator,
    +.tab-group .tab-scroll > ul li.separator {
     	border-bottom: 1px solid #7f7f7f;
    -	display: inline-block;
    -	margin: 0.45rem 0 0 0;
    -	width: 100%;
    -}
    -tabset [role=tablist] li[role=tab], .tab-group [role=tablist] li[role=tab] {
    -	background-color: #FFF;
     	border-left: 1px solid #7f7f7f;
    -	border-right: 1px solid #7f7f7f;
    -	border-radius: 0.5rem 0.5rem 0 0;
    -	border-top: 1px solid #7f7f7f;
    -	cursor: pointer;
    -	display: inline;
    -	margin: 0;
    -	padding: 1rem 1.5rem 0.14rem 1.5rem;
    -	z-index: 2;
    -}
    -tabset [role=tablist] li[role=tab]:last-of-type, .tab-group [role=tablist] li[role=tab]:last-of-type {
    -	border-right: 1px solid #7f7f7f;
    -}
    -tabset [role=tablist] li[role=tab]:not(.selected), .tab-group [role=tablist] li[role=tab]:not(.selected) {
    -	background-color: #f0f0f0;
    -	border-bottom: 1px solid #7f7f7f;
    -}
    -tabset [role=tablist] li[role=tab] span, .tab-group [role=tablist] li[role=tab] span {
    -	display: block;
    -	margin: 0 0 0.5rem 0;
    +	display: inline-block;
    +	-webkit-box-flex: 1;
    +	    -ms-flex: 1 1 auto;
    +	        flex: 1 1 auto;
    +	margin: 0.45rem 0 0 0;
    +	width: auto;
     }
     tabset .tab-hidden, .tab-group .tab-hidden {
     	display: none;
     }
    +tabset [role=tab], .tab-group [role=tab] {
    +	background-color: #FFF;
    +	border-left: 1px solid #7f7f7f;
    +	border-radius: 0.5rem 0.5rem 0 0;
    +	border-top: 1px solid #7f7f7f;
    +	cursor: pointer;
    +	display: block;
    +	-webkit-box-flex: 0;
    +	    -ms-flex: 0 0 auto;
    +	        flex: 0 0 auto;
    +	margin: 0;
    +	max-width: 100vw;
    +	overflow: hidden;
    +	padding: 1rem 1.5rem 0.14rem 1.5rem;
    +	-webkit-user-select: none;
    +	   -moz-user-select: none;
    +	    -ms-user-select: none;
    +	        user-select: none;
    +	white-space: normal;
    +	word-break: break-word;
    +}
    +tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type {
    +	border-right: 1px solid #7f7f7f;
    +}
    +tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) {
    +	background-color: #f0f0f0;
    +	border-bottom: 1px solid #7f7f7f;
    +}
    +tabset [role=tab] span, .tab-group [role=tab] span {
    +	display: block;
    +	margin: 0 0 0.5rem 0;
    +}
     tabset [role=tabpanel], .tab-group [role=tabpanel] {
     	background-color: #FFF;
     	border: 1px solid #7f7f7f;
    @@ -90,6 +115,112 @@ tabset [role=tabpanel], .tab-group [role=tabpanel] {
     }
     tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) {
     	display: none;
    +}
    +
    +.tab-scroll {
    +	width: 100%;
    +	overflow-x: auto;
    +	overflow-y: hidden;
    +	scrollbar-width: none;
    +	-ms-overflow-style: none;
    +	-webkit-user-select: none;
    +	   -moz-user-select: none;
    +	    -ms-user-select: none;
    +	        user-select: none;
    +}
    +.tab-scroll::-webkit-scrollbar {
    +	display: none;
    +}
    +.tab-scroll > ul {
    +	-ms-flex-wrap: nowrap;
    +	    flex-wrap: nowrap;
    +	min-width: 100%;
    +	width: -webkit-max-content;
    +	width: -moz-max-content;
    +	width: max-content;
    +}
    +
    +.tab-scroll-wrapper {
    +	position: relative;
    +	-webkit-user-select: none;
    +	   -moz-user-select: none;
    +	    -ms-user-select: none;
    +	        user-select: none;
    +}
    +.tab-scroll-wrapper::before, .tab-scroll-wrapper::after {
    +	content: "";
    +	position: absolute;
    +	top: 0;
    +	width: 2.5rem;
    +	height: 100%;
    +	pointer-events: none;
    +	z-index: 2;
    +	opacity: 0;
    +	-webkit-transition: opacity 0.2s ease;
    +	transition: opacity 0.2s ease;
    +}
    +.tab-scroll-wrapper::before {
    +	background: radial-gradient(circle at left center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%);
    +	border-top-right-radius: 2.5rem;
    +	border-bottom-right-radius: 2.5rem;
    +	left: 0;
    +}
    +.tab-scroll-wrapper::after {
    +	right: 0;
    +	background: radial-gradient(circle at right center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%);
    +	border-top-left-radius: 2.5rem;
    +	border-bottom-left-radius: 2.5rem;
    +}
    +.tab-scroll-wrapper.is-overflowing::before, .tab-scroll-wrapper.is-overflowing::after {
    +	opacity: 0;
    +	-webkit-transition: opacity 0.15s ease-out;
    +	transition: opacity 0.15s ease-out;
    +	-webkit-transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1);
    +	transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1);
    +}
    +.tab-scroll-wrapper.is-overflowing.show-left::before {
    +	opacity: 1;
    +}
    +.tab-scroll-wrapper.is-overflowing.show-right::after {
    +	opacity: 1;
    +}
    +.tab-scroll-wrapper .tab-scroll-arrow {
    +	-webkit-box-align: center;
    +	    -ms-flex-align: center;
    +	        align-items: center;
    +	cursor: pointer;
    +	display: none;
    +	height: 100%;
    +	-webkit-box-pack: center;
    +	    -ms-flex-pack: center;
    +	        justify-content: center;
    +	position: absolute;
    +	top: 0;
    +	-webkit-user-select: none;
    +	   -moz-user-select: none;
    +	    -ms-user-select: none;
    +	        user-select: none;
    +	width: 2.5rem;
    +	z-index: 3;
    +}
    +.tab-scroll-wrapper .tab-scroll-arrow path {
    +	fill: #7f7f7f;
    +}
    +.tab-scroll-wrapper .tab-scroll-arrow.left {
    +	left: 0;
    +}
    +.tab-scroll-wrapper .tab-scroll-arrow.right {
    +	right: 0;
    +}
    +.tab-scroll-wrapper .tab-scroll-arrow.hidden {
    +	display: none !important;
    +	pointer-events: none;
    +	visibility: hidden;
    +}
    +.tab-scroll-wrapper.is-overflowing .tab-scroll-arrow {
    +	display: -webkit-box;
    +	display: -ms-flexbox;
    +	display: flex;
     }

    Example

    @@ -98,70 +229,78 @@ tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) { // optional content block }; -
    //		DS2 core (c) 2024 Alexander McIlwraith 
    -//		Licensed under CC BY-SA 4.0 
    +        
    $tab-border: #7f7f7f !default;
     
    -$tab-border: #7f7f7f !default; 
    -$tab-panel-background-color: #FFF !default;
    -$tab-panel-top-border: #7f7f7f !default;
    -$tab-panel-top-border-width: 1px !default;
     $tab-selected: #FFF !default;
     $tab-selected-text: #000 !default;
    +
     $tab-notselected: #f0f0f0 !default;
     $tab-notselected-text: #000 !default;
     
     @mixin tabs {
    +
     	tabset, .tab-group {
    +
     		margin: 2rem 0 1rem 0;
     
    -		[role="tablist"] {
    +		[role="tablist"] li.selected {
    +			background-color: var(--colour-green);
    +			color: var(--colour-white);
    +			
    +		}
    +
    +		> ul,
    +		.tab-scroll > ul {
     			display: flex;
     			margin: 0;
     			padding: 0;
    +			user-select: none;
     
    -
    -			li {
    -				&.separator {	
    -					border-bottom: 1px solid $tab-border;
    -					display: inline-block;
    -					margin: .45rem 0 0 0;
    -					width: 100%;
    -				}
    -
    -				&[role="tab"] {
    -					background-color: $tab-selected;
    -					border-left: 1px solid $tab-border;
    -					border-right: 1px solid $tab-border;
    -					border-radius: .5rem .5rem 0 0;
    -					border-top: 1px solid $tab-border;
    -					cursor:pointer;
    -					display: inline;
    -					margin: 0;
    -					padding: 1rem 1.5rem .14rem 1.5rem;
    -					z-index: 2;
    -					
    -					&:last-of-type {
    -						border-right: 1px solid $tab-border;
    -					}
    -
    -					&:not(.selected) {
    -						background-color: $tab-notselected;
    -						border-bottom: 1px solid $tab-border;
    -									/// color
    -					}
    -
    -					span {
    -						display: block;
    -						margin: 0 0 .5rem 0;
    -					}
    -				}
    +			li.separator {
    +				border-bottom: 1px solid $tab-border;
    +				border-left: 1px solid $tab-border;
    +				display: inline-block;
    +				flex: 1 1 auto;
    +				margin: .45rem 0 0 0;
    +				width: auto;
     			}
     		}
     
     		.tab-hidden {
     			display: none;
     		}
    -		
    +
    +		[role="tab"] {
    +			background-color: $tab-selected;
    +			border-left: 1px solid $tab-border;
    +			border-radius: .5rem .5rem 0 0;
    +			border-top: 1px solid $tab-border;
    +			cursor: pointer;
    +			display: block;
    +			flex: 0 0 auto;
    +			margin: 0;
    +			max-width: 100vw;
    +			overflow: hidden;
    +			padding: 1rem 1.5rem .14rem 1.5rem;
    +			user-select: none;
    +			white-space: normal;
    +			word-break: break-word;
    +
    +			&:last-of-type {
    +				border-right: 1px solid $tab-border;
    +			}
    +
    +			&:not(.selected) {
    +				background-color: $tab-notselected;
    +				border-bottom: 1px solid $tab-border;
    +			}
    +
    +			span {
    +				display: block;
    +				margin: 0 0 .5rem 0;
    +			}
    +		}
    +
     		[role="tabpanel"] {
     			background-color: $tab-selected;
     			border: 1px solid $tab-border;
    @@ -172,8 +311,138 @@ $tab-notselected-text: #000 !default;
     			&:not(.open) {
     				display: none;
     			}
    +
    +			@content;
    +		}
    +	}
    +
    +	// scroller
    +	.tab-scroll {
    +		width: 100%;
    +		overflow-x: auto;
    +		overflow-y: hidden;
    +		scrollbar-width: none;
    +		-ms-overflow-style: none;
    +		user-select: none;
    +
    +		&::-webkit-scrollbar {
    +			display: none;
    +		}
    +
    +		> ul {
    +			flex-wrap: nowrap;
    +			min-width: 100%;
    +			width: max-content;
    +		}
    +	}
    +
    +	// wrapper (now owns the fade)
    +	.tab-scroll-wrapper {
    +		position: relative;
    +		user-select: none;
    +		$radial: 2.5rem;
    +		// edge fades (this is the fix)
    +		&::before,
    +		&::after {
    +			content: "";
    +			position: absolute;
    +			top: 0;
    +			width: 2.5rem;
    +			height: 100%;
    +			pointer-events: none;
    +			z-index: 2;
    +			opacity: 0; // hidden by default
    +			transition: opacity 0.2s ease;
    +		}
    +
    +		// left fade
    +		&::before {
    +			background: radial-gradient(
    +				circle at left center,
    +				rgba(255,255,255,1) 0%,
    +				rgba(255,255,255,0.9) 50%,
    +				rgba(255,255,255,0.5) 75%,
    +				rgba(255,255,255,0.25) 95%,
    +				transparent 100%
    +			);
    +			border-top-right-radius: $radial;
    +			border-bottom-right-radius: $radial;
    +			left: 0;
    +		}
    +
    +		// right fade
    +		&::after {
    +			right: 0;
    +				background: radial-gradient(
    +					circle at right center,
    +					rgba(255,255,255,1) 0%,
    +					rgba(255,255,255,0.9) 50%,
    +					rgba(255,255,255,0.5) 75%,
    +					rgba(255,255,255,0.25) 95%,
    +					transparent 100%
    +				);
    +				border-top-left-radius: $radial;
    +				border-bottom-left-radius: $radial;
    +		}
    +
    +		// show fade only when overflowing
    +		&.is-overflowing {
    +			&::before,
    +			&::after {
    +				opacity: 0;
    +				transition: opacity 0.15s ease-out;
    +				transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1);
    +			}
    +			
    +			&.show-left {
    +				&::before {
    +					opacity: 1;
    +				}
    +			}
    +			&.show-right {
    +				&::after {
    +					opacity: 1;
    +				}
    +			}
    +			
    +		}
    +
    +		// arrows
    +		.tab-scroll-arrow {
    +			align-items: center;
    +			cursor: pointer;
    +			display: none;
    +			height: 100%;
    +			justify-content: center;
    +			position: absolute;
    +			top: 0;
    +			user-select: none;
    +			width: 2.5rem;
    +			z-index: 3;
    +			path {
    +				fill: $tab-border;
    +			}
    +			&.left {
    +				left: 0;
    +			}
    +
    +			&.right {
    +				right: 0;
    +			}
    +
    +			&.hidden {
    +				display: none !important;
    +				pointer-events: none;
    +				visibility: hidden;
    +			}
    +		}
    +
    +		// only show arrows when overflow
    +		&.is-overflowing {
    +			.tab-scroll-arrow {
    +				display: flex;
    +			}
     		}
    -		@content;
     	}
     }
    @@ -181,9 +450,9 @@ $tab-notselected-text: #000 !default;

    Example

    import * as tabs from "./js/core/tabs/_tabs.js";
     tabs.init();
    -
    /*  DS2 core (c) 2024 Alexander McIlwraith 
    -	Released under Creative Commons Attribution-ShareAlike 4.0 International
    - */
    +        
    /* DS2 core (c) 2024-2026 Alexander McIlwraith
    +   Released under Creative Commons Attribution-ShareAlike 4.0 International
    +*/
     
     // create a pure JS mouse click event
     const click = new MouseEvent('click', {
    @@ -192,48 +461,55 @@ const click = new MouseEvent('click', {
     	cancelable: true
     });
     
    +// wait for an element to appear in the DOM
     const waitForElement = (selector) => {
    -    return new Promise(resolve => {
    -        if (document.querySelector(selector)) {
    -            return resolve(document.querySelector(selector));
    -        }
    +	return new Promise(resolve => {
    +		if (document.querySelector(selector)) {
    +			return resolve(document.querySelector(selector));
    +		}
    +		const observer = new MutationObserver(() => {
    +			if (document.querySelector(selector)) {
    +				observer.disconnect();
    +				resolve(document.querySelector(selector));
    +			}
    +		});
    +		observer.observe(document.body, {
    +			childList: true,
    +			subtree: true
    +		});
    +	});
    +};
     
    -        const observer = new MutationObserver(mutations => {
    -            if (document.querySelector(selector)) {
    -                observer.disconnect();
    -                resolve(document.querySelector(selector));
    -            }
    -        });
    -
    -        // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
    -        observer.observe(document.body, {
    -            childList: true,
    -            subtree: true
    -        });
    -    });
    -}
    +// Tab logic
    +const tabNamespace = "#tab:";
     
     const chooseTab = (tab) => {
    -	const siblings = Array.from(tab.parentNode.children);
    +	const siblings = Array.from(
    +		tab.closest('[role="tablist"]').querySelectorAll('[role="tab"]')
    +	);
     	siblings.forEach(sibling => sibling.classList.remove("selected"));
     	tab.classList.add("selected");
    -	
    -	const tabPanels = Array.from(tab.parentNode.parentNode.children)
    -	tabPanels.forEach(panel => panel.classList.remove("open"));
     
    +	const tabGroup = tab.closest("tabset, .tab-group");
    +	const tabPanels = Array.from(
    +		tabGroup.querySelectorAll('[role="tabpanel"]')
    +	);
    +	
    +	tabPanels.forEach(panel => panel.classList.remove("open"));
     	const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel");
     	document.getElementById(tabPanelId).classList.add("open");
    -}
    +};
     
    -let pushState = 0;
    +let pushStateCount = 0;
     let tabsetCount = 0;
     
    -export function init(container = document, spacer = true, args = {}) {
    +export function init(container = document, spacer = true) {
     	container.querySelectorAll(".tab-group, tabset").forEach(tabGroup => {
    -		if (tabGroup.querySelector("[role=tablist]") === null) {
    +
    +		if (tabGroup.querySelector('[role="tablist"]') === null) {
    +
     			if (tabGroup.getAttribute("id") == null) {
    -				tabGroup.setAttribute("id", "tab-group-" + tabsetCount);
    -				tabsetCount++;
    +				tabGroup.setAttribute("id", `tab-group-${tabsetCount++}`);
     			}
     
     			const tabgroup = tabGroup.getAttribute("id");
    @@ -241,24 +517,19 @@ export function init(container = document, spacer = true, args = {}) {
     
     			Array.from(tabGroup.children).forEach(child => {
     
    -				// is details? 
    -				let dtls = child.nodeName == "DETAILS" ? true : false;
    +				const isDetails = child.nodeName === "DETAILS";
    +				const tabLabel = isDetails ? child.querySelector("summary")?.innerHTML : child.getAttribute("tab") || child.getAttribute("data-tab");
     
    -				// get the tab text 
    -				let tab = dtls ? child.querySelector("summary").innerHTML : child.getAttribute("tab") || child.getAttribute("data-tab");
    +				if (tabLabel !== null) {
     
    -				// if the tab text is not blank 
    -				if (tab !== null) {
    -					const tabID = tab.replace(/\W+/g, "-").toLowerCase();
    -					
    +					const tabID = tabLabel.replace(/\W+/g, "-").toLowerCase();
    +					let tabPanel;
     
    -					// define the tab panel content
    -					let tabPanel = null;
    -					if (dtls) { 
    +					if (isDetails) {
     						tabPanel = child;
     						tabPanel.setAttribute("open", "");
     					} else {
    -						tabPanel = document.createElement('div');
    +						tabPanel = document.createElement("div");
     						tabPanel.appendChild(child.cloneNode(true));
     					}
     
    @@ -266,80 +537,225 @@ export function init(container = document, spacer = true, args = {}) {
     					tabPanel.className = tablist === "" ? "open" : "";
     					tabPanel.setAttribute("role", "tabpanel");
     					tabPanel.setAttribute("tabindex", "0");
    -					tabPanel.setAttribute("aria-labelledby", `tab-${tabgroup}-${tabID}`);
    +					tabPanel.setAttribute(
    +						"aria-labelledby",
    +						`tab-${tabgroup}-${tabID}`
    +					);
    +
     					child.parentNode.replaceChild(tabPanel, child);
    -					tablist += ``;
    +
    +					tablist += ``;
     				} else {
     					child.classList.add("tab-hidden");
     				}
     			});
     
    -			const ul = document.createElement('ul');
    +			const ul = document.createElement("ul");
     			ul.setAttribute("role", "tablist");
     			tabGroup.insertBefore(ul, tabGroup.firstChild);
    -			ul.innerHTML = spacer != true ? `${tablist}` : `${tablist}`;
     
    -			if ( tabGroup.hasAttribute("order") || tabGroup.hasAttribute("data-order") ) {
    -				let order = (tabGroup.getAttribute("order") || tabGroup.getAttribute("data-order")).split(",");
    +
    +			const wrapper = document.createElement("div");
    +			wrapper.className = "tab-scroll-wrapper";
    +
    +			const scroller = document.createElement("div");
    +			scroller.className = "tab-scroll";
    +
    +			const leftArrow = document.createElement("div");
    +			leftArrow.className = "tab-scroll-arrow left";
    +
    +			leftArrow.setAttribute("aria-hidden", "true");
    +
    +			leftArrow.innerHTML = `
    +				
    +					
    +				
    +			`;
    +
    +			const rightArrow = document.createElement("div");
    +			rightArrow.className = "tab-scroll-arrow right";
    +
    +			rightArrow.setAttribute("aria-hidden", "true");
    +
    +			rightArrow.innerHTML = `
    +				
    +					
    +				
    +			`;
    +
    +			ul.parentNode.insertBefore(wrapper, ul);
    +			wrapper.appendChild(scroller);
    +			wrapper.appendChild(leftArrow);
    +			wrapper.appendChild(rightArrow);
    +			scroller.appendChild(ul);
    +
    +			const updateScrollState = () => {
    +				const isOverflowing = scroller.scrollWidth > scroller.clientWidth;
    +
    +				wrapper.classList.toggle("is-overflowing", isOverflowing);
    +
    +				const atStart = scroller.scrollLeft <= 1;
    +				const atEnd = scroller.scrollLeft + scroller.clientWidth >= scroller.scrollWidth - 2;
    +
    +				leftArrow.classList.toggle("hidden", !isOverflowing || atStart);
    +				rightArrow.classList.toggle("hidden", !isOverflowing || atEnd);
    +				
    +				
    +    wrapper.classList.toggle("show-left", isOverflowing && !atStart);
    +    wrapper.classList.toggle("show-right", isOverflowing && !atEnd);
    +
    +			};
    +
    +			const scrollAmount = 15;   // smaller = smoother per frame
    +			const scrollInterval = 16; // ~60fps
    +
    +			let scrollTimer = null;
    +
    +			const startScrolling = (direction) => {
    +				if (scrollTimer) return;
    +
    +				let speed = 0.1;
    +
    +				scrollTimer = setInterval(() => {
    +					speed = Math.min(speed + 0.01, 5); // ramp up
    +					scroller.scrollBy({
    +						left: direction * scrollAmount * speed,
    +						behavior: "auto"
    +					});
    +				}, scrollInterval);
    +			};
    +
    +
    +			const stopScrolling = () => {
    +				clearInterval(scrollTimer);
    +				scrollTimer = null;
    +			};
    +			leftArrow.addEventListener("mousedown", () => startScrolling(-1));
    +			leftArrow.addEventListener("mouseup", stopScrolling);
    +			leftArrow.addEventListener("mouseleave", stopScrolling);
    +
    +			leftArrow.addEventListener("touchstart", () => startScrolling(-1));
    +			leftArrow.addEventListener("touchend", stopScrolling);
    +
    +			rightArrow.addEventListener("mousedown", () => startScrolling(1));
    +			rightArrow.addEventListener("mouseup", stopScrolling);
    +			rightArrow.addEventListener("mouseleave", stopScrolling);
    +
    +			rightArrow.addEventListener("touchstart", () => startScrolling(1));
    +			rightArrow.addEventListener("touchend", stopScrolling);
    +
    +			const ARROW_ZONE = 40;
    +
    +			wrapper.addEventListener("contextmenu", (e) => {
    +				const isOverflowing = wrapper.classList.contains("is-overflowing");
    +				if (!isOverflowing) return;
    +
    +				const rect = wrapper.getBoundingClientRect();
    +
    +				const isLeftZone = e.clientX < rect.left + ARROW_ZONE;
    +				const isRightZone = e.clientX > rect.right - ARROW_ZONE;
    +
    +				if (isLeftZone || isRightZone) {
    +					e.preventDefault();
    +				}
    +			});
    +
    +
    +			const scrollClickAmount = 150;
    +
    +			leftArrow.addEventListener("click", () => {
    +					scroller.scrollBy({ left: -scrollClickAmount, behavior: "smooth" });
    +			});
    +
    +			rightArrow.addEventListener("click", () => {
    +					scroller.scrollBy({ left: scrollClickAmount, behavior: "smooth" });
    +			});
    +
    +			scroller.addEventListener("scroll", updateScrollState);
    +			window.addEventListener("resize", updateScrollState);
    +
    +			updateScrollState();
    +			ul.innerHTML = spacer !== true ? tablist : `${tablist}`;
    +
    +			requestAnimationFrame(updateScrollState);
    +			setTimeout(updateScrollState, 50);
    +
    +			ul.innerHTML = spacer !== true ? tablist : `${tablist}`;
    +
    +			// Tab ordering
    +			if (tabGroup.hasAttribute("order") || tabGroup.hasAttribute("data-order")) {
    +
    +				const order = (
    +					tabGroup.getAttribute("order") ||
    +					tabGroup.getAttribute("data-order")
    +				).split(",");
     
     				const items = Array.from(ul.getElementsByTagName("li"));
    +
     				items.sort((a, b) => {
    -					console.log("here")
     					const aa = order.indexOf(a.textContent.trim());
     					const bb = order.indexOf(b.textContent.trim());
    -
    -					// Check if both items exist in orderArray
    -					if (aa === -1) return 1; // Move to the end if not found
    -					if (bb === -1) return -1; // Move to the end if not found
    -
    -					return aa - bb; // Sort based on the defined order
    +					if (aa === -1) return 1;
    +					if (bb === -1) return -1;
    +					return aa - bb;
     				});
     
    -				ul.innerHTML = '';
    +				ul.innerHTML = "";
     				items.forEach(item => ul.appendChild(item));
    +				chooseTab(items[0]);
     			}
     
    +			// Tab event handlers
     			tabGroup.querySelectorAll('[role="tab"]').forEach(tab => {
    +
     				tab.addEventListener("click", (evt) => {
    -					if (pushState == 0) {
    -						window.history.pushState({rand: Math.random(), pushState: pushState, tab: tab.parentNode.firstChild.getAttribute("id")}, "", `#${tab.parentNode.firstChild.getAttribute("id")}`);
    -						pushState++;
    -					}
    +
    +					const tabId = tab.getAttribute("id");
    +					const hash = `${tabNamespace}${tabId}`;
     
     					chooseTab(evt.currentTarget);
    -					window.history.pushState({rand: Math.random(), pushState: pushState, tab: tab.getAttribute("id")}, "", `#${tab.getAttribute("id")}`);
    -					pushState++;
    +
    +					window.history.pushState(
    +						{ tab: tabId },
    +						"",
    +						`${location.pathname}${location.search}${hash}`
    +					);
    +
    +					pushStateCount++;
     				});
     
     				tab.addEventListener("keypress", (e) => {
    -					e.preventDefault();
    -					if( e.which == 32 || e.which == 13 ) {
    +					if (e.which === 32 || e.which === 13) {
    +						e.preventDefault();
     						e.currentTarget.dispatchEvent(click);
     					}
    -				})
    +				});
     			});
    -			ul.querySelector("li").classList.add("selected");
    -		}
     
    -		if (document.location.hash != "" && document.location.hash.substring(0,5) == "#tab-") {
    -			waitForElement(document.location.hash).then((el) => {
    -				//el.scrollIntoView();
    -				el.focus();
    -				el.dispatchEvent(click);
    -			});
    +			ul.querySelector("li")?.classList.add("selected");
     		}
     	});
     
    -	window.addEventListener("popstate", function (e) {
    -		e.preventDefault();
    -		if (e.state != null) {
    -			chooseTab(document.querySelector(`#${e.state.tab}`));
    -		} else {
    -			history.go(-1);
    +	// Initial hash handling (tabs only)
    +	if (location.hash.startsWith(tabNamespace)) {
    +		const tabId = location.hash.replace(tabNamespace, "");
    +		waitForElement(`#${tabId}`).then(el => {
    +			el.focus();
    +			el.dispatchEvent(click);
    +		});
    +	}
    +
    +	// History navigation (tabs only)
    +	window.addEventListener("popstate", (e) => {
    +		if (!location.hash.startsWith(tabNamespace)) return;
    +		if (e.state?.tab) {
    +			const tab = document.querySelector(`#${e.state.tab}`);
    +			if (tab) chooseTab(tab);
     		}
     	});
    -}
    -
    +}
    diff --git a/src/pg/patterns/core/tabs/_tabs-jquery.js b/src/pg/patterns/core/tabs/_tabs-jquery.js deleted file mode 100644 index e697201..0000000 --- a/src/pg/patterns/core/tabs/_tabs-jquery.js +++ /dev/null @@ -1,27 +0,0 @@ -jQuery(document).ready(function($){ - $(".tab-group").each(function(){ - if ($(this).children('[role="tablist"]').length > 0) { - let tabgroup = $(this).attr("id"), - tablist = ""; - $(this).children("*").each(function(){ - let tab = $(this).attr("data-tab"); - if (typeof tab !== 'undefined' && tab !== false) { - let tabID = tab.replace(/\W+/g,"-").toLowerCase(); - $(this).wrap(`
    `); - tablist += ``; - } else { - $(this).addClass("tab-hidden"); - } - - }) - $(this).prepend(``); - - $(this).children('[role="tab"]').on("click", function(){ - $(this).parent().children('[role="tab"]').removeClass("selected"); - $(this).addClass("selected"); - $(this).parent().parent().children('[role="tabpanel"]').removeClass("open"); - $("#" + $(this).attr("id").replace("tab", "tab-panel")).addClass("open"); - }) - } - }) -}) \ No newline at end of file diff --git a/src/pg/patterns/core/tabs/_tabs.js b/src/pg/patterns/core/tabs/_tabs.js index 46a5859..2721a03 100644 --- a/src/pg/patterns/core/tabs/_tabs.js +++ b/src/pg/patterns/core/tabs/_tabs.js @@ -1,192 +1,306 @@ -/* DS2 core (c) 2024-2026 Alexander McIlwraith - Released under Creative Commons Attribution-ShareAlike 4.0 International -*/ - -// create a pure JS mouse click event -const click = new MouseEvent('click', { - view: window, - bubbles: false, - cancelable: true -}); - -// wait for an element to appear in the DOM -const waitForElement = (selector) => { - return new Promise(resolve => { - if (document.querySelector(selector)) { - return resolve(document.querySelector(selector)); - } - const observer = new MutationObserver(() => { - if (document.querySelector(selector)) { - observer.disconnect(); - resolve(document.querySelector(selector)); - } - }); - observer.observe(document.body, { - childList: true, - subtree: true - }); - }); -}; - -// Tab logic -const tabNamespace = "#tab:"; - -const chooseTab = (tab) => { - const siblings = Array.from(tab.parentNode.children); - siblings.forEach(sibling => sibling.classList.remove("selected")); - tab.classList.add("selected"); - - const tabPanels = Array.from(tab.parentNode.parentNode.children); - tabPanels.forEach(panel => panel.classList.remove("open")); - - const tabPanelId = tab - .getAttribute("id") - .replace("tab", "tab-panel"); - - document - .getElementById(tabPanelId) - .classList.add("open"); -}; - -let pushStateCount = 0; -let tabsetCount = 0; - -export function init(container = document, spacer = true) { - - container.querySelectorAll(".tab-group, tabset").forEach(tabGroup => { - - if (tabGroup.querySelector('[role="tablist"]') === null) { - - if (tabGroup.getAttribute("id") == null) { - tabGroup.setAttribute("id", `tab-group-${tabsetCount++}`); - } - - const tabgroup = tabGroup.getAttribute("id"); - let tablist = ""; - - Array.from(tabGroup.children).forEach(child => { - - const isDetails = child.nodeName === "DETAILS"; - const tabLabel = - isDetails - ? child.querySelector("summary")?.innerHTML - : child.getAttribute("tab") || child.getAttribute("data-tab"); - - if (tabLabel !== null) { - - const tabID = tabLabel.replace(/\W+/g, "-").toLowerCase(); - let tabPanel; - - if (isDetails) { - tabPanel = child; - tabPanel.setAttribute("open", ""); - } else { - tabPanel = document.createElement("div"); - tabPanel.appendChild(child.cloneNode(true)); - } - - tabPanel.id = `tab-panel-${tabgroup}-${tabID}`; - tabPanel.className = tablist === "" ? "open" : ""; - tabPanel.setAttribute("role", "tabpanel"); - tabPanel.setAttribute("tabindex", "0"); - tabPanel.setAttribute( - "aria-labelledby", - `tab-${tabgroup}-${tabID}` - ); - - child.parentNode.replaceChild(tabPanel, child); - - tablist += ` - - `; - } else { - child.classList.add("tab-hidden"); - } - }); - - const ul = document.createElement("ul"); - ul.setAttribute("role", "tablist"); - tabGroup.insertBefore(ul, tabGroup.firstChild); - - ul.innerHTML = spacer !== true - ? tablist - : `${tablist}`; - - // Tab ordering - if (tabGroup.hasAttribute("order") || tabGroup.hasAttribute("data-order")) { - - const order = ( - tabGroup.getAttribute("order") || - tabGroup.getAttribute("data-order") - ).split(","); - - const items = Array.from(ul.getElementsByTagName("li")); - - items.sort((a, b) => { - const aa = order.indexOf(a.textContent.trim()); - const bb = order.indexOf(b.textContent.trim()); - if (aa === -1) return 1; - if (bb === -1) return -1; - return aa - bb; - }); - - ul.innerHTML = ""; - items.forEach(item => ul.appendChild(item)); - chooseTab(items[0]); - } - - // Tab event handlers - tabGroup.querySelectorAll('[role="tab"]').forEach(tab => { - - tab.addEventListener("click", (evt) => { - - const tabId = tab.getAttribute("id"); - const hash = `${tabNamespace}${tabId}`; - - chooseTab(evt.currentTarget); - - window.history.pushState( - { tab: tabId }, - "", - `${location.pathname}${location.search}${hash}` - ); - - pushStateCount++; - }); - - tab.addEventListener("keypress", (e) => { - if (e.which === 32 || e.which === 13) { - e.preventDefault(); - e.currentTarget.dispatchEvent(click); - } - }); - }); - - ul.querySelector("li")?.classList.add("selected"); - } - }); - - // Initial hash handling (tabs only) - if (location.hash.startsWith(tabNamespace)) { - const tabId = location.hash.replace(tabNamespace, ""); - waitForElement(`#${tabId}`).then(el => { - el.focus(); - el.dispatchEvent(click); - }); - } - - // History navigation (tabs only) - window.addEventListener("popstate", (e) => { - if (!location.hash.startsWith(tabNamespace)) return; - if (e.state?.tab) { - const tab = document.querySelector(`#${e.state.tab}`); - if (tab) chooseTab(tab); - } - }); +/* DS2 core (c) 2024-2026 Alexander McIlwraith + Released under Creative Commons Attribution-ShareAlike 4.0 International +*/ + +// create a pure JS mouse click event +const click = new MouseEvent('click', { + view: window, + bubbles: false, + cancelable: true +}); + +// wait for an element to appear in the DOM +const waitForElement = (selector) => { + return new Promise(resolve => { + if (document.querySelector(selector)) { + return resolve(document.querySelector(selector)); + } + const observer = new MutationObserver(() => { + if (document.querySelector(selector)) { + observer.disconnect(); + resolve(document.querySelector(selector)); + } + }); + observer.observe(document.body, { + childList: true, + subtree: true + }); + }); +}; + +// Tab logic +const tabNamespace = "#tab:"; + +const chooseTab = (tab) => { + const siblings = Array.from( + tab.closest('[role="tablist"]').querySelectorAll('[role="tab"]') + ); + siblings.forEach(sibling => sibling.classList.remove("selected")); + tab.classList.add("selected"); + + const tabGroup = tab.closest("tabset, .tab-group"); + const tabPanels = Array.from( + tabGroup.querySelectorAll('[role="tabpanel"]') + ); + + tabPanels.forEach(panel => panel.classList.remove("open")); + const tabPanelId = tab.getAttribute("id").replace("tab", "tab-panel"); + document.getElementById(tabPanelId).classList.add("open"); +}; + +let pushStateCount = 0; +let tabsetCount = 0; + +export function init(container = document, spacer = true) { + container.querySelectorAll(".tab-group, tabset").forEach(tabGroup => { + + if (tabGroup.querySelector('[role="tablist"]') === null) { + + if (tabGroup.getAttribute("id") == null) { + tabGroup.setAttribute("id", `tab-group-${tabsetCount++}`); + } + + const tabgroup = tabGroup.getAttribute("id"); + let tablist = ""; + + Array.from(tabGroup.children).forEach(child => { + + const isDetails = child.nodeName === "DETAILS"; + const tabLabel = isDetails ? child.querySelector("summary")?.innerHTML : child.getAttribute("tab") || child.getAttribute("data-tab"); + + if (tabLabel !== null) { + + const tabID = tabLabel.replace(/\W+/g, "-").toLowerCase(); + let tabPanel; + + if (isDetails) { + tabPanel = child; + tabPanel.setAttribute("open", ""); + } else { + tabPanel = document.createElement("div"); + tabPanel.appendChild(child.cloneNode(true)); + } + + tabPanel.id = `tab-panel-${tabgroup}-${tabID}`; + tabPanel.className = tablist === "" ? "open" : ""; + tabPanel.setAttribute("role", "tabpanel"); + tabPanel.setAttribute("tabindex", "0"); + tabPanel.setAttribute( + "aria-labelledby", + `tab-${tabgroup}-${tabID}` + ); + + child.parentNode.replaceChild(tabPanel, child); + + tablist += ``; + } else { + child.classList.add("tab-hidden"); + } + }); + + const ul = document.createElement("ul"); + ul.setAttribute("role", "tablist"); + tabGroup.insertBefore(ul, tabGroup.firstChild); + + + const wrapper = document.createElement("div"); + wrapper.className = "tab-scroll-wrapper"; + + const scroller = document.createElement("div"); + scroller.className = "tab-scroll"; + + const leftArrow = document.createElement("div"); + leftArrow.className = "tab-scroll-arrow left"; + + leftArrow.setAttribute("aria-hidden", "true"); + + leftArrow.innerHTML = ` + + + + `; + + const rightArrow = document.createElement("div"); + rightArrow.className = "tab-scroll-arrow right"; + + rightArrow.setAttribute("aria-hidden", "true"); + + rightArrow.innerHTML = ` + + + + `; + + ul.parentNode.insertBefore(wrapper, ul); + wrapper.appendChild(scroller); + wrapper.appendChild(leftArrow); + wrapper.appendChild(rightArrow); + scroller.appendChild(ul); + + const updateScrollState = () => { + const isOverflowing = scroller.scrollWidth > scroller.clientWidth; + + wrapper.classList.toggle("is-overflowing", isOverflowing); + + const atStart = scroller.scrollLeft <= 1; + const atEnd = scroller.scrollLeft + scroller.clientWidth >= scroller.scrollWidth - 2; + + leftArrow.classList.toggle("hidden", !isOverflowing || atStart); + rightArrow.classList.toggle("hidden", !isOverflowing || atEnd); + + + wrapper.classList.toggle("show-left", isOverflowing && !atStart); + wrapper.classList.toggle("show-right", isOverflowing && !atEnd); + + }; + + const scrollAmount = 15; // smaller = smoother per frame + const scrollInterval = 16; // ~60fps + + let scrollTimer = null; + + const startScrolling = (direction) => { + if (scrollTimer) return; + + let speed = 0.1; + + scrollTimer = setInterval(() => { + speed = Math.min(speed + 0.01, 5); // ramp up + scroller.scrollBy({ + left: direction * scrollAmount * speed, + behavior: "auto" + }); + }, scrollInterval); + }; + + + const stopScrolling = () => { + clearInterval(scrollTimer); + scrollTimer = null; + }; + leftArrow.addEventListener("mousedown", () => startScrolling(-1)); + leftArrow.addEventListener("mouseup", stopScrolling); + leftArrow.addEventListener("mouseleave", stopScrolling); + + leftArrow.addEventListener("touchstart", () => startScrolling(-1)); + leftArrow.addEventListener("touchend", stopScrolling); + + rightArrow.addEventListener("mousedown", () => startScrolling(1)); + rightArrow.addEventListener("mouseup", stopScrolling); + rightArrow.addEventListener("mouseleave", stopScrolling); + + rightArrow.addEventListener("touchstart", () => startScrolling(1)); + rightArrow.addEventListener("touchend", stopScrolling); + + const ARROW_ZONE = 40; + + wrapper.addEventListener("contextmenu", (e) => { + const isOverflowing = wrapper.classList.contains("is-overflowing"); + if (!isOverflowing) return; + + const rect = wrapper.getBoundingClientRect(); + + const isLeftZone = e.clientX < rect.left + ARROW_ZONE; + const isRightZone = e.clientX > rect.right - ARROW_ZONE; + + if (isLeftZone || isRightZone) { + e.preventDefault(); + } + }); + + + const scrollClickAmount = 150; + + leftArrow.addEventListener("click", () => { + scroller.scrollBy({ left: -scrollClickAmount, behavior: "smooth" }); + }); + + rightArrow.addEventListener("click", () => { + scroller.scrollBy({ left: scrollClickAmount, behavior: "smooth" }); + }); + + scroller.addEventListener("scroll", updateScrollState); + window.addEventListener("resize", updateScrollState); + + updateScrollState(); + ul.innerHTML = spacer !== true ? tablist : `${tablist}`; + + requestAnimationFrame(updateScrollState); + setTimeout(updateScrollState, 50); + + ul.innerHTML = spacer !== true ? tablist : `${tablist}`; + + // Tab ordering + if (tabGroup.hasAttribute("order") || tabGroup.hasAttribute("data-order")) { + + const order = ( + tabGroup.getAttribute("order") || + tabGroup.getAttribute("data-order") + ).split(","); + + const items = Array.from(ul.getElementsByTagName("li")); + + items.sort((a, b) => { + const aa = order.indexOf(a.textContent.trim()); + const bb = order.indexOf(b.textContent.trim()); + if (aa === -1) return 1; + if (bb === -1) return -1; + return aa - bb; + }); + + ul.innerHTML = ""; + items.forEach(item => ul.appendChild(item)); + chooseTab(items[0]); + } + + // Tab event handlers + tabGroup.querySelectorAll('[role="tab"]').forEach(tab => { + + tab.addEventListener("click", (evt) => { + + const tabId = tab.getAttribute("id"); + const hash = `${tabNamespace}${tabId}`; + + chooseTab(evt.currentTarget); + + window.history.pushState( + { tab: tabId }, + "", + `${location.pathname}${location.search}${hash}` + ); + + pushStateCount++; + }); + + tab.addEventListener("keypress", (e) => { + if (e.which === 32 || e.which === 13) { + e.preventDefault(); + e.currentTarget.dispatchEvent(click); + } + }); + }); + + ul.querySelector("li")?.classList.add("selected"); + } + }); + + // Initial hash handling (tabs only) + if (location.hash.startsWith(tabNamespace)) { + const tabId = location.hash.replace(tabNamespace, ""); + waitForElement(`#${tabId}`).then(el => { + el.focus(); + el.dispatchEvent(click); + }); + } + + // History navigation (tabs only) + window.addEventListener("popstate", (e) => { + if (!location.hash.startsWith(tabNamespace)) return; + if (e.state?.tab) { + const tab = document.querySelector(`#${e.state.tab}`); + if (tab) chooseTab(tab); + } + }); } \ No newline at end of file diff --git a/src/pg/patterns/core/tabs/_tabs.scss b/src/pg/patterns/core/tabs/_tabs.scss index 4a8e1ed..08487b8 100644 --- a/src/pg/patterns/core/tabs/_tabs.scss +++ b/src/pg/patterns/core/tabs/_tabs.scss @@ -1,78 +1,216 @@ -// DS2 core (c) 2024 Alexander McIlwraith -// Licensed under CC BY-SA 4.0 - -$tab-border: #7f7f7f !default; -$tab-panel-background-color: #FFF !default; -$tab-panel-top-border: #7f7f7f !default; -$tab-panel-top-border-width: 1px !default; -$tab-selected: #FFF !default; -$tab-selected-text: #000 !default; -$tab-notselected: #f0f0f0 !default; -$tab-notselected-text: #000 !default; - -@mixin tabs { - tabset, .tab-group { - margin: 2rem 0 1rem 0; - - [role="tablist"] { - display: flex; - margin: 0; - padding: 0; - - - li { - &.separator { - border-bottom: 1px solid $tab-border; - display: inline-block; - margin: .45rem 0 0 0; - width: 100%; - } - - &[role="tab"] { - background-color: $tab-selected; - border-left: 1px solid $tab-border; - border-right: 1px solid $tab-border; - border-radius: .5rem .5rem 0 0; - border-top: 1px solid $tab-border; - cursor:pointer; - display: inline; - margin: 0; - padding: 1rem 1.5rem .14rem 1.5rem; - z-index: 2; - - &:last-of-type { - border-right: 1px solid $tab-border; - } - - &:not(.selected) { - background-color: $tab-notselected; - border-bottom: 1px solid $tab-border; - /// color - } - - span { - display: block; - margin: 0 0 .5rem 0; - } - } - } - } - - .tab-hidden { - display: none; - } - - [role="tabpanel"] { - background-color: $tab-selected; - border: 1px solid $tab-border; - border-top: none; - padding: 1rem; - z-index: 1; - - &:not(.open) { - display: none; - } - } - @content; - } +$tab-border: #7f7f7f !default; + +$tab-selected: #FFF !default; +$tab-selected-text: #000 !default; + +$tab-notselected: #f0f0f0 !default; +$tab-notselected-text: #000 !default; + +@mixin tabs { + + tabset, .tab-group { + + margin: 2rem 0 1rem 0; + + [role="tablist"] li.selected { + background-color: var(--colour-green); + color: var(--colour-white); + + } + + > ul, + .tab-scroll > ul { + display: flex; + margin: 0; + padding: 0; + user-select: none; + + li.separator { + border-bottom: 1px solid $tab-border; + border-left: 1px solid $tab-border; + display: inline-block; + flex: 1 1 auto; + margin: .45rem 0 0 0; + width: auto; + } + } + + .tab-hidden { + display: none; + } + + [role="tab"] { + background-color: $tab-selected; + border-left: 1px solid $tab-border; + border-radius: .5rem .5rem 0 0; + border-top: 1px solid $tab-border; + cursor: pointer; + display: block; + flex: 0 0 auto; + margin: 0; + max-width: 100vw; + overflow: hidden; + padding: 1rem 1.5rem .14rem 1.5rem; + user-select: none; + white-space: normal; + word-break: break-word; + + &:last-of-type { + border-right: 1px solid $tab-border; + } + + &:not(.selected) { + background-color: $tab-notselected; + border-bottom: 1px solid $tab-border; + } + + span { + display: block; + margin: 0 0 .5rem 0; + } + } + + [role="tabpanel"] { + background-color: $tab-selected; + border: 1px solid $tab-border; + border-top: none; + padding: 1rem; + z-index: 1; + + &:not(.open) { + display: none; + } + + @content; + } + } + + // scroller + .tab-scroll { + width: 100%; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + user-select: none; + + &::-webkit-scrollbar { + display: none; + } + + > ul { + flex-wrap: nowrap; + min-width: 100%; + width: max-content; + } + } + + // wrapper (now owns the fade) + .tab-scroll-wrapper { + position: relative; + user-select: none; + $radial: 2.5rem; + // edge fades (this is the fix) + &::before, + &::after { + content: ""; + position: absolute; + top: 0; + width: 2.5rem; + height: 100%; + pointer-events: none; + z-index: 2; + opacity: 0; // hidden by default + transition: opacity 0.2s ease; + } + + // left fade + &::before { + background: radial-gradient( + circle at left center, + rgba(255,255,255,1) 0%, + rgba(255,255,255,0.9) 50%, + rgba(255,255,255,0.5) 75%, + rgba(255,255,255,0.25) 95%, + transparent 100% + ); + border-top-right-radius: $radial; + border-bottom-right-radius: $radial; + left: 0; + } + + // right fade + &::after { + right: 0; + background: radial-gradient( + circle at right center, + rgba(255,255,255,1) 0%, + rgba(255,255,255,0.9) 50%, + rgba(255,255,255,0.5) 75%, + rgba(255,255,255,0.25) 95%, + transparent 100% + ); + border-top-left-radius: $radial; + border-bottom-left-radius: $radial; + } + + // show fade only when overflowing + &.is-overflowing { + &::before, + &::after { + opacity: 0; + transition: opacity 0.15s ease-out; + transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1); + } + + &.show-left { + &::before { + opacity: 1; + } + } + &.show-right { + &::after { + opacity: 1; + } + } + + } + + // arrows + .tab-scroll-arrow { + align-items: center; + cursor: pointer; + display: none; + height: 100%; + justify-content: center; + position: absolute; + top: 0; + user-select: none; + width: 2.5rem; + z-index: 3; + path { + fill: $tab-border; + } + &.left { + left: 0; + } + + &.right { + right: 0; + } + + &.hidden { + display: none !important; + pointer-events: none; + visibility: hidden; + } + } + + // only show arrows when overflow + &.is-overflowing { + .tab-scroll-arrow { + display: flex; + } + } + } } \ No newline at end of file diff --git a/src/pg/patterns/core/tabs/tabs.css b/src/pg/patterns/core/tabs/tabs.css index 0a31721..1df61a1 100644 --- a/src/pg/patterns/core/tabs/tabs.css +++ b/src/pg/patterns/core/tabs/tabs.css @@ -1,45 +1,70 @@ tabset, .tab-group { margin: 2rem 0 1rem 0; } -tabset [role=tablist], .tab-group [role=tablist] { +tabset [role=tablist] li.selected, .tab-group [role=tablist] li.selected { + background-color: var(--colour-green); + color: var(--colour-white); +} +tabset > ul, +tabset .tab-scroll > ul, .tab-group > ul, +.tab-group .tab-scroll > ul { display: -webkit-box; display: -ms-flexbox; display: flex; margin: 0; padding: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -tabset [role=tablist] li.separator, .tab-group [role=tablist] li.separator { +tabset > ul li.separator, +tabset .tab-scroll > ul li.separator, .tab-group > ul li.separator, +.tab-group .tab-scroll > ul li.separator { border-bottom: 1px solid #7f7f7f; - display: inline-block; - margin: 0.45rem 0 0 0; - width: 100%; -} -tabset [role=tablist] li[role=tab], .tab-group [role=tablist] li[role=tab] { - background-color: #FFF; border-left: 1px solid #7f7f7f; - border-right: 1px solid #7f7f7f; - border-radius: 0.5rem 0.5rem 0 0; - border-top: 1px solid #7f7f7f; - cursor: pointer; - display: inline; - margin: 0; - padding: 1rem 1.5rem 0.14rem 1.5rem; - z-index: 2; -} -tabset [role=tablist] li[role=tab]:last-of-type, .tab-group [role=tablist] li[role=tab]:last-of-type { - border-right: 1px solid #7f7f7f; -} -tabset [role=tablist] li[role=tab]:not(.selected), .tab-group [role=tablist] li[role=tab]:not(.selected) { - background-color: #f0f0f0; - border-bottom: 1px solid #7f7f7f; -} -tabset [role=tablist] li[role=tab] span, .tab-group [role=tablist] li[role=tab] span { - display: block; - margin: 0 0 0.5rem 0; + display: inline-block; + -webkit-box-flex: 1; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + margin: 0.45rem 0 0 0; + width: auto; } tabset .tab-hidden, .tab-group .tab-hidden { display: none; } +tabset [role=tab], .tab-group [role=tab] { + background-color: #FFF; + border-left: 1px solid #7f7f7f; + border-radius: 0.5rem 0.5rem 0 0; + border-top: 1px solid #7f7f7f; + cursor: pointer; + display: block; + -webkit-box-flex: 0; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + margin: 0; + max-width: 100vw; + overflow: hidden; + padding: 1rem 1.5rem 0.14rem 1.5rem; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: normal; + word-break: break-word; +} +tabset [role=tab]:last-of-type, .tab-group [role=tab]:last-of-type { + border-right: 1px solid #7f7f7f; +} +tabset [role=tab]:not(.selected), .tab-group [role=tab]:not(.selected) { + background-color: #f0f0f0; + border-bottom: 1px solid #7f7f7f; +} +tabset [role=tab] span, .tab-group [role=tab] span { + display: block; + margin: 0 0 0.5rem 0; +} tabset [role=tabpanel], .tab-group [role=tabpanel] { background-color: #FFF; border: 1px solid #7f7f7f; @@ -49,4 +74,110 @@ tabset [role=tabpanel], .tab-group [role=tabpanel] { } tabset [role=tabpanel]:not(.open), .tab-group [role=tabpanel]:not(.open) { display: none; +} + +.tab-scroll { + width: 100%; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.tab-scroll::-webkit-scrollbar { + display: none; +} +.tab-scroll > ul { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + min-width: 100%; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; +} + +.tab-scroll-wrapper { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.tab-scroll-wrapper::before, .tab-scroll-wrapper::after { + content: ""; + position: absolute; + top: 0; + width: 2.5rem; + height: 100%; + pointer-events: none; + z-index: 2; + opacity: 0; + -webkit-transition: opacity 0.2s ease; + transition: opacity 0.2s ease; +} +.tab-scroll-wrapper::before { + background: radial-gradient(circle at left center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%); + border-top-right-radius: 2.5rem; + border-bottom-right-radius: 2.5rem; + left: 0; +} +.tab-scroll-wrapper::after { + right: 0; + background: radial-gradient(circle at right center, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 255, 255, 0.5) 75%, rgba(255, 255, 255, 0.25) 95%, transparent 100%); + border-top-left-radius: 2.5rem; + border-bottom-left-radius: 2.5rem; +} +.tab-scroll-wrapper.is-overflowing::before, .tab-scroll-wrapper.is-overflowing::after { + opacity: 0; + -webkit-transition: opacity 0.15s ease-out; + transition: opacity 0.15s ease-out; + -webkit-transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1); + transition: opacity 0.12s cubic-bezier(0.4, 0, 0.2, 1); +} +.tab-scroll-wrapper.is-overflowing.show-left::before { + opacity: 1; +} +.tab-scroll-wrapper.is-overflowing.show-right::after { + opacity: 1; +} +.tab-scroll-wrapper .tab-scroll-arrow { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + display: none; + height: 100%; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + position: absolute; + top: 0; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: 2.5rem; + z-index: 3; +} +.tab-scroll-wrapper .tab-scroll-arrow path { + fill: #7f7f7f; +} +.tab-scroll-wrapper .tab-scroll-arrow.left { + left: 0; +} +.tab-scroll-wrapper .tab-scroll-arrow.right { + right: 0; +} +.tab-scroll-wrapper .tab-scroll-arrow.hidden { + display: none !important; + pointer-events: none; + visibility: hidden; +} +.tab-scroll-wrapper.is-overflowing .tab-scroll-arrow { + display: -webkit-box; + display: -ms-flexbox; + display: flex; } \ No newline at end of file