Skip to content

Commit

Permalink
Implement related posts carousel
Browse files Browse the repository at this point in the history
* Separate behaviour for mobile (1 and dots) and desktop (3 and arrows)
* Maximum number of pages (5)
* Fix issue with mobile menu not being scrollable
* Disable pagination, we don't use it anymore
* Add design elements through CSS and SVG
  • Loading branch information
the-overengineer committed Sep 30, 2021
1 parent 1f2f278 commit f39b7ca
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 24 deletions.
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ code_examples_folder: examples
host: 0.0.0.0

pagination:
enabled: true
enabled: false
per_page: 6
limit: 0
sort_field: 'date'
Expand Down
4 changes: 2 additions & 2 deletions _includes/post-card.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="col-12 {%if include.small %}col-md-4{% else %}col-md-6 col-xl-4{% endif %} py-3 blog-card js-blog-card">
<div class="elevated-container blog-card-content position-relative h-100">
{% if include.post.summary_image %}
<div class="blog-card-summary-image" style="background-image: url('{{ include.post.summary_image }}')"></div>
<div class="blog-card-summary-image" style="background-image: url('{{ include.post.summary_image }}')"></div>
{% else %}
<div class="blog-card-summary-image {{ include.post.categories }}"></div>
<div class="blog-card-summary-image {{ include.post.categories }}"></div>
{% endif %}
<div class="p-4 d-flex flex-column justify-content-between blog-card-text">
<h4 class="text-dark-1">{{ include.post.title }}</h4>
Expand Down
35 changes: 18 additions & 17 deletions _layouts/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,33 +79,34 @@ <h6>Share this post</h6>

{% assign related = site.posts | where_exp:"item","item.categories == page.categories and item.title != page.title" %}

<div class="container-fluid bg-lightest">
<div class="container-fluid bg-lightest js-related-items-carousel-container pt-lg-5">
<div class="container">
<div class="w-100 text-center mb-5 carousel-heading">
<h2>Related Posts</h2>
</div>
<div class="blog-related-container position-relative">
<div id="blogPostsCarousel" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
{% for post in related %}
{% assign mod_idx = forloop.index | modulo: 3 %}
{% if mod_idx == 1 %}
<div class="carousel-item row no-gutters d-flex justify-content-center">
{% endif %}
{% include post-card.html post=post small=1 %}
{% if mod_idx == 1 %}
</div>
{% endif %}
{% endfor %}
<ol class="carousel-indicators d-lg-none js-carousel-indicators">
</ol>

<div class="carousel-inner js-carousel-items">
</div>
</div>

<a data-target="#blogPostsCarousel" data-slide="prev" role="button" class="previous-blog-btn">
<img src="/assets/img/icons/directional/carousel-navigation-previous.svg" alt="Next post slide icon">
<a data-target="#blogPostsCarousel" data-slide="prev" role="button" class="d-none d-lg-block previous-blog-btn js-carousel-btn">
<img src="/assets/img/icons/directional/angle-left.svg" alt="Next post slide icon">
</a>
<a data-target="#blogPostsCarousel" data-slide="next" role="button" class="next-blog-btn">
<img src="/assets/img/icons/directional/carousel-navigation-next.svg" alt="Previous post slide icon">
<a data-target="#blogPostsCarousel" data-slide="next" role="button" class="d-none d-lg-block next-blog-btn js-carousel-btn">
<img src="/assets/img/icons/directional/angle-right.svg" alt="Previous post slide icon">
</a>
</div>
</div>
</div>
</div>

<div class="js-related-posts-templates">
{% for post in related %}
{% include post-card.html post=post small=1 %}
{% endfor %}
</div>
</main>

Expand Down
6 changes: 6 additions & 0 deletions _sass/_nav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ a.nav-link {

.navbar.mobile-expanded {
background-color: $color-dark-background !important;
max-height: 100%;
overflow: auto;

.notification-bar + & {
max-height: calc(100% - 36px);
}
}

.notification-bar {
Expand Down
40 changes: 36 additions & 4 deletions _sass/layouts/_post.scss
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,34 @@
}

.blog-related-container {
display: flex;
align-items: stretch;
width: 100%;
min-height: 400px;
padding: 0 72px;
min-height: 502px;
padding: 0;

@media (min-width: $lg-start) {
display: block;
min-height: 606px;
padding: 0 72px;
}

.carousel {
padding-bottom: 36px;
}

.carousel-indicators li {
width: 12px;
height: 12px;
background-color: $color-dark-2;
border-radius: 100%;
opacity: 0.2;
transition: opacity 200ms linear;

&.active {
opacity: 1;
}
}
}

.previous-blog-btn,
Expand All @@ -140,11 +165,14 @@
display: inline-block;
top: 50%;
transform: translateY(-50%);
width: 60px;
height: 60px;
width: 30px;
text-decoration: none;
cursor: pointer;

img {
width: 26px;
}

&:hover,
&:active {
text-decoration: none;
Expand All @@ -158,3 +186,7 @@
.next-blog-btn {
right: 8px;
}

.carousel-heading {
font-weight: 700;
}
3 changes: 3 additions & 0 deletions assets/img/icons/directional/angle-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/img/icons/directional/angle-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions assets/js/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,77 @@ function generateTableOfContents() {
})
}

// Note: Liquid seems to have a problem of auto-closing tags
// when trying to group by modulo of index. I cannot figure out why,
// except for the fact that Liquid sucks. Hence JS grouping
function createCarouselFromItems() {
const perPage = window.innerWidth >= 992 ? 3 : 1
const $templateContainer = $('.js-related-posts-templates')
const $templates = $templateContainer.children()
const $carousel = $('.js-carousel-items')
const $indicators = $('.js-carousel-indicators')

let elementBuffer = []

const appendBuffer = () => {
if (elementBuffer.length > 0) {
const $container = $('<div class="row d-flex justify-content-center"></div>')
elementBuffer.forEach(($el) => {
$container.append($el)
})
const $item = $('<div class="carousel-item"></div>')
$item.append($container)
$carousel.append($item)
}

elementBuffer = []
}

let page = -1

for (let i = 0; i < $templates.length; i++) {
if (i % perPage === 0) {
page++
appendBuffer()
}

// Only go with the first several pages
if (page >= 5) {
break
}

elementBuffer.push($($templates[i]))

if (perPage === 1 && $templates.length > 1) {
const $indicator = $(`<li class="js-indicator" data-target="#blogPostsCarousel" data-slide-to="${i}"></li>`)
$indicators.append($indicator)
}
}

appendBuffer()

// Clean up the initial templates
$templateContainer.remove()
}

function initCarouselItems() {
createCarouselFromItems()
const $items = $('.carousel-item')
const $indicators = $('.js-indicator')
const first = $items.get(0)

if (first) {
$(first).addClass('active')
if ($indicators[0]) {
$indicators[0].classList.add('active')
}
} else {
// We don't have any items then. Let's remove the whole thing
$('.js-related-items-carousel-container').remove()
}

if ($items.length === 1) {
$('.js-carousel-btn').remove()
}
}

Expand Down

0 comments on commit f39b7ca

Please sign in to comment.