Skip to content

Commit

Permalink
fix/issue-395/carousel (#418)
Browse files Browse the repository at this point in the history
* Fix drag behaviour

* Add testing/example conditionals, clean carousel js code

* Update _carousel.scss

* Update caniuse-lite, invert navigation buttons, remove looping as default in the examples

* Fix counter functionality and add return statement if there are no carousel items

* Update _carousel.hbs
  • Loading branch information
laurenhitchon authored Jun 12, 2024
1 parent c6c7d35 commit b506c8e
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 61 deletions.
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 25 additions & 2 deletions src/components/card-carousel/_carousel.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{#if default}}<div class="nsw-carousel js-carousel" data-description="Highlighted latest news"{{#if pagination}} data-navigation-pagination="on"{{/if}}>
{{#if default}}<div class="nsw-carousel js-carousel" data-description="Highlighted latest news"{{#if loop}} data-loop="on" data-navigation="off"{{/if}}{{#if drag}} data-drag="on"{{/if}}{{#if pagination}} data-navigation-pagination="on"{{/if}}{{#if counter}} data-loop="off" data-navigation="off"{{/if}}>
<p class="sr-only">Carousel items</p>
<div class="nsw-carousel__wrapper js-carousel__wrapper">
<ol class="nsw-carousel__list">
Expand Down Expand Up @@ -41,5 +41,28 @@
</button>
</li>
</ul>
</nav>{{/unless}}
</nav>{{/unless}}{{#if counter}}
<div class="nsw-carousel__counter">
<p><i class="js-carousel__counter"></i> / <i class="js-carousel__counter-tot"></i></p>
<nav>
<ul>
<li>
<button aria-controls="nsw-carousel__list" aria-label="Show previous items" class="nsw-carousel__control nsw-carousel__control--prev js-carousel__control">
<svg class="nsw-icon" viewBox="0 0 20 20">
<title>Show previous items</title>
<polyline points="13 2 5 10 13 18" fill="none" stroke="currentColor" stroke-linecap="square" stroke-linejoin="square" stroke-width="2" />
</svg>
</button>
</li>
<li>
<button aria-controls="nsw-carousel__list" aria-label="Show next items" class="nsw-carousel__control nsw-carousel__control--next js-carousel__control">
<svg class="nsw-icon" viewBox="0 0 20 20">
<title>Show next items</title>
<polyline points="7 2 15 10 7 18" fill="none" stroke="currentColor" stroke-linecap="square" stroke-linejoin="square" stroke-width="2" />
</svg>
</button>
</li>
</ul>
</nav>
</div>{{/if}}
</div>{{/if}}
31 changes: 30 additions & 1 deletion src/components/card-carousel/_carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
// margin: 0;
// padding: 0;
}

button {
// addresses issue from button padding-inline-end and padding-inline-start which are set to 16px
padding: 0;
}

img,
video,
Expand All @@ -58,7 +63,8 @@
max-width: initial;
}

> nav {
> nav,
&__counter > nav {
order: 1;
margin-bottom: 0.5rem;
margin-right: 0.25rem;
Expand Down Expand Up @@ -89,6 +95,16 @@
}
}

&__counter {
display: flex;
justify-content: space-between;
align-items: center;

@include breakpoint('md') {
width: 100%;
}
}

&__list {
display: flex;
flex-wrap: nowrap;
Expand Down Expand Up @@ -290,13 +306,26 @@
@include nsw-focus(false);
outline-offset: 2px;
}

.nsw-section--invert & {
border: 2px solid var(--nsw-white);

&:focus {
@include nsw-focus($color: var(--nsw-focus-light));
outline-offset: 2px;
}
}
}

&--selected button {
background-color: var(--nsw-brand-dark);
border-radius: 7px;
width: 2.2em;

.nsw-section--invert & {
background-color: var(--nsw-white);
}

@include breakpoint('md') {
width: 1.6em;
}
Expand Down
11 changes: 7 additions & 4 deletions src/components/card-carousel/blank.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,25 @@ page: true

{{#>_layout-container}}
<h3>5 cards</h3>
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}

<h3>9 cards</h3>
{{>_carousel model.carousel-nine default=true loop=true}}
{{>_carousel model.carousel-nine default=true drag=true}}

<h3>Pagination</h3>
{{>_carousel model.carousel-nine pagination=true default=true}}

<h3>Counter</h3>
{{>_carousel model.carousel-nine counter=true default=true}}

{{/_layout-container}}

{{#>_layout-container brand-dark="true" invert="true"}}
<h3>5 cards</h3>
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}

<h3>9 cards</h3>
{{>_carousel model.carousel-nine default=true loop=true}}
{{>_carousel model.carousel-nine default=true drag=true}}

<h3>Pagination</h3>
{{>_carousel model.carousel-nine pagination=true default=true}}
Expand Down
63 changes: 24 additions & 39 deletions src/components/card-carousel/carousel.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import SwipeContent from './swipe-content'

/* eslint-disable no-new, max-len */
class Carousel {
/* eslint-disable max-len */
class Carousel extends SwipeContent {
constructor(element) {
super(element)
this.element = element
this.containerClass = 'nsw-carousel-container'
this.controlClass = 'js-carousel__control'
this.wrapperClass = 'js-carousel__wrapper'
this.counterClass = 'js-carousel__counter'
this.counterTorClass = 'js-carousel__counter-tot'
this.navClass = 'js-carousel__navigation'
this.navItemClass = 'js-carousel__nav-item'
this.navigationItemClass = element.getAttribute('data-navigation-item-class') ? element.getAttribute('data-navigation-item-class') : 'nsw-carousel__nav-item'
this.navigationClass = element.getAttribute('data-navigation-class') ? element.getAttribute('data-navigation-class') : 'nsw-carousel__navigation'
this.paginationClass = element.getAttribute('data-pagination-class') ? element.getAttribute('data-pagination-class') : 'nsw-carousel__navigation--pagination'
this.navigationItemClass = this.element.getAttribute('data-navigation-item-class') ? this.element.getAttribute('data-navigation-item-class') : 'nsw-carousel__nav-item'
this.navigationClass = this.element.getAttribute('data-navigation-class') ? this.element.getAttribute('data-navigation-class') : 'nsw-carousel__navigation'
this.paginationClass = this.element.getAttribute('data-pagination-class') ? this.element.getAttribute('data-pagination-class') : 'nsw-carousel__navigation--pagination'
this.draggingClass = 'nsw-carousel--is-dragging'
this.loadedClass = 'nsw-carousel--loaded'
this.animateClass = 'nsw-carousel__list--animating'
Expand All @@ -22,21 +24,18 @@ class Carousel {
this.hideControlsClass = 'nsw-carousel--hide-controls'
this.hideClass = 'nsw-display-none'
this.centerClass = 'nsw-justify-content-center'
this.element = element
this.listWrapper = this.element.querySelector(`.${this.wrapperClass}`)
this.list = this.listWrapper ? this.listWrapper.querySelector('ol') : false
this.items = this.list ? this.list.getElementsByTagName('li') : false
this.controls = this.element.querySelectorAll(`.${this.controlClass}`)
this.counter = this.element.querySelectorAll(`.${this.counterClass}`)
this.counterTor = this.element.querySelectorAll(`.${this.counterTorClass}`)
this.ariaLabel = (element.getAttribute('data-description')) ? element.getAttribute('data-description') : 'Card carousel'
this.drag = !((element.getAttribute('data-drag') && element.getAttribute('data-drag') === 'off'))
this.loop = !!((element.getAttribute('data-loop') && element.getAttribute('data-loop') === 'on'))
this.nav = !((element.getAttribute('data-navigation') && element.getAttribute('data-navigation') === 'off'))
this.navigationPagination = !!((element.getAttribute('data-navigation-pagination') && element.getAttribute('data-navigation-pagination') === 'on'))
this.overflowItems = !((element.getAttribute('data-overflow-items') && element.getAttribute('data-overflow-items') === 'off'))
this.alignControls = element.getAttribute('data-align-controls') ? element.getAttribute('data-align-controls') : false
this.justifyContent = !!((element.getAttribute('data-justify-content') && element.getAttribute('data-justify-content') === 'on'))
this.ariaLabel = this.element.getAttribute('data-description') ? this.element.getAttribute('data-description') : 'Card carousel'
this.dragEnabled = !!((this.element.getAttribute('data-drag') && this.element.getAttribute('data-drag') === 'on'))
this.loop = !!((this.element.getAttribute('data-loop') && this.element.getAttribute('data-loop') === 'on'))
this.nav = !((this.element.getAttribute('data-navigation') && this.element.getAttribute('data-navigation') === 'off'))
this.navigationPagination = !!((this.element.getAttribute('data-navigation-pagination') && this.element.getAttribute('data-navigation-pagination') === 'on'))
this.justifyContent = !!((this.element.getAttribute('data-justify-content') && this.element.getAttribute('data-justify-content') === 'on'))
this.initItems = []
this.itemsNb = this.items.length
this.visibItemsNb = 1
Expand All @@ -58,6 +57,8 @@ class Carousel {
}

init() {
if (!this.items) return

this.initCarouselLayout()
this.setItemsWidth(true)
this.insertBefore(this.visibItemsNb)
Expand All @@ -83,12 +84,13 @@ class Carousel {

this.carouselCreateContainer()

const itemStyle = window.getComputedStyle(this.items[0])
const containerStyle = window.getComputedStyle(this.listWrapper)
let itemWidth = parseFloat(itemStyle.getPropertyValue('width'))
const itemMargin = parseFloat(itemStyle.getPropertyValue('margin-right'))
const containerPadding = parseFloat(containerStyle.getPropertyValue('padding-left'))
let containerWidth = parseFloat(containerStyle.getPropertyValue('width'))
const itemStyle = this.items && window.getComputedStyle(this.items[0])

const containerStyle = this.listWrapper && window.getComputedStyle(this.listWrapper)
let itemWidth = itemStyle ? parseFloat(itemStyle.getPropertyValue('width')) : 0
const itemMargin = itemStyle ? parseFloat(itemStyle.getPropertyValue('margin-right')) : 0
const containerPadding = containerStyle ? parseFloat(containerStyle.getPropertyValue('padding-left')) : 0
let containerWidth = containerStyle ? parseFloat(containerStyle.getPropertyValue('width')) : 0

if (!this.itemAutoSize) {
this.itemAutoSize = itemWidth
Expand Down Expand Up @@ -123,7 +125,6 @@ class Carousel {
if (this.items.length <= this.visibItemsNb) this.totTranslate = 0

this.centerItems()
this.alignControlsFunc()
}

carouselCreateContainer() {
Expand Down Expand Up @@ -176,8 +177,8 @@ class Carousel {
this.emitCarouselActiveItemsEvent()
}

if (this.drag && window.requestAnimationFrame) {
new SwipeContent(this.element)
if (this.dragEnabled && window.requestAnimationFrame) {
super.init()
this.element.addEventListener('dragStart', (event) => {
if (event.detail.origin && event.detail.origin.closest(`.${this.controlClass}`)) return
if (event.detail.origin && event.detail.origin.closest(`.${this.navClass}`)) return
Expand Down Expand Up @@ -206,7 +207,6 @@ class Carousel {
this.resetCarouselControls()
this.setCounterItem()
this.centerItems()
this.alignControlsFunc()
this.emitCarouselActiveItemsEvent()
}, 250)
})
Expand Down Expand Up @@ -649,20 +649,6 @@ class Carousel {
this.list.classList.toggle(this.centerClass, this.items.length < this.visibItemsNb)
}

alignControlsFunc() {
if (this.controls.length < 1 || !this.alignControls) return
if (!this.controlsAlignEl) {
this.controlsAlignEl = this.element.querySelector(this.alignControls)
}
if (!this.controlsAlignEl) return
const translate = (this.element.offsetHeight - this.controlsAlignEl.offsetHeight)

this.controls.forEach((element) => {
const el = element
el.style.marginBottom = `${translate}px`
})
}

emitCarouselActiveItemsEvent() {
this.emitCarouselEvents('carousel-active-items', { firstSelectedItem: this.selectedItem, visibleItemsNb: this.visibItemsNb })
}
Expand All @@ -673,7 +659,6 @@ class Carousel {
}

resetVisibilityOverflowItems(j) {
if (!this.overflowItems) return
const itemWidth = this.containerWidth / this.items.length
const delta = (window.innerWidth - itemWidth * this.visibItemsNb) / 2
const overflowItems = Math.ceil(delta / itemWidth)
Expand Down
4 changes: 2 additions & 2 deletions src/components/card-carousel/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ meta-index: true
</div>

{{#>_docs-example showcode=true separated=true}}
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}
{{/_docs-example}}

{{#>_docs-code}}
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}
{{/_docs-code}}

<h3>Pagination</h3>
Expand Down
8 changes: 4 additions & 4 deletions src/components/card-carousel/swipe-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class SwipeContent {
this.dragging = false
this.intervalId = false
this.changedTouches = false
this.init()
}

init() {
Expand Down Expand Up @@ -107,12 +106,13 @@ class SwipeContent {
this.dragging = false
}

drag() {
drag(event) {
if (!this.dragging) return

if (!window.requestAnimationFrame) {
this.intervalId = setTimeout(() => { this.emitDrag.bind(this) }, 250)
this.intervalId = setTimeout(() => { this.emitDrag(event) }, 250)
} else {
this.intervalId = window.requestAnimationFrame(this.emitDrag.bind(this))
this.intervalId = window.requestAnimationFrame(() => { this.emitDrag(event) })
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/components/card-carousel/theme.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ page: true
{{#>_theme}}
{{#>_layout-container}}
<h3>5 cards</h3>
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}

<h3>9 cards</h3>
{{>_carousel model.carousel-nine default=true loop=true}}
{{>_carousel model.carousel-nine default=true drag=true}}

<h3>Pagination</h3>
{{>_carousel model.carousel-nine pagination=true default=true}}
Expand All @@ -22,10 +22,10 @@ page: true

{{#>_layout-container brand-dark="true" invert="true"}}
<h3>5 cards</h3>
{{>_carousel model.carousel-five default=true loop=true}}
{{>_carousel model.carousel-five default=true drag=true}}

<h3>9 cards</h3>
{{>_carousel model.carousel-nine default=true loop=true}}
{{>_carousel model.carousel-nine default=true drag=true}}

<h3>Pagination</h3>
{{>_carousel model.carousel-nine pagination=true default=true}}
Expand Down

0 comments on commit b506c8e

Please sign in to comment.