From b0282bc30b8e8388f783a54fdb216a197576517e Mon Sep 17 00:00:00 2001 From: Rushan Date: Wed, 25 Jan 2023 21:26:37 +0400 Subject: [PATCH] Add clickable buttons to navigate between images in the carousel (#714) Preview: Screenshot 2023-01-25 at 20 03 00 Limitations: - Arrows are only present on the carousel and not in the Lightbox preview. In the future, I'll investigate the options for including arrows on the Light box. For this, we might need to replace the existing Lightbox plugin with a modern one. - Loop navigation is not available; instead, arrows will only be shown when they correspond to the first and last slides. --- source/_static/js/main.js | 66 ++++++++++++++++++ source/_static/scss/includes/_misc.scss | 93 +++++++++++++++++++++++-- 2 files changed, 155 insertions(+), 4 deletions(-) diff --git a/source/_static/js/main.js b/source/_static/js/main.js index caeefe3b..a126b1fe 100644 --- a/source/_static/js/main.js +++ b/source/_static/js/main.js @@ -426,4 +426,70 @@ window.addEventListener("DOMContentLoaded", (event) => { }); } })(); + + // -------------------------------------------------- + // Carousel + // -------------------------------------------------- + (function () { + const carousels = document.querySelectorAll(".sd-cards-carousel"); + var scrollLength = 1000; + + const arrowIcon = ` + + `; + + function toggleArrows(elem, arrowLeft, arrowRight) { + var scrollWidth = elem.scrollWidth; + var scrollLeft = elem.scrollLeft + elem.clientWidth; + + // Set the scroll length based on the window width + window.innerWidth < 1400 ? scrollLength = 500 : scrollLength = 1000; + + scrollWidth - scrollLeft <= 1 + ? arrowRight.classList.add("inactive") + : arrowRight.classList.remove("inactive"); + scrollLeft === elem.clientWidth + ? arrowLeft.classList.add("inactive") + : arrowLeft.classList.remove("inactive"); + } + + if(carousels.length > 0) { + carousels.forEach((item) => { + // Get the amount of columns + const colsAmount = item.className.match(/(^|\s)sd-card-cols-(\w+)/g).pop().split('-').pop(); + + // Wrap the carousel in a div + const wrapper = document.createElement("div"); + wrapper.classList.add("carousel-wrapper"); + item.insertAdjacentElement("beforebegin", wrapper); + + // Create the arrows + const arrowLeft = document.createElement("button"); + arrowLeft.classList.add("carousel-arrow", "carousel-arrow--left"); + arrowLeft.innerHTML = arrowIcon; + arrowLeft.onclick = function() { + item.scrollLeft -= scrollLength/colsAmount; + } + + const arrowRight = document.createElement("button"); + arrowRight.classList.add("carousel-arrow", "carousel-arrow--right"); + arrowRight.innerHTML = arrowIcon; + arrowRight.onclick = function() { + item.scrollLeft += scrollLength/colsAmount; + } + + wrapper.insertAdjacentElement("afterbegin", arrowLeft); + wrapper.insertAdjacentElement("beforeend", arrowRight); + + // Move the carousel into the wrapper + wrapper.appendChild(item); + + // Toggle arrows on manual scroll + item.addEventListener("scroll", () => { + toggleArrows(item, arrowLeft, arrowRight); + }); + toggleArrows(item, arrowLeft, arrowRight); + }); + } + })(); }); \ No newline at end of file diff --git a/source/_static/scss/includes/_misc.scss b/source/_static/scss/includes/_misc.scss index f3607bdf..d7e8a80b 100644 --- a/source/_static/scss/includes/_misc.scss +++ b/source/_static/scss/includes/_misc.scss @@ -206,6 +206,8 @@ --sd-color-shadow: none; --sd-color-card-border: var(--theme-light-bg); --sd-color-card-border-hover: var(--theme-light-hover-bg); + + font-size: $font-size-sm; } .sd-card-hover { @@ -215,7 +217,7 @@ } .sd-card-body { - padding: 1.5rem; + padding: 1.35rem; img { border: 0; @@ -223,10 +225,14 @@ } .sd-card-title { - line-height: 100%; - margin: -0.2rem 0 1rem; + margin-bottom: 1rem; + color: var(--headings-color); } +[data-lightbox] img { + padding: 0; + margin-bottom: 1rem; +} // ----------------------------- // Copy button @@ -272,4 +278,83 @@ button.copybtn { content: "Copied"; } } -} \ No newline at end of file +} + +// ----------------------------- +// Carousel +// ----------------------------- +.sd-cards-carousel { + border-radius: $border-radius; + overflow-x: scroll; + scroll-behavior: smooth; + + @include hide-scrollbars(); + + &.sd-card-cols-1 { + & > .sd-card { + width: 100%; + } + } + + &.sd-card-cols-2 { + & > .sd-card { + width: 50%; + } + } + + &.sd-card-cols-3 { + & > .sd-card { + width: 33.333%; + } + } + + &[class*=sd-card-cols] > .sd-card { + --sd-color-card-border: none + border-radius: 0; + margin: 0; + padding: 0.25rem; + + .sd-card-body { + border: 1px solid var(--table-border-color); + border-radius: $border-radius; + } + } +} + +.carousel-wrapper { + position: relative; +} + +.carousel-arrow { + background-color: var(--body-bg); + border: 1px solid var(--table-border-color); + border-radius: 50%; + width: 2.5rem; + height: 2.5rem; + display: grid; + place-content: center; + cursor: pointer; + position: absolute; + top: 50%; + transform: translateY(-50%); + z-index: 1; + transition: background-color 300ms, opacity 200ms; + color: var(--headings-color); + + &:hover { + background-color: var(--content-nav-bg); + } + + &.inactive { + opacity: 0; + } + + &.carousel-arrow--left { + left: -1rem; + } + + &.carousel-arrow--right { + right: -1rem; + transform: rotate(180deg) translateY(50%); + } +}