Skip to content

Commit

Permalink
feat(storefront): BCTHEME-200 add notifications announcement on carou…
Browse files Browse the repository at this point in the history
…sel change
  • Loading branch information
bc-alexsaiannyi committed Feb 24, 2021
1 parent 851e42b commit 0c35ac4
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 35 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Fixed required checkbox message displaying. [1963](https://github.com/bigcommerce/cornerstone/pull/1963)

## Draft
- Added notifications on Carousel's content cahnge through 'Next/Prev' buttons. [#1986](https://github.com/bigcommerce/cornerstone/pull/1986)
- Provided sufficient & informative text along with the color swatches [#1976](https://github.com/bigcommerce/cornerstone/pull/1976)
- If multiple Pick List Options are applied, customers cannot select "none" on both. [#1975](https://github.com/bigcommerce/cornerstone/pull/1975)
- Moved phrase from compare.html to en.json for increasing localization. [#1972](https://github.com/bigcommerce/cornerstone/pull/1972)
Expand Down
50 changes: 34 additions & 16 deletions assets/js/theme/common/carousel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,54 @@ import {
tooltipSetup,
setTabindexes,
arrowAriaLabling,
updateTextWithLiveData,
heroCarouselSetup,
getRealSlidesQuantityAndCurrentSlide,
} from './utils';

/**
* returns actualSlide and actualSlideCount
* based on provided carousel settings
* @param {Object} $slickSettings
* @returns {Object}
*/
const extractSlidesDetails = ({
slideCount, currentSlide, breakpointSettings, activeBreakpoint, $slider,
}) => getRealSlidesQuantityAndCurrentSlide(
breakpointSettings,
activeBreakpoint,
currentSlide,
slideCount,
$slider.data('slick').slidesToScroll,
);

export const onCarouselClick = ({
data: $activeSlider,
}) => {
const $parentContainer = $activeSlider.hasClass('productView-thumbnails') ? $('.productView-images') : $activeSlider;
const { actualSlideCount, actualSlide } = extractSlidesDetails($activeSlider[0].slick);
const $carouselContentElement = $('.js-carousel-content-change-message', $parentContainer);
const carouselContentInitText = $carouselContentElement.text();
const carouselContentAnnounceMessage = updateTextWithLiveData(carouselContentInitText, (actualSlide + 1), actualSlideCount);

$carouselContentElement.text(carouselContentAnnounceMessage);
};

export const onCarouselChange = (event, carousel) => {
const {
options: { prevArrow, nextArrow },
currentSlide,
slideCount,
$prevArrow,
$nextArrow,
$dots,
$slider,
breakpointSettings,
activeBreakpoint,
} = carousel;

const { actualSlideCount, actualSlide } = getRealSlidesQuantityAndCurrentSlide(
breakpointSettings,
activeBreakpoint,
currentSlide,
slideCount,
$slider.data('slick').slidesToScroll,
);

const { actualSlideCount, actualSlide } = extractSlidesDetails(carousel);
const $prevArrowNode = $prevArrow || $slider.find(prevArrow);
const $nextArrowNode = $nextArrow || $slider.find(nextArrow);

const dataArrowLabel = $slider.data('arrow-label');

if (dataArrowLabel) {
$prevArrowNode.attr('aria-label', dataArrowLabel);
$nextArrowNode.attr('aria-label', dataArrowLabel);
Expand All @@ -54,14 +73,13 @@ export default function () {
$carouselCollection.each((index, carousel) => {
// getting element using find to pass jest test
const $carousel = $(document).find(carousel);

$carousel.on('init', onCarouselChange);
$carousel.on('afterChange', onCarouselChange);
$carousel.on('init afterChange', onCarouselChange);
$carousel.on('click', '.slick-arrow, .js-carousel-dot', $carousel, onCarouselClick);

const isMultipleSlides = $carousel.children().length > 1;
const customPaging = isMultipleSlides
? () => (
'<button type="button"></button>'
'<button class="js-carousel-dot" type="button"></button>'
)
: () => {};

Expand Down
17 changes: 5 additions & 12 deletions assets/js/theme/common/carousel/utils/arrowAriaLabling.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
const NUMBER = '[NUMBER]';
const integerRegExp = /[0-9]+/;
const lastIntegerRegExp = /(\d+)(?!.*\d)/;
import updateTextWithLiveData from './updateTextWithLiveData';

export default ($prevArrow, $nextArrow, actualSlide, actualSlideCount) => {
if (actualSlideCount < 2) return;
if ($prevArrow.length === 0 || $nextArrow.length === 0) return;

const arrowAriaLabelBaseText = $prevArrow.attr('aria-label');

const isInit = arrowAriaLabelBaseText.includes(NUMBER);
const valueToReplace = isInit ? NUMBER : integerRegExp;
const currentSlideNumber = actualSlide + 1;

const prevSlideNumber = actualSlide === 0 ? actualSlideCount : currentSlideNumber - 1;
const arrowLeftText = arrowAriaLabelBaseText
.replace(valueToReplace, prevSlideNumber)
.replace(lastIntegerRegExp, actualSlideCount);
const arrowLeftText = updateTextWithLiveData(arrowAriaLabelBaseText, prevSlideNumber, actualSlideCount);

$prevArrow.attr('aria-label', arrowLeftText);

const nextSlideNumber = actualSlide === actualSlideCount - 1 ? 1 : currentSlideNumber + 1;
const arrowRightText = arrowAriaLabelBaseText
.replace(valueToReplace, nextSlideNumber)
.replace(lastIntegerRegExp, actualSlideCount);
const arrowRightText = updateTextWithLiveData(arrowAriaLabelBaseText, nextSlideNumber, actualSlideCount);

$nextArrow.attr('aria-label', arrowRightText);
};
1 change: 1 addition & 0 deletions assets/js/theme/common/carousel/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { default as heroCarouselSetup } from './heroCarouselSetup';
export { default as arrowAriaLabling } from './arrowAriaLabling';
export { default as updateTextWithLiveData } from './updateTextWithLiveData';
export { default as dotsSetup } from './dotsSetup';
export { default as getRealSlidesQuantityAndCurrentSlide } from './getRealSlidesQuantityAndCurrentSlide';
export { default as setTabindexes } from './setTabindexes';
Expand Down
3 changes: 1 addition & 2 deletions assets/js/theme/common/carousel/utils/tooltipSetup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const carouselTooltipClass = 'carousel-tooltip';
const carouselTooltip = `<span class="${carouselTooltipClass}"></span>`;

const setupTooltipAriaLabel = ($node) => {
const $existedTooltip = $node.find(`.${carouselTooltipClass}`);

Expand All @@ -17,7 +16,7 @@ const setupArrowTooltips = (...arrowNodes) => {
};

const setupDotTooltips = ($dots) => {
$dots.children().each((idx, dot) => setupTooltipAriaLabel($(dot).find('button')));
$dots.children().each((idx, dot) => setupTooltipAriaLabel($('.js-carousel-dot', dot)));
};

export default ($prevArrow, $nextArrow, $dots) => {
Expand Down
11 changes: 11 additions & 0 deletions assets/js/theme/common/carousel/utils/updateTextWithLiveData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const NUMBER = '[NUMBER]';
const integerRegExp = /[0-9]+/;
const lastIntegerRegExp = /(\d+)(?!.*\d)/;

export default (textForChange, slideNumber, slideCount) => {
const valueToReplace = textForChange.includes(NUMBER) ? NUMBER : integerRegExp;

return textForChange
.replace(valueToReplace, slideNumber)
.replace(lastIntegerRegExp, slideCount);
};
6 changes: 3 additions & 3 deletions assets/js/theme/global/quick-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import utils from '@bigcommerce/stencil-utils';
import ProductDetails from '../common/product-details';
import { defaultModal, modalTypes } from './modal';
import 'slick-carousel';
import { onCarouselChange } from '../common/carousel';
import { onCarouselChange, onCarouselClick } from '../common/carousel';

export default function (context) {
const modal = defaultModal();
Expand All @@ -24,8 +24,8 @@ export default function (context) {
const $carousel = modal.$content.find('[data-slick]');

if ($carousel.length) {
$carousel.on('init', onCarouselChange);
$carousel.on('afterChange', onCarouselChange);
$carousel.on('init afterChange', $carousel, onCarouselChange);
$carousel.on('click', '.slick-arrow', $carousel, onCarouselClick);

$carousel.slick();
}
Expand Down
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,7 @@
},
"carousel": {
"arrowAriaLabel": "Go to slide [NUMBER] of",
"contentAnnounceMessage": "You are currently on slide [NUMBER] of",
"dotAriaLabel": "Slide number",
"activeDotAriaLabel": "active",
"playPauseButtonPlay": "Play",
Expand Down
6 changes: 6 additions & 0 deletions templates/components/carousel-content-announcement.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<span
class="js-carousel-content-change-message aria-description--hidden"
aria-live="polite"
role="status">
{{lang 'carousel.contentAnnounceMessage'}} {{slides_length}}
</span>
7 changes: 5 additions & 2 deletions templates/components/carousel.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@
</a>
{{/if}}
{{/each}}
{{#and arrows (if carousel.slides.length '>' 1)}}
{{#if carousel.slides.length '>' 1}}
{{> components/carousel-content-announcement slides_length=carousel.slides.length}}
{{#if arrows}}
<button aria-label="{{lang 'carousel.arrowAriaLabel'}} {{carousel.slides.length}}" class="js-hero-next-arrow slick-next slick-arrow"></button>
{{/and}}
{{/if}}
{{#if play_pause_button}}
<button
type="button"
Expand All @@ -78,4 +80,5 @@
{{lang 'carousel.playPauseButtonPause'}}
</button>
{{/if}}
{{/if}}
</section>
1 change: 1 addition & 0 deletions templates/components/products/carousel.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@
{{/each}}
{{#if products.length '>' 1}}
<button aria-label="{{lang 'carousel.arrowAriaLabel'}} {{products.length}}" class="{{#if customArrowClass}}{{customArrowClass}} {{/if}}js-product-next-arrow slick-next slick-arrow"></button>
{{> components/carousel-content-announcement slides_length=products.length}}
{{/if}}
</section>
3 changes: 3 additions & 0 deletions templates/components/products/product-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
Note that these image sizes are coupled to image sizes used in /assets/js/theme/common/product-details.js
for variant/rule image replacement
--}}
{{#if product.images.length '>' 1 }}
{{> components/carousel-content-announcement slides_length=product.images.length}}
{{/if}}
<figure class="productView-image"
data-image-gallery-main
{{#if product.main_image}}
Expand Down

0 comments on commit 0c35ac4

Please sign in to comment.