Skip to content

Commit

Permalink
feat(carousel): Orange branded 🎉
Browse files Browse the repository at this point in the history
  • Loading branch information
ffoodd committed Jan 5, 2021
1 parent 3911d64 commit 7f320f6
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 89 deletions.
76 changes: 74 additions & 2 deletions js/src/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ const CLASS_NAME_START = 'carousel-item-start'
const CLASS_NAME_NEXT = 'carousel-item-next'
const CLASS_NAME_PREV = 'carousel-item-prev'
const CLASS_NAME_POINTER_EVENT = 'pointer-event'
const CLASS_NAME_PAUSED = 'paused' // Boosted mod: used for progress indicators
const CLASS_NAME_DONE = 'done' // Boosted mod: used for progress indicators

const SELECTOR_ACTIVE = '.active'
const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'
Expand All @@ -91,6 +93,8 @@ const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'
const SELECTOR_INDICATORS = '.carousel-indicators'
const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'
const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'
const SELECTOR_CONTROL_PREV = '.carousel-control-prev' // Boosted mod
const SELECTOR_CONTROL_NEXT = '.carousel-control-next' // Boosted mod

const PREFIX_CUSTOM_PROPS = 'o-' // Boosted mod: should match `$boosted-variable-prefix` in scss/_variables.scss

Expand Down Expand Up @@ -158,6 +162,12 @@ class Carousel extends BaseComponent {
}

pause(event) {
// Boosted mod: reset the animation on progress indicator
if (this._indicatorsElement) {
this._element.classList.add(CLASS_NAME_PAUSED)
}
// End mod

if (!event) {
this._isPaused = true
}
Expand All @@ -172,6 +182,12 @@ class Carousel extends BaseComponent {
}

cycle(event) {
// Boosted mod: restart the animation on progress indicator
if (this._indicatorsElement) {
this._element.classList.remove(CLASS_NAME_PAUSED)
}
// End mod

if (!event) {
this._isPaused = false
}
Expand All @@ -195,6 +211,12 @@ class Carousel extends BaseComponent {
this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)
const activeIndex = this._getItemIndex(this._activeElement)

// Boosted mod: restart the animation on progress indicator
if (this._indicatorsElement) {
this._element.classList.remove(CLASS_NAME_DONE)
}
// End mod

if (index > this._items.length - 1 || index < 0) {
return
}
Expand Down Expand Up @@ -350,6 +372,26 @@ class Carousel extends BaseComponent {
}
}

// Boosted mod: handle prev/next controls states
_disableControl(element) {
if (element.nodeName === 'BUTTON') {
element.disabled = true
} else {
element.setAttribute('aria-disabled', true)
element.setAttribute('tabindex', '-1')
}
}

_enableControl(element) {
if (element.nodeName === 'BUTTON') {
element.disabled = false
} else {
element.removeAttribute('aria-disabled')
element.removeAttribute('tabindex')
}
}
// End mod

_getItemIndex(element) {
this._items = element && element.parentNode ?
SelectorEngine.find(SELECTOR_ITEM, element.parentNode) :
Expand All @@ -366,9 +408,23 @@ class Carousel extends BaseComponent {
const isGoingToWrap = (isPrevDirection && activeIndex === 0) ||
(isNextDirection && activeIndex === lastItemIndex)

if (isGoingToWrap && !this._config.wrap) {
return activeElement
// Boosted mod: progress indicators animation when wrapping is disabled
if (!this._config.wrap) {
if (isGoingToWrap) {
// Reset the animation on last progress indicator when last slide is active
if (isNextDirection && this._indicatorsElement && !this._element.hasAttribute('data-bs-slide')) {
this._element.classList.add(CLASS_NAME_DONE)
}

return activeElement
}

// Restart animation otherwise
if (this._indicatorsElement) {
this._element.classList.remove(CLASS_NAME_DONE)
}
}
// End mod

const delta = direction === DIRECTION_PREV ? -1 : 1
const itemIndex = (activeIndex + delta) % this._items.length
Expand Down Expand Up @@ -479,6 +535,22 @@ class Carousel extends BaseComponent {
this._setActiveIndicatorElement(nextElement)
this._activeElement = nextElement

// Boosted mod: enable/disable prev/next controls when wrap=false
if (!this._config.wrap) {
const prevControl = SelectorEngine.findOne(SELECTOR_CONTROL_PREV, this._element)
const nextControl = SelectorEngine.findOne(SELECTOR_CONTROL_NEXT, this._element)

this._enableControl(prevControl)
this._enableControl(nextControl)

if (nextElementIndex === 0) {
this._disableControl(prevControl)
} else if (nextElementIndex === (this._items.length - 1)) {
this._disableControl(nextControl)
}
}
// End mod

if (this._element.classList.contains(CLASS_NAME_SLIDE)) {
nextElement.classList.add(orderClassName)

Expand Down
162 changes: 126 additions & 36 deletions scss/_carousel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

.carousel {
position: relative;
margin-bottom: $carousel-margin-bottom; // Boosted mod
}

.carousel.pointer-event {
Expand Down Expand Up @@ -114,11 +113,11 @@
}

.carousel-control-prev {
left: $carousel-control-offset; // Boosted mod
left: 0;
background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null);
}
.carousel-control-next {
right: $carousel-control-offset; // Boosted mod
right: 0;
background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null);
}

Expand All @@ -128,7 +127,8 @@
display: inline-block;
width: $carousel-control-icon-width;
height: $carousel-control-icon-width;
background: escape-svg($carousel-control-prev-icon-bg) no-repeat 50% / #{$carousel-control-icon-size $carousel-control-icon-size}; // Boosted mod
background: rgba($carousel-indicator-active-bg, .5) escape-svg($carousel-control-icon-bg) no-repeat subtract(50%, $spacer / 10) 50% / #{$carousel-control-icon-size $carousel-control-icon-size}; // Boosted mod
@include border-radius(50%, 50%);
}

// Boosted mod
Expand All @@ -145,26 +145,55 @@
transform: scaleX(-1);
}
*/

@each $direction in "prev", "next" {
.carousel-control-#{$direction} {
&:hover,
&:focus {
.carousel-control-#{$direction}-icon {
background-color: $carousel-indicator-active-bg;
filter: $carousel-control-icon-filter;
}
}

&:active {
.carousel-control-#{$direction}-icon {
background-color: $carousel-control-icon-active-bg;
filter: none;
}
}

&:disabled,
&[aria-disabled] {
pointer-events: none;

.carousel-control-#{$direction}-icon {
background-image: escape-svg($carousel-control-icon-disabled-bg);
}
}
}
}
// End mod

