Skip to content

Commit c1ef115

Browse files
author
Spencer Canner
committed
update accessibility label on cart toggle
1 parent 33d6aff commit c1ef115

File tree

5 files changed

+109
-11
lines changed

5 files changed

+109
-11
lines changed

src/defaults/components.js

+1
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ const defaults = {
310310
},
311311
text: {
312312
title: 'cart',
313+
countAccessibilityLabel: 'Number of items in your cart:',
313314
},
314315
},
315316
window: {

src/styles/host/host.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/styles/host/sass/host.css

+10
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,13 @@
133133
display: block;
134134
}
135135
}
136+
137+
.shopify-buy--visually-hidden {
138+
position: absolute !important;
139+
clip: rect(1px, 1px, 1px, 1px);
140+
padding:0 !important;
141+
border:0 !important;
142+
height: 1px !important;
143+
width: 1px !important;
144+
overflow: hidden;
145+
}

src/views/toggle.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ export default class ToggleView extends View {
3131
return `<p class="shopify-buy--visually-hidden">${this.component.options.text.title}</p>`;
3232
}
3333

34+
get accessibilityLabel() {
35+
return `<span>${this.component.options.text.title}</span>`;
36+
}
37+
38+
get countAccessibilityLabel() {
39+
if (!this.component.options.contents.count) {
40+
return '';
41+
}
42+
return `<span>${this.component.options.text.countAccessibilityLabel} ${this.component.count}</span>`;
43+
}
44+
45+
get summaryHtml() {
46+
return `<span class="shopify-buy--visually-hidden">${this.accessibilityLabel}${this.countAccessibilityLabel}</span>`;
47+
}
48+
3449
render() {
3550
super.render();
3651
if (this.component.options.sticky) {
@@ -44,8 +59,9 @@ export default class ToggleView extends View {
4459
if (this.iframe) {
4560
this.iframe.parent.setAttribute('tabindex', 0);
4661
this.iframe.parent.setAttribute('role', 'button');
47-
this.iframe.parent.setAttribute('aria-label', this.component.options.text.title);
62+
this.iframe.el.setAttribute('aria-hidden', true);
4863
this.resize();
64+
this.node.insertAdjacentHTML('afterbegin', this.summaryHtml);
4965
}
5066
}
5167

test/unit/toggle/toggle-view.js

+80-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Toggle from '../../../src/components/toggle';
22
import View from '../../../src/view';
3+
import { assert } from 'chai';
4+
import iframe from '../../../src/iframe';
35

46
describe('Toggle View class', () => {
57
let toggle;
@@ -25,6 +27,8 @@ describe('Toggle View class', () => {
2527
let addClassStub;
2628
let removeClassStub;
2729
let resizeStub;
30+
let insertAdjacentHtmlStub;
31+
const summaryHtml = '<span>summary</span>';
2832

2933
beforeEach(() => {
3034
superRenderStub = sinon.stub(View.prototype, 'render');
@@ -34,13 +38,19 @@ describe('Toggle View class', () => {
3438
toggle.view = Object.defineProperty(toggle.view, 'isVisible', {
3539
writable: true,
3640
});
41+
toggle.view = Object.defineProperty(toggle.view, 'summaryHtml', {
42+
writable: true,
43+
value: summaryHtml,
44+
});
45+
insertAdjacentHtmlStub = sinon.stub(toggle.view.node, 'insertAdjacentHTML');
3746
});
3847

3948
afterEach(() => {
4049
superRenderStub.restore();
4150
addClassStub.restore();
4251
removeClassStub.restore();
4352
resizeStub.restore();
53+
insertAdjacentHtmlStub.restore();
4454
});
4555

4656
it('calls super\'s render()', () => {
@@ -75,36 +85,47 @@ describe('Toggle View class', () => {
7585
});
7686

7787
describe('when iframe exists', () => {
78-
let setAttributeSpy;
88+
let parentSetAttributeSpy;
89+
let elSetAttributeSpy;
7990
beforeEach(() => {
80-
setAttributeSpy = sinon.spy();
91+
parentSetAttributeSpy = sinon.spy();
92+
elSetAttributeSpy = sinon.spy();
8193
toggle.view.iframe = {
8294
parent: {
83-
setAttribute: setAttributeSpy,
95+
setAttribute: parentSetAttributeSpy,
8496
},
97+
el: {
98+
setAttribute: elSetAttributeSpy,
99+
}
85100
};
86101
toggle.view.render();
87102
});
88103

89-
it('updates three attributes', () => {
90-
assert.calledThrice(setAttributeSpy);
104+
it('updates two attributes on the iframe\'s parent and one attribute on the iframe\'s el', () => {
105+
assert.calledTwice(parentSetAttributeSpy);
106+
assert.calledOnce(elSetAttributeSpy);
91107
});
92108

93109
it('sets tabindex of iframe\'s parent to zero', () => {
94-
assert.calledWith(setAttributeSpy.getCall(0), 'tabindex', 0);
110+
assert.calledWith(parentSetAttributeSpy.getCall(0), 'tabindex', 0);
95111
});
96112

97113
it('sets role of iframe\'s parent to button', () => {
98-
assert.calledWith(setAttributeSpy.getCall(1), 'role', 'button');
114+
assert.calledWith(parentSetAttributeSpy.getCall(1), 'role', 'button');
99115
});
100116

101-
it('sets aria-label of iframe\'s parent to text title', () => {
102-
assert.calledWith(setAttributeSpy.getCall(2), 'aria-label', toggle.options.text.title);
117+
it('sets aria-hidden to true on the iframe\'s el', () => {
118+
assert.calledWith(elSetAttributeSpy.getCall(0), 'aria-hidden', true);
103119
});
104120

105121
it('resizes view', () => {
106122
assert.calledOnce(resizeStub);
107123
});
124+
125+
it('inserts the summaryHtml at the beginning of the node', () => {
126+
assert.calledOnce(insertAdjacentHtmlStub);
127+
assert.calledWith(insertAdjacentHtmlStub, 'afterbegin', summaryHtml);
128+
});
108129
});
109130
});
110131

@@ -284,5 +305,55 @@ describe('Toggle View class', () => {
284305
assert.equal(toggle.view.readableLabel, `<p class="shopify-buy--visually-hidden">${toggle.options.text.title}</p>`);
285306
});
286307
});
308+
309+
describe('accessibilityLabel', () => {
310+
it('returns the title wrapped in a span', () => {
311+
assert.equal(toggle.view.accessibilityLabel, `<span>${toggle.options.text.title}</span>`)
312+
});
313+
});
314+
315+
describe('countAccessibilityLabel', () => {
316+
it('returns an empty string if count is false in the options contents', () => {
317+
toggle.config.toggle = {
318+
contents: {count: false},
319+
text: {countAccessibilityLabel: 'count label'},
320+
};
321+
322+
assert.equal(toggle.view.countAccessibilityLabel, '');
323+
});
324+
325+
it('returns the accessibililty label with the count wrapped in a span if count is true in the options contents', () => {
326+
const count = 2;
327+
toggle = Object.defineProperty(toggle, 'count', {
328+
writable: true,
329+
});
330+
toggle.count = count;
331+
toggle.config.toggle = {
332+
contents: {count: true},
333+
text: {countAccessibilityLabel: 'count label'},
334+
};
335+
336+
assert.equal(toggle.view.countAccessibilityLabel, `<span>${toggle.options.text.countAccessibilityLabel} ${count}</span>`);
337+
});
338+
});
339+
340+
describe('summaryHtml', () => {
341+
it('returns the accessibilityLabel and countAccessibilityLabel wrapped in a visually hidden span', () => {
342+
const accessibilityLabel = 'accessibility label';
343+
const countAccessibilityLabel = 'count accessibility label';
344+
345+
toggle.view = Object.defineProperty(toggle.view, 'accessibilityLabel', {
346+
writable: true,
347+
value: accessibilityLabel,
348+
});
349+
toggle.view = Object.defineProperty(toggle.view, 'countAccessibilityLabel', {
350+
writable: true,
351+
value: countAccessibilityLabel,
352+
});
353+
354+
assert.equal(toggle.view.summaryHtml, `<span class="shopify-buy--visually-hidden">${accessibilityLabel}${countAccessibilityLabel}</span>`)
355+
});
356+
});
357+
287358
});
288359
});

0 commit comments

Comments
 (0)