Skip to content

Commit f7af593

Browse files
author
Spencer Canner
committed
add aria live region to communicate cart changes
1 parent 33d6aff commit f7af593

File tree

4 files changed

+322
-174
lines changed

4 files changed

+322
-174
lines changed

src/components/cart.js

+50-15
Original file line numberDiff line numberDiff line change
@@ -93,21 +93,8 @@ export default class Cart extends Component {
9393
const data = Object.assign({}, lineItem, this.options.viewData);
9494
const fullPrice = data.variant.priceV2.amount * data.quantity;
9595
const formattedPrice = formatMoney(fullPrice, this.moneyFormat);
96-
const discountAllocations = data.discountAllocations;
97-
98-
const {discounts, totalDiscount} = discountAllocations.reduce((discountAcc, discount) => {
99-
const targetSelection = discount.discountApplication.targetSelection;
100-
if (LINE_ITEM_TARGET_SELECTIONS.indexOf(targetSelection) > -1) {
101-
const discountAmount = discount.allocatedAmount.amount;
102-
const discountDisplayText = discount.discountApplication.title || discount.discountApplication.code;
103-
discountAcc.totalDiscount += discountAmount;
104-
discountAcc.discounts.push({discount: `${discountDisplayText} (-${formatMoney(discountAmount, this.moneyFormat)})`});
105-
}
106-
return discountAcc;
107-
}, {
108-
discounts: [],
109-
totalDiscount: 0,
110-
});
96+
97+
const {discounts, totalDiscount} = this.discountsForLineItem(lineItem);
11198
data.discounts = discounts.length > 0 ? discounts : null;
11299
data.formattedFullPrice = totalDiscount > 0 ? formattedPrice : null;
113100
data.formattedActualPrice = formatMoney(fullPrice - totalDiscount, this.moneyFormat);
@@ -408,8 +395,15 @@ export default class Cart extends Component {
408395
this.toggles.forEach((toggle) => toggle.view.render());
409396
if (quantity > 0) {
410397
this.view.render();
398+
const updatedLineItem = this.model.lineItems.find((item) => item.id === id);
399+
this.updateSummaryText(`${this.options.text.itemTotalAccessibilityLabel} ${this.formattedLineItemTotal(updatedLineItem)}`);
411400
} else {
412401
this.view.animateRemoveNode(id);
402+
if (this.model.lineItems.length > 0) {
403+
this.updateSummaryText(this.options.text.itemRemovedAccessibilityLabel);
404+
} else {
405+
this.updateSummaryText(`${this.options.text.itemRemovedAccessibilityLabel} ${this.options.text.empty}`, true);
406+
}
413407
}
414408
return checkout;
415409
});
@@ -437,6 +431,7 @@ export default class Cart extends Component {
437431
if (!openCart) {
438432
this.setFocus();
439433
}
434+
this.updateSummaryText(this.options.text.itemAddedAccessibilityLabel);
440435
return checkout;
441436
});
442437
} else {
@@ -454,6 +449,7 @@ export default class Cart extends Component {
454449
if (!openCart) {
455450
this.setFocus();
456451
}
452+
this.updateSummaryText(this.options.text.itemAddedAccessibilityLabel);
457453
return checkout;
458454
});
459455
}
@@ -495,4 +491,43 @@ export default class Cart extends Component {
495491
this.view.setFocus();
496492
}, 0);
497493
}
494+
495+
updateSummaryText(lineItemText, hideSubtotal) {
496+
const summaryText = hideSubtotal ? lineItemText : `${lineItemText} ${this.options.text.subtotalAccessibilityLabel} ${this.formattedTotal}`;
497+
498+
const summaryNode = this.view.document.querySelector(this.selectors.cart.hiddenSummary);
499+
summaryNode.textContent = summaryText;
500+
501+
setTimeout(() => {
502+
summaryNode.textContent = '';
503+
}, 1000);
504+
}
505+
506+
formattedLineItemTotal(lineItem) {
507+
const fullPrice = lineItem.variant.priceV2.amount * lineItem.quantity;
508+
if (!this.options.contents.discounts) {
509+
return formatMoney(fullPrice, this.moneyFormat);
510+
}
511+
512+
const {totalDiscount} = this.discountsForLineItem(lineItem);
513+
return formatMoney(fullPrice - totalDiscount, this.moneyFormat);
514+
}
515+
516+
discountsForLineItem(lineItem) {
517+
const discountAllocations = lineItem.discountAllocations;
518+
519+
return discountAllocations.reduce((discountAcc, discount) => {
520+
const targetSelection = discount.discountApplication.targetSelection;
521+
if (LINE_ITEM_TARGET_SELECTIONS.indexOf(targetSelection) > -1) {
522+
const discountAmount = discount.allocatedAmount.amount;
523+
const discountDisplayText = discount.discountApplication.title || discount.discountApplication.code;
524+
discountAcc.totalDiscount += discountAmount;
525+
discountAcc.discounts.push({discount: `${discountDisplayText} (-${formatMoney(discountAmount, this.moneyFormat)})`});
526+
}
527+
return discountAcc;
528+
}, {
529+
discounts: [],
530+
totalDiscount: 0,
531+
});
532+
}
498533
}

src/defaults/components.js

+5
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ const defaults = {
230230
note: 'shopify-buy__cart__note',
231231
noteDescription: 'shopify-buy__cart__note__description',
232232
noteTextArea: 'shopify-buy__cart__note__text-area',
233+
hiddenSummary: 'shopify-buy__cart__summary visuallyhidden',
233234
},
234235
text: {
235236
title: 'Cart',
@@ -240,6 +241,10 @@ const defaults = {
240241
notice: 'Shipping and discount codes are added at checkout.',
241242
noteDescription: 'Special instructions for seller',
242243
closeAccessibilityLabel: 'Close cart',
244+
subtotalAccessibilityLabel: 'Cart subtotal',
245+
itemTotalAccessibilityLabel: 'Item total',
246+
itemRemovedAccessibilityLabel: 'Item removed from cart.',
247+
itemAddedAccessibilityLabel: 'Item added to cart.',
243248
},
244249
},
245250
lineItem: {

src/templates/cart.js

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const cartTemplates = {
3434
{{/data.contents.note}}
3535
<p class="{{data.classes.cart.notice}}" data-element="cart.notice">{{data.text.notice}}</p>
3636
<button class="{{data.classes.cart.button}}" type="button" data-element="cart.button">{{data.text.button}}</button>
37+
<span class="{{data.classes.cart.hiddenSummary}}" aria-live="polite" aria-atomic="true"></span>
3738
</div>
3839
{{/data.isEmpty}}`,
3940
};

0 commit comments

Comments
 (0)