@ons/design-system 57.0.1 → 58.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/autosuggest/_autosuggest.scss +16 -16
- package/components/breadcrumbs/_breadcrumbs.scss +2 -2
- package/components/browser-banner/_browser-banner.scss +5 -5
- package/components/button/_button.scss +62 -62
- package/components/call-to-action/_call-to-action.scss +1 -1
- package/components/checkboxes/_checkbox.scss +16 -16
- package/components/collapsible/_collapsible.scss +8 -8
- package/components/content-pagination/_content-pagination.scss +1 -1
- package/components/cookies-banner/_cookies-banner.scss +3 -3
- package/components/document-list/document-list.scss +10 -10
- package/components/download-resources/_download-resources.scss +5 -5
- package/components/external-link/_external-link.scss +4 -4
- package/components/feedback/_feedback.scss +3 -3
- package/components/field/_field.scss +1 -1
- package/components/find-a-support-centre/_find-a-support-centre.scss +1 -1
- package/components/footer/_footer.scss +7 -7
- package/components/header/_header.scss +26 -26
- package/components/hero/_hero.scss +4 -4
- package/components/input/_input-type.scss +5 -5
- package/components/input/_input.scss +13 -13
- package/components/label/_label.scss +1 -1
- package/components/lists/_list.scss +1 -1
- package/components/message/_message.scss +3 -3
- package/components/message-list/_message-list.scss +1 -1
- package/components/modal/_modal.scss +1 -1
- package/components/navigation/_macro.njk +1 -1
- package/components/navigation/_macro.spec.js +20 -2
- package/components/navigation/_navigation.scss +14 -14
- package/components/pagination/_pagination.scss +2 -2
- package/components/panel/_panel.scss +22 -22
- package/components/phase-banner/_phase-banner.scss +3 -3
- package/components/promotional-banner/_promo-banner.scss +5 -5
- package/components/question/_question.scss +4 -4
- package/components/quote/_quote.scss +2 -2
- package/components/radios/_radio.scss +6 -4
- package/components/related-content/_related-content.scss +2 -2
- package/components/relationships/_relationships.scss +2 -2
- package/components/section-navigation/_macro.njk +1 -1
- package/components/section-navigation/_section-navigation.scss +8 -8
- package/components/skip-to-content/_skip.scss +3 -3
- package/components/status/_status.scss +5 -5
- package/components/summary/_summary.scss +6 -6
- package/components/table/_table.scss +18 -18
- package/components/table-of-contents/_toc.scss +3 -3
- package/components/table-of-contents/toc.dom.js +2 -4
- package/components/tabs/_macro.njk +18 -5
- package/components/tabs/_macro.spec.js +54 -0
- package/components/tabs/_tabs.scss +57 -25
- package/components/tabs/tabs.js +35 -12
- package/components/tabs/tabs.spec.js +104 -10
- package/components/text-indent/_text-indent.scss +1 -1
- package/components/timeline/_timeline.scss +2 -2
- package/components/upload/_upload.scss +6 -6
- package/css/census.css +3 -3
- package/css/ids.css +3 -3
- package/css/main.css +3 -3
- package/css/print.css +1 -1
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +2 -2
- package/scss/base/_global.scss +7 -7
- package/scss/base/_typography.scss +2 -2
- package/scss/census.scss +1 -1
- package/scss/helpers/_functions.scss +0 -8
- package/scss/ids.scss +1 -1
- package/scss/overrides/hcm.scss +1 -1
- package/scss/overrides/rtl.scss +1 -1
- package/scss/patternlib.scss +10 -9
- package/scss/print.scss +7 -5
- package/scss/settings/_census.scss +24 -19
- package/scss/settings/_ids.scss +12 -8
- package/scss/utilities/_border.scss +1 -1
- package/scss/utilities/_colors.scss +1 -10
- package/scss/utilities/_grid.scss +3 -3
- package/scss/utilities/_typography.scss +1 -1
- package/scss/vars/_colors.scss +112 -99
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
.ons-toc {
|
|
2
2
|
&-container {
|
|
3
|
-
border-bottom: 1px solid
|
|
3
|
+
border-bottom: 1px solid var(--ons-color-grey-15);
|
|
4
4
|
margin-bottom: 2rem;
|
|
5
5
|
padding-bottom: 1rem;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
&__link-active {
|
|
9
|
-
color:
|
|
10
|
-
text-decoration: underline solid
|
|
9
|
+
color: var(--ons-color-text-link-hover);
|
|
10
|
+
text-decoration: underline solid var(--ons-color-text-link-hover) 2px;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
@@ -4,11 +4,9 @@ async function toc() {
|
|
|
4
4
|
const toc = [...document.querySelectorAll('.ons-js-toc-container')];
|
|
5
5
|
|
|
6
6
|
if (toc.length) {
|
|
7
|
-
|
|
8
|
-
const Toc = (await import('./toc')).default;
|
|
7
|
+
const Toc = (await import('./toc')).default;
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
}
|
|
9
|
+
toc.forEach(component => new Toc(component));
|
|
12
10
|
}
|
|
13
11
|
}
|
|
14
12
|
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
{% macro onsTabs(params) %}
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
{% set classes = 'ons-tabs' %}
|
|
3
|
+
|
|
4
|
+
{% set variantClasses %}
|
|
5
|
+
{% for variant in params.variants %}
|
|
6
|
+
{% set classes = classes ~ ' ons-tabs--' ~ variant %}
|
|
7
|
+
{% endfor %}
|
|
8
|
+
{% endset %}
|
|
9
|
+
|
|
10
|
+
<section class="{{ classes }}"
|
|
11
|
+
{% if params.noInitialActiveTab %}data-no-initial-active-tab="true"{% endif %}
|
|
12
|
+
>
|
|
13
|
+
{% set titleTag = params.titleTag | default("h2") %}
|
|
14
|
+
<{{ titleTag }} class="ons-tabs__title ons-u-fs-r--b ons-u-mt-no">{{ params.title }}</{{ titleTag }}>
|
|
15
|
+
|
|
4
16
|
<ul class="ons-tabs__list">
|
|
5
17
|
{% for tab in params.tabs %}
|
|
6
|
-
<li
|
|
18
|
+
<li class="ons-tab__list-item"><a href="#{{ tab.id if tab.id else 'tabId' ~ loop.index }}" class="ons-tab" data-ga="click" data-ga-category="tabs" data-ga-action="Show: {{ tab.title }}" data-ga-label="Show: {{ tab.title }}">{{ tab.title }}</a></li>
|
|
7
19
|
{% endfor %}
|
|
8
20
|
</ul>
|
|
21
|
+
|
|
9
22
|
{% for tab in params.tabs %}
|
|
10
|
-
<section id="
|
|
11
|
-
{{tab.content | safe}}
|
|
23
|
+
<section id="{{ tab.id if tab.id else 'tabId' ~ loop.index }}" class="ons-tabs__panel">
|
|
24
|
+
{{ tab.content | safe }}
|
|
12
25
|
</section>
|
|
13
26
|
{% endfor %}
|
|
14
27
|
</section>
|
|
@@ -6,6 +6,22 @@ import axe from '../../tests/helpers/axe';
|
|
|
6
6
|
import { renderComponent } from '../../tests/helpers/rendering';
|
|
7
7
|
|
|
8
8
|
const EXAMPLE_TABS = {
|
|
9
|
+
title: 'Example tabs',
|
|
10
|
+
tabs: [
|
|
11
|
+
{
|
|
12
|
+
id: 'first-tab',
|
|
13
|
+
title: 'Tab 1',
|
|
14
|
+
content: 'Example content...',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'second-tab',
|
|
18
|
+
title: 'Tab 2',
|
|
19
|
+
content: 'Some nested <strong>strong element</strong>...',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const EXAMPLE_TABS_WITHOUT_TAB_IDS = {
|
|
9
25
|
title: 'Example tabs',
|
|
10
26
|
tabs: [
|
|
11
27
|
{
|
|
@@ -27,6 +43,18 @@ describe('macro: tabs', () => {
|
|
|
27
43
|
expect(results).toHaveNoViolations();
|
|
28
44
|
});
|
|
29
45
|
|
|
46
|
+
it('has the provided variant classes', () => {
|
|
47
|
+
const $ = cheerio.load(
|
|
48
|
+
renderComponent('tabs', {
|
|
49
|
+
...EXAMPLE_TABS,
|
|
50
|
+
variants: ['details', 'example-variant'],
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect($('.ons-tabs').hasClass('ons-tabs--details')).toBe(true);
|
|
55
|
+
expect($('.ons-tabs').hasClass('ons-tabs--example-variant')).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
30
58
|
it('has the provided `title`', () => {
|
|
31
59
|
const $ = cheerio.load(renderComponent('tabs', EXAMPLE_TABS));
|
|
32
60
|
|
|
@@ -37,6 +65,32 @@ describe('macro: tabs', () => {
|
|
|
37
65
|
).toBe('Example tabs');
|
|
38
66
|
});
|
|
39
67
|
|
|
68
|
+
it('has title with provided tag override', () => {
|
|
69
|
+
const $ = cheerio.load(
|
|
70
|
+
renderComponent('tabs', {
|
|
71
|
+
...EXAMPLE_TABS,
|
|
72
|
+
titleTag: 'h4',
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const titleTag = $('.ons-tabs__title')[0].tagName;
|
|
77
|
+
expect(titleTag).toBe('h4');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('has the provided tab id attributes', () => {
|
|
81
|
+
const $ = cheerio.load(renderComponent('tabs', EXAMPLE_TABS));
|
|
82
|
+
|
|
83
|
+
expect($('.ons-tabs__panel:first').attr('id')).toBe('first-tab');
|
|
84
|
+
expect($('.ons-tabs__panel:last').attr('id')).toBe('second-tab');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('has default tab id attribute values when identifiers are not provided', () => {
|
|
88
|
+
const $ = cheerio.load(renderComponent('tabs', EXAMPLE_TABS_WITHOUT_TAB_IDS));
|
|
89
|
+
|
|
90
|
+
expect($('.ons-tabs__panel:first').attr('id')).toBe('tabId1');
|
|
91
|
+
expect($('.ons-tabs__panel:last').attr('id')).toBe('tabId2');
|
|
92
|
+
});
|
|
93
|
+
|
|
40
94
|
it('has expected label text in tab links', () => {
|
|
41
95
|
const $ = cheerio.load(renderComponent('tabs', EXAMPLE_TABS));
|
|
42
96
|
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
position: relative;
|
|
19
19
|
|
|
20
20
|
&::after {
|
|
21
|
-
background:
|
|
21
|
+
background: var(--ons-color-borders);
|
|
22
22
|
bottom: 0;
|
|
23
|
-
box-shadow: 0 1px 0 0
|
|
23
|
+
box-shadow: 0 1px 0 0 var(--ons-color-page-light);
|
|
24
24
|
content: '';
|
|
25
25
|
height: 1px;
|
|
26
26
|
left: 0;
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.ons-tab--row {
|
|
46
|
-
background:
|
|
47
|
-
border: 1px solid
|
|
46
|
+
background: var(--ons-color-button-secondary);
|
|
47
|
+
border: 1px solid var(--ons-color-button-secondary);
|
|
48
48
|
border-radius: 3px 3px 0 0;
|
|
49
|
-
color:
|
|
49
|
+
color: var(--ons-color-text);
|
|
50
50
|
display: inline-block;
|
|
51
51
|
height: 2.55rem;
|
|
52
52
|
line-height: 2.3rem;
|
|
@@ -57,42 +57,42 @@
|
|
|
57
57
|
text-decoration: underline;
|
|
58
58
|
|
|
59
59
|
&:hover {
|
|
60
|
-
background-color:
|
|
61
|
-
border-color:
|
|
62
|
-
color:
|
|
63
|
-
text-decoration: underline solid
|
|
60
|
+
background-color: var(--ons-color-button-secondary-hover);
|
|
61
|
+
border-color: var(--ons-color-button-secondary-hover);
|
|
62
|
+
color: var(--ons-color-text);
|
|
63
|
+
text-decoration: underline solid var(--ons-color-text) 2px;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
&:focus {
|
|
67
|
-
background-color:
|
|
68
|
-
border-bottom: 1px solid
|
|
69
|
-
box-shadow: inset 0 0 0 9px
|
|
70
|
-
inset 17px 0 0 0
|
|
71
|
-
inset -17px 0 0 0
|
|
72
|
-
inset 0 -13px 0 0
|
|
73
|
-
color:
|
|
67
|
+
background-color: var(--ons-color-focus);
|
|
68
|
+
border-bottom: 1px solid var(--ons-color-borders);
|
|
69
|
+
box-shadow: inset 0 0 0 9px var(--ons-color-button-secondary),
|
|
70
|
+
inset 17px 0 0 0 var(--ons-color-button-secondary),
|
|
71
|
+
inset -17px 0 0 0 var(--ons-color-button-secondary),
|
|
72
|
+
inset 0 -13px 0 0 var(--ons-color-text-link-focus);
|
|
73
|
+
color: var(--ons-color-text-link-focus);
|
|
74
74
|
|
|
75
75
|
// Add transparent outline because Windows High Contrast Mode doesn't show box-shadows
|
|
76
76
|
outline: 3px solid transparent;
|
|
77
77
|
outline-offset: 1px;
|
|
78
|
-
text-decoration: underline solid
|
|
78
|
+
text-decoration: underline solid var(--ons-color-text) 2px;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// Tab when selected
|
|
82
82
|
&[aria-selected='true'] {
|
|
83
|
-
background-color:
|
|
83
|
+
background-color: var(--ons-color-page-light);
|
|
84
84
|
border-bottom: none;
|
|
85
|
-
border-color:
|
|
85
|
+
border-color: var(--ons-color-borders);
|
|
86
86
|
border-radius: 3px 3px 0 0;
|
|
87
87
|
text-decoration: none;
|
|
88
88
|
z-index: 1;
|
|
89
89
|
|
|
90
90
|
&:focus {
|
|
91
|
-
background-color:
|
|
92
|
-
box-shadow: inset 0 0 0 9px
|
|
93
|
-
inset 17px 0 0 0
|
|
94
|
-
inset -17px 0 0 0
|
|
95
|
-
inset 0 -13px 0 0
|
|
91
|
+
background-color: var(--ons-color-focus);
|
|
92
|
+
box-shadow: inset 0 0 0 9px var(--ons-color-page-light),
|
|
93
|
+
inset 17px 0 0 0 var(--ons-color-page-light),
|
|
94
|
+
inset -17px 0 0 0 var(--ons-color-page-light),
|
|
95
|
+
inset 0 -13px 0 0 var(--ons-color-text-link-focus);
|
|
96
96
|
text-decoration: none;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -109,8 +109,40 @@
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
&:focus {
|
|
112
|
-
box-shadow: 0 0 0 3px
|
|
112
|
+
box-shadow: 0 0 0 3px var(--ons-color-page-light), 0 0 0 5px var(--ons-color-text-link-focus), 0 0 0 8px var(--ons-color-focus);
|
|
113
113
|
outline: 3px solid transparent; // Add transparent outline because Windows High Contrast Mode doesn't show box-shadows
|
|
114
114
|
z-index: 1;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
|
|
118
|
+
.ons-tabs--details {
|
|
119
|
+
border-top: 1px solid var(--ons-color-borders);
|
|
120
|
+
margin: 0;
|
|
121
|
+
|
|
122
|
+
.ons-tab {
|
|
123
|
+
border-radius: 0;
|
|
124
|
+
border-top: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.ons-tab__list-item:first-child .ons-tab {
|
|
128
|
+
border-left: none;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.ons-tabs__title {
|
|
132
|
+
padding: 1rem 1rem 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.ons-tabs__list {
|
|
136
|
+
padding: 0 1rem;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.ons-tabs__list--row {
|
|
140
|
+
margin-bottom: -1px;
|
|
141
|
+
padding: 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.ons-tabs__panel {
|
|
145
|
+
margin-top: 1px;
|
|
146
|
+
padding: 1rem;
|
|
147
|
+
}
|
|
148
|
+
}
|
package/components/tabs/tabs.js
CHANGED
|
@@ -30,6 +30,8 @@ export default class Tabs {
|
|
|
30
30
|
this.jsTabItemAsRowClass = 'ons-tab__list-item--row';
|
|
31
31
|
this.jsTabAsListClass = 'ons-tab--row';
|
|
32
32
|
|
|
33
|
+
this.noInitialActiveTab = this.component.getAttribute('data-no-initial-active-tab');
|
|
34
|
+
|
|
33
35
|
if (matchMediaUtil.hasMatchMedia()) {
|
|
34
36
|
this.setupViewportChecks();
|
|
35
37
|
} else {
|
|
@@ -39,10 +41,10 @@ export default class Tabs {
|
|
|
39
41
|
|
|
40
42
|
// Set up checks for responsive functionality
|
|
41
43
|
// The tabs will display as tabs for >40rem viewports
|
|
42
|
-
// Tabs will display as a TOC list and show full content for <
|
|
43
|
-
// Aria tags are added only for >
|
|
44
|
+
// Tabs will display as a TOC list and show full content for <740px viewports
|
|
45
|
+
// Aria tags are added only for >740px viewports
|
|
44
46
|
setupViewportChecks() {
|
|
45
|
-
this.viewport = matchMediaUtil('(min-width:
|
|
47
|
+
this.viewport = matchMediaUtil('(min-width: 740px)');
|
|
46
48
|
this.viewport.addListener(this.checkViewport.bind(this));
|
|
47
49
|
this.checkViewport();
|
|
48
50
|
}
|
|
@@ -79,8 +81,12 @@ export default class Tabs {
|
|
|
79
81
|
this.hideTab(tab);
|
|
80
82
|
});
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
if (!this.noInitialActiveTab) {
|
|
85
|
+
const activeTab = this.getTab(window.location.hash) || this.tabs[0];
|
|
86
|
+
this.showTab(activeTab);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.ensureTabIndexExists();
|
|
84
90
|
|
|
85
91
|
this.component.boundOnHashChange = this.onHashChange.bind(this);
|
|
86
92
|
window.addEventListener('hashchange', this.component.boundOnHashChange, true);
|
|
@@ -124,9 +130,10 @@ export default class Tabs {
|
|
|
124
130
|
return;
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
const currentTab = this.getCurrentTab();
|
|
134
|
+
if (!!currentTab) {
|
|
135
|
+
this.hideTab(currentTab);
|
|
136
|
+
}
|
|
130
137
|
this.showTab(tabWithHash);
|
|
131
138
|
tabWithHash.focus();
|
|
132
139
|
}
|
|
@@ -177,9 +184,24 @@ export default class Tabs {
|
|
|
177
184
|
e.preventDefault();
|
|
178
185
|
const newTab = e.target;
|
|
179
186
|
const currentTab = this.getCurrentTab();
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
187
|
+
|
|
188
|
+
if (!!currentTab) {
|
|
189
|
+
this.hideTab(currentTab);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!this.noInitialActiveTab || newTab !== currentTab) {
|
|
193
|
+
this.showTab(newTab);
|
|
194
|
+
this.createHash(newTab);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
this.ensureTabIndexExists();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
ensureTabIndexExists() {
|
|
201
|
+
// Ensure that at least the first tab has a tab index when all tabs are hidden.
|
|
202
|
+
if (!this.tabs.find(tab => tab.getAttribute('tabindex') === '0')) {
|
|
203
|
+
this.tabs[0].setAttribute('tabindex', '0');
|
|
204
|
+
}
|
|
183
205
|
}
|
|
184
206
|
|
|
185
207
|
createHash(tab) {
|
|
@@ -220,7 +242,8 @@ export default class Tabs {
|
|
|
220
242
|
}
|
|
221
243
|
|
|
222
244
|
getPanel(tab) {
|
|
223
|
-
const
|
|
245
|
+
const panelSelector = this.getHref(tab).replace(/\./g, '\\.');
|
|
246
|
+
const panel = this.component.querySelector(panelSelector);
|
|
224
247
|
return panel;
|
|
225
248
|
}
|
|
226
249
|
|
|
@@ -7,20 +7,28 @@ const EXAMPLE_TABS = {
|
|
|
7
7
|
title: 'Example tabs',
|
|
8
8
|
tabs: [
|
|
9
9
|
{
|
|
10
|
+
id: 'tab.id.1',
|
|
10
11
|
title: 'Tab 1',
|
|
11
12
|
content: 'First content...',
|
|
12
13
|
},
|
|
13
14
|
{
|
|
15
|
+
id: 'tab.id.2',
|
|
14
16
|
title: 'Tab 2',
|
|
15
17
|
content: 'Second content...',
|
|
16
18
|
},
|
|
17
19
|
{
|
|
20
|
+
id: 'tab.id.3',
|
|
18
21
|
title: 'Tab 3',
|
|
19
22
|
content: 'Third content...',
|
|
20
23
|
},
|
|
21
24
|
],
|
|
22
25
|
};
|
|
23
26
|
|
|
27
|
+
const EXAMPLE_TABS_WITH_NO_INITIAL_ACTIVE_TAB = {
|
|
28
|
+
...EXAMPLE_TABS,
|
|
29
|
+
noInitialActiveTab: true,
|
|
30
|
+
};
|
|
31
|
+
|
|
24
32
|
describe('script: tabs', () => {
|
|
25
33
|
afterEach(async () => {
|
|
26
34
|
// Clear viewport size and browser emulation after each test.
|
|
@@ -47,7 +55,7 @@ describe('script: tabs', () => {
|
|
|
47
55
|
it('has "aria-controls" assigned to each tab with the corresponding panel id', async () => {
|
|
48
56
|
const ariaControlsValues = await page.$$eval('.ons-tab', nodes => nodes.map(node => node.getAttribute('aria-controls')));
|
|
49
57
|
|
|
50
|
-
expect(ariaControlsValues).toEqual(['
|
|
58
|
+
expect(ariaControlsValues).toEqual(['tab.id.1', 'tab.id.2', 'tab.id.3']);
|
|
51
59
|
});
|
|
52
60
|
|
|
53
61
|
it('has "aria-selected" assigned to the first tab', async () => {
|
|
@@ -78,7 +86,7 @@ describe('script: tabs', () => {
|
|
|
78
86
|
|
|
79
87
|
describe('when a tab is clicked', () => {
|
|
80
88
|
beforeEach(async () => {
|
|
81
|
-
await page.focus('#
|
|
89
|
+
await page.focus('a[href="#tab.id.2"]');
|
|
82
90
|
await page.keyboard.press('Enter');
|
|
83
91
|
});
|
|
84
92
|
|
|
@@ -89,13 +97,13 @@ describe('script: tabs', () => {
|
|
|
89
97
|
});
|
|
90
98
|
|
|
91
99
|
it('has the "aria-selected" attribute', async () => {
|
|
92
|
-
const ariaSelectedValue = await page.$eval('#
|
|
100
|
+
const ariaSelectedValue = await page.$eval('a[href="#tab.id.2"]', node => node.getAttribute('aria-selected'));
|
|
93
101
|
|
|
94
102
|
expect(ariaSelectedValue).toBe('true');
|
|
95
103
|
});
|
|
96
104
|
|
|
97
105
|
it('has the "ons-tab--selected" class assigned', async () => {
|
|
98
|
-
const hasClass = await page.$eval('#
|
|
106
|
+
const hasClass = await page.$eval('a[href="#tab.id.2"]', node => node.classList.contains('ons-tab--selected'));
|
|
99
107
|
|
|
100
108
|
expect(hasClass).toBe(true);
|
|
101
109
|
});
|
|
@@ -111,21 +119,21 @@ describe('script: tabs', () => {
|
|
|
111
119
|
|
|
112
120
|
describe('when the right arrow key is pressed', () => {
|
|
113
121
|
it('focuses the next tab', async () => {
|
|
114
|
-
await page.focus('#
|
|
122
|
+
await page.focus('a[href="#tab.id.2"]');
|
|
115
123
|
await page.keyboard.press('ArrowRight');
|
|
116
124
|
|
|
117
|
-
const
|
|
118
|
-
expect(
|
|
125
|
+
const activeElement = await page.evaluate(() => document.activeElement.innerText);
|
|
126
|
+
expect(activeElement).toBe('Tab 3');
|
|
119
127
|
});
|
|
120
128
|
});
|
|
121
129
|
|
|
122
130
|
describe('when the left arrow key is pressed', () => {
|
|
123
131
|
it('focuses the previous tab', async () => {
|
|
124
|
-
await page.focus('#
|
|
132
|
+
await page.focus('a[href="#tab.id.2"]');
|
|
125
133
|
await page.keyboard.press('ArrowLeft');
|
|
126
134
|
|
|
127
|
-
const
|
|
128
|
-
expect(
|
|
135
|
+
const activeElement = await page.evaluate(() => document.activeElement.innerText);
|
|
136
|
+
expect(activeElement).toBe('Tab 1');
|
|
129
137
|
});
|
|
130
138
|
});
|
|
131
139
|
});
|
|
@@ -159,4 +167,90 @@ describe('script: tabs', () => {
|
|
|
159
167
|
expect(hiddenPanelCount).toBe(0);
|
|
160
168
|
});
|
|
161
169
|
});
|
|
170
|
+
|
|
171
|
+
describe('when `data-no-initial-active-tab` is not present', () => {
|
|
172
|
+
beforeEach(async () => {
|
|
173
|
+
await setViewport(page, { width: 1650, height: 1050 });
|
|
174
|
+
await setTestPage('/test', renderComponent('tabs', EXAMPLE_TABS_WITH_NO_INITIAL_ACTIVE_TAB));
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('does not assign "aria-selected" to the first tab', async () => {
|
|
178
|
+
const ariaSelectedValue = await page.$eval('.ons-tab', node => node.getAttribute('aria-selected'));
|
|
179
|
+
|
|
180
|
+
expect(ariaSelectedValue).not.toBe('true');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('does not assign the "ons-tab--selected" class to the first tab', async () => {
|
|
184
|
+
const hasClass = await page.$eval('.ons-tab', node => node.classList.contains('ons-tab--selected'));
|
|
185
|
+
|
|
186
|
+
expect(hasClass).toBe(false);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('when a tab is clicked', () => {
|
|
190
|
+
beforeEach(async () => {
|
|
191
|
+
await page.focus('a[href="#tab.id.1"]');
|
|
192
|
+
await page.keyboard.press('Enter');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('is assigned a "tabindex" value', async () => {
|
|
196
|
+
const tabIndexValues = await page.$$eval('.ons-tab', nodes => nodes.map(node => node.getAttribute('tabindex')));
|
|
197
|
+
|
|
198
|
+
expect(tabIndexValues).toEqual(['0', '-1', '-1']);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('has the "aria-selected" attribute', async () => {
|
|
202
|
+
const ariaSelectedValue = await page.$eval('a[href="#tab.id.1"]', node => node.getAttribute('aria-selected'));
|
|
203
|
+
|
|
204
|
+
expect(ariaSelectedValue).toBe('true');
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('has the "ons-tab--selected" class assigned', async () => {
|
|
208
|
+
const hasClass = await page.$eval('a[href="#tab.id.1"]', node => node.classList.contains('ons-tab--selected'));
|
|
209
|
+
|
|
210
|
+
expect(hasClass).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('shows the corresponding panel', async () => {
|
|
214
|
+
const panelHiddenStates = await page.$$eval('.ons-tabs__panel', nodes =>
|
|
215
|
+
nodes.map(node => node.classList.contains('ons-tabs__panel--hidden')),
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
expect(panelHiddenStates).toEqual([false, true, true]);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('when a tab is clicked twice', () => {
|
|
223
|
+
beforeEach(async () => {
|
|
224
|
+
await page.focus('a[href="#tab.id.2"]');
|
|
225
|
+
await page.keyboard.press('Enter');
|
|
226
|
+
await page.keyboard.press('Enter');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('is assigned a "tabindex" value', async () => {
|
|
230
|
+
const tabIndexValues = await page.$$eval('.ons-tab', nodes => nodes.map(node => node.getAttribute('tabindex')));
|
|
231
|
+
|
|
232
|
+
expect(tabIndexValues).toEqual(['0', '-1', '-1']);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('does not have the "aria-selected" attribute', async () => {
|
|
236
|
+
const ariaSelectedValue = await page.$eval('a[href="#tab.id.2"]', node => node.getAttribute('aria-selected'));
|
|
237
|
+
|
|
238
|
+
expect(ariaSelectedValue).not.toBe('true');
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('does not have the "ons-tab--selected" class assigned', async () => {
|
|
242
|
+
const hasClass = await page.$eval('a[href="#tab.id.2"]', node => node.classList.contains('ons-tab--selected'));
|
|
243
|
+
|
|
244
|
+
expect(hasClass).toBe(false);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('hides the corresponding panel', async () => {
|
|
248
|
+
const panelHiddenStates = await page.$$eval('.ons-tabs__panel', nodes =>
|
|
249
|
+
nodes.map(node => node.classList.contains('ons-tabs__panel--hidden')),
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
expect(panelHiddenStates).toEqual([true, true, true]);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
162
256
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
position: relative;
|
|
4
4
|
|
|
5
5
|
&::before {
|
|
6
|
-
border-left: 4px solid
|
|
6
|
+
border-left: 4px solid var(--ons-color-black);
|
|
7
7
|
content: '';
|
|
8
8
|
height: 100%;
|
|
9
9
|
left: 0;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
position: relative;
|
|
18
18
|
|
|
19
19
|
&::before {
|
|
20
|
-
background-color:
|
|
20
|
+
background-color: var(--ons-color-black);
|
|
21
21
|
content: '';
|
|
22
22
|
height: 4px;
|
|
23
23
|
left: -1.5rem;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
.ons-input--upload {
|
|
2
|
-
background:
|
|
3
|
-
border: 1px solid
|
|
2
|
+
background: var(--ons-color-white);
|
|
3
|
+
border: 1px solid var(--ons-color-input-border);
|
|
4
4
|
border-radius: $input-radius;
|
|
5
5
|
font-size: 1rem;
|
|
6
6
|
padding: 0;
|
|
7
7
|
width: 100%;
|
|
8
8
|
&::-webkit-file-upload-button {
|
|
9
|
-
background:
|
|
9
|
+
background: var(--ons-color-button-secondary);
|
|
10
10
|
border: 0;
|
|
11
11
|
border-bottom-right-radius: 0;
|
|
12
|
-
border-right: 1px solid
|
|
12
|
+
border-right: 1px solid var(--ons-color-input-border);
|
|
13
13
|
border-top-right-radius: 0;
|
|
14
|
-
color:
|
|
14
|
+
color: var(--ons-color-text);
|
|
15
15
|
font-size: 1rem;
|
|
16
16
|
outline: none;
|
|
17
17
|
padding: 0.5rem 1rem;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
&:hover {
|
|
21
21
|
cursor: pointer;
|
|
22
22
|
&::-webkit-file-upload-button {
|
|
23
|
-
border-right-color:
|
|
23
|
+
border-right-color: var(--ons-color-text-link-hover);
|
|
24
24
|
cursor: pointer;
|
|
25
25
|
}
|
|
26
26
|
}
|