// Optional indicator pips
//
// Add an ordered list with the following class and add a list item for each
// slide your carousel holds.

/* rtl:begin:ignore */
.carousel-indicators {
position: absolute;
right: 0;
bottom: -$carousel-margin-bottom;
left: 0;
bottom: 0;
left: 50%; // Boosted mod
z-index: 2;
display: flex;
justify-content: center;
padding-left: 0; // override <ol> default
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width;
margin-left: $carousel-control-width;
padding: $carousel-indicators-padding-y 0; // Boosted mod
// Boosted mod: no margins
list-style: none;
background: rgba($carousel-indicator-active-bg, .5); // Boosted mod
transform: translateX(-50%); // Boosted mod
@include border-radius($spacer, $spacer); // Boosted mod

li {
box-sizing: content-box;
Expand All @@ -176,48 +205,109 @@
text-indent: -999px;
cursor: pointer;
background-color: $carousel-control-color; // Boosted mod
background-clip: padding-box;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-top: $carousel-indicator-hit-area-height solid transparent;
border-bottom: $carousel-indicator-hit-area-height solid transparent;
// Boosted mod: use our own target-size() mixin instead of transparent borders
opacity: $carousel-indicator-opacity;
@include transition($carousel-indicator-transition);
@include border-radius(50%, 50%); // Boosted mod

// Boosted mod
@include border-radius(50%, 50%);
@include target-size($carousel-indicator-hit-area-height);

&:hover,
&:focus {
background-color: color-contrast($carousel-indicator-active-bg);
transform: scale($carousel-indicator-hover-scale);

&::before {
transform: translate3d(-50%, -50%, 0) scale($carousel-indicator-active-scale);
}
}
}

.active {
background-color: $carousel-indicator-active-bg; // Boosted mod
background-color: $carousel-indicator-active-bg;
border-color: color-contrast($carousel-indicator-active-bg);
opacity: $carousel-indicator-active-opacity;

@if $enable-transitions {
// Animation based on Lea Verou's simple pie chart
// See https://www.smashingmagazine.com/2015/07/designing-simple-pie-charts-with-css/
background-image: linear-gradient(to right, transparent 50%, color-contrast($carousel-indicator-active-bg) 0);
transform: scale($carousel-indicator-hover-scale);
// No need to feature test mask-*
// See https://caniuse.com/mdn-css_properties_mask-image
mask-image: radial-gradient(circle at 50%, transparent 33%, $white add(33%, 1px));

&:hover,
&:focus {
mask-image: none;
}

&::before {
transform: translate3d(-50%, -50%, 0) scale($carousel-indicator-active-scale);
}

&::after {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
content: "";
background-color: inherit;
transform-origin: left;
// stylelint-disable-next-line function-disallowed-list
animation: carousel-progress calc(#{$carousel-indicator-animation-interval} / 2) linear infinite, carousel-progress-half $carousel-indicator-animation-interval step-end infinite;
@include border-radius($carousel-indicator-active-radius, $carousel-indicator-active-radius);
}

@keyframes carousel-progress {
to { transform: rotate(.5turn); }
}

@keyframes carousel-progress-half {
50% { background: color-contrast($carousel-indicator-active-bg); }
}

.carousel.done &,
.carousel.paused &,
.carousel.static & {
background: color-contrast($carousel-indicator-active-bg);

&::after {
animation: none;
}
}

@if $enable-reduced-motion {
@media (prefers-reduced-motion: reduce) {
background: color-contrast($carousel-indicator-active-bg);

&::after {
animation: none;
}
}
}
}
}
}

/* rtl:end:ignore */
// End mod


// Optional captions
//
//

.carousel-caption {
position: absolute;
right: (100% - $carousel-caption-width) / 2;
bottom: $carousel-caption-spacer;
left: map-get($spacers, 5);
padding: $carousel-caption-padding-y; // Boosted mod
left: (100% - $carousel-caption-width) / 2;
padding: $carousel-caption-padding-y $carousel-caption-padding-x; // Boosted mod
color: $carousel-caption-color;
background-color: color-contrast($carousel-caption-color); // Boosted mod
background-color: color-contrast($carousel-caption-color); // Boosted mod: ensure contrast
}

// Dark mode carousel

.carousel-dark {
.carousel-control-prev-icon,
.carousel-control-next-icon {
filter: $carousel-dark-control-icon-filter;
}

.carousel-indicators li {
background-color: $carousel-dark-indicator-active-bg;
}

.carousel-caption {
color: $carousel-dark-caption-color;
}
}
// Boosted mod: no dark carousel
Loading

0 comments on commit 7f320f6

Please sign in to comment.