Skip to content

Commit

Permalink
feature(storefront): BCTHEME-74 As a shopper I want to have the add t…
Browse files Browse the repository at this point in the history
…o cart modal immediately have keyboard focus
  • Loading branch information
yurytut1993 committed Aug 3, 2020
1 parent 72e2b60 commit a0c0102
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Draft

- Added modal trap for for product details. [#1758](https://github.com/bigcommerce/cornerstone/pull/1758)
- Added tooltips for carousel Previous and Next buttons. [#1749](https://github.com/bigcommerce/cornerstone/pull/1749)

## 4.9.0 (07-28-2020)
- Added correct alt text on image change in product view. [#1747](https://github.com/bigcommerce/cornerstone/pull/1747)
- Description tab is hidden in case of empty product descrioption. [#1746](https://github.com/bigcommerce/cornerstone/pull/1746)
Expand Down
4 changes: 2 additions & 2 deletions assets/js/theme/common/product-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import utils from '@bigcommerce/stencil-utils';
import 'foundation-sites/js/foundation/foundation';
import 'foundation-sites/js/foundation/foundation.reveal';
import ImageGallery from '../product/image-gallery';
import modalFactory, { showAlertModal } from '../global/modal';
import modalFactory, { showAlertModal, modalTypes } from '../global/modal';
import _ from 'lodash';
import Wishlist from '../wishlist';
import { normalizeFormData } from './utils/api';
Expand Down Expand Up @@ -392,7 +392,7 @@ export default class ProductDetails {
if (this.previewModal) {
this.previewModal.open();

this.updateCartContent(this.previewModal, response.data.cart_item.id);
this.updateCartContent(this.previewModal, response.data.cart_item.id, () => this.previewModal.setupFocusableElements(modalTypes.PRODUCT_DETAILS));
} else {
this.$overlay.show();
// if no modal, redirect to the cart page
Expand Down
46 changes: 29 additions & 17 deletions assets/js/theme/global/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const modalBodyClass = 'modal-body';
const modalContentClass = 'modal-content';

const allTabbableElementsSelector = ':tabbable';
const inactiveTabbableElementsSelector = '[tabindex="-1"], [type="hidden"]';
const tabKeyCode = 9;
const firstTabbableClass = 'first-tabbable';
const lastTabbableClass = 'last-tabbable';
Expand All @@ -20,14 +19,19 @@ const SizeClasses = {

export const modalTypes = {
QUICK_VIEW: 'forQuickView',
PRODUCT_DETAILS: 'forProductDetails',
};

const focusableElements = {
[modalTypes.QUICK_VIEW]: () => $('#modal')
.find(allTabbableElementsSelector)
.not('#modal-review-form *')
.not('#previewModal *')
.not(inactiveTabbableElementsSelector),
[modalTypes.QUICK_VIEW]: () => (
$('#modal')
.find(allTabbableElementsSelector)
.not('#modal-review-form *')
.not('#previewModal *')
),
[modalTypes.PRODUCT_DETAILS]: () => (
$('#previewModal').find(allTabbableElementsSelector)
),
};

export const ModalEvents = {
Expand Down Expand Up @@ -218,25 +222,33 @@ export class Modal {

setupFocusableElements(modalType) {
this.$preModalFocusedEl = $(document.activeElement);
const $modalTabbableCollection = focusableElements[modalType]();

const $collection = focusableElements[modalType]();
$collection.get(0).focus();

$('#modal').on('keydown', event => this.onTabbing(event, modalType));
const elementToFocus = $modalTabbableCollection.get(0);
if (elementToFocus) elementToFocus.focus();

this.$modal.on('keydown', event => this.onTabbing(event, modalType));
}

onTabbing(event, modalType) {
const isTab = event.which === tabKeyCode;

if (!isTab) return;

const $tabbableCollection = focusableElements[modalType]();
const lastCollectionIdx = $tabbableCollection.length - 1;
const $firstTabbable = $tabbableCollection.get(0);
const $lastTabbable = $tabbableCollection.get(lastCollectionIdx);
const $modalTabbableCollection = focusableElements[modalType]();
const lastCollectionIdx = $modalTabbableCollection.length - 1;
const $firstTabbable = $modalTabbableCollection.get(0);
const $lastTabbable = $modalTabbableCollection.get(lastCollectionIdx);

$tabbableCollection.each((index, element) => {
$modalTabbableCollection.each((index, element) => {
const $element = $(element);

if ($modalTabbableCollection.length === 1) {
$element.addClass(`${firstTabbableClass} ${lastTabbableClass}`);
return false;
}

if ($element.is($firstTabbable)) {
$element.addClass(firstTabbableClass).removeClass(lastTabbableClass);
} else if ($element.is($lastTabbable)) {
Expand All @@ -253,13 +265,13 @@ export class Modal {
if (direction === 'forwards') {
const isLastActive = $activeElement.hasClass(lastTabbableClass);
if (isLastActive) {
$tabbableCollection.get(0).focus();
$modalTabbableCollection.get(0).focus();
event.preventDefault();
}
} else if (direction === 'backwards') {
const isFirstActive = $activeElement.hasClass(firstTabbableClass);
if (isFirstActive) {
$tabbableCollection.get(lastCollectionIdx).focus();
$modalTabbableCollection.get(lastCollectionIdx).focus();
event.preventDefault();
}
}
Expand All @@ -272,7 +284,7 @@ export class Modal {
onModalClosed() {
this.size = this.defaultSize;
if (this.$preModalFocusedEl) this.$preModalFocusedEl.focus();
$('#modal').off(ModalEvents.keyDown);
this.$modal.off(ModalEvents.keyDown);
this.unbindEvents();
}

Expand Down
4 changes: 2 additions & 2 deletions templates/components/common/modal.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div id="modal" class="modal" data-reveal data-prevent-quick-search-close>
<a href="#" class="modal-close" aria-label="{{lang 'common.close'}}" role="button">
<button class="modal-close" aria-label="{{lang 'common.close'}}">
<span aria-hidden="true">&#215;</span>
</a>
</button>
<div class="modal-content"></div>
<div class="loadingOverlay"></div>
</div>
4 changes: 2 additions & 2 deletions templates/components/products/product-view.html
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,9 @@ <h2 class="productView-brand"{{#if schema}} itemprop="brand" itemscope itemtype=
</div>

<div id="previewModal" class="modal modal--large" data-reveal>
<a href="#" class="modal-close" aria-label="{{lang 'common.close'}}" role="button">
<button class="modal-close" aria-label="{{lang 'common.close'}}">
<span aria-hidden="true">&#215;</span>
</a>
</button>
<div class="modal-content"></div>
<div class="loadingOverlay"></div>
</div>

0 comments on commit a0c0102

Please sign in to comment.