testaro 1.0.0
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/LICENSE +21 -0
- package/README.md +502 -0
- package/aceconfig.js +7 -0
- package/commands.js +249 -0
- package/index.js +1248 -0
- package/package.json +39 -0
- package/procs/score/asp09.js +555 -0
- package/procs/test/allText.js +76 -0
- package/procs/test/allVis.js +17 -0
- package/procs/test/linksByType.js +90 -0
- package/procs/test/textOf.txt +73 -0
- package/scoring/correlation.js +74 -0
- package/scoring/correlations.json +327 -0
- package/scoring/data.json +26021 -0
- package/scoring/dupCounts.js +39 -0
- package/scoring/dupCounts.json +112 -0
- package/scoring/duplications.json +253 -0
- package/scoring/issues.json +304 -0
- package/scoring/packageData.js +171 -0
- package/scoring/packageIssues.js +34 -0
- package/scoring/rulesetData.json +15 -0
- package/tests/aatt.js +64 -0
- package/tests/alfa.js +107 -0
- package/tests/axe.js +109 -0
- package/tests/bulk.js +21 -0
- package/tests/embAc.js +36 -0
- package/tests/focAll.js +62 -0
- package/tests/focInd.js +99 -0
- package/tests/focOp.js +132 -0
- package/tests/hover.js +195 -0
- package/tests/ibm.js +89 -0
- package/tests/labClash.js +157 -0
- package/tests/linkUl.js +65 -0
- package/tests/menuNav.js +254 -0
- package/tests/motion.js +115 -0
- package/tests/radioSet.js +87 -0
- package/tests/role.js +164 -0
- package/tests/styleDiff.js +146 -0
- package/tests/tabNav.js +282 -0
- package/tests/wave.js +44 -0
- package/tests/zIndex.js +49 -0
- package/validation/batches/sample.json +13 -0
- package/validation/executors/sample.js +11 -0
- package/validation/scripts/app/sample.json +21 -0
- package/validation/scripts/test/bulk.json +39 -0
- package/validation/scripts/test/embAc.json +45 -0
- package/validation/scripts/test/focAll.json +59 -0
- package/validation/scripts/test/focInd.json +55 -0
- package/validation/scripts/test/focOp.json +53 -0
- package/validation/scripts/test/hover.json +47 -0
- package/validation/scripts/test/labClash.json +43 -0
- package/validation/scripts/test/linkUl.json +62 -0
- package/validation/scripts/test/menuNav.json +97 -0
- package/validation/scripts/test/motion.json +53 -0
- package/validation/scripts/test/radioSet.json +43 -0
- package/validation/scripts/test/role.json +42 -0
- package/validation/scripts/test/styleDiff.json +61 -0
- package/validation/scripts/test/tabNav.json +97 -0
- package/validation/scripts/test/zIndex.json +40 -0
- package/validation/targets/bulk/bad.html +48 -0
- package/validation/targets/bulk/good.html +15 -0
- package/validation/targets/embAc/bad.html +21 -0
- package/validation/targets/embAc/good.html +15 -0
- package/validation/targets/focAll/good.html +15 -0
- package/validation/targets/focAll/less.html +15 -0
- package/validation/targets/focAll/more.html +16 -0
- package/validation/targets/focInd/bad.html +31 -0
- package/validation/targets/focInd/good.html +22 -0
- package/validation/targets/focOp/bad.html +18 -0
- package/validation/targets/focOp/good.html +15 -0
- package/validation/targets/hover/bad.html +19 -0
- package/validation/targets/hover/good.html +15 -0
- package/validation/targets/labClash/bad.html +20 -0
- package/validation/targets/labClash/good.html +18 -0
- package/validation/targets/linkUl/bad.html +16 -0
- package/validation/targets/linkUl/good.html +30 -0
- package/validation/targets/linkUl/na.html +20 -0
- package/validation/targets/menuNav/bad.html +106 -0
- package/validation/targets/menuNav/bad.js +348 -0
- package/validation/targets/menuNav/good.html +106 -0
- package/validation/targets/menuNav/good.js +365 -0
- package/validation/targets/menuNav/style.css +22 -0
- package/validation/targets/motion/bad.css +15 -0
- package/validation/targets/motion/bad.html +16 -0
- package/validation/targets/motion/good.html +15 -0
- package/validation/targets/radioSet/bad.html +34 -0
- package/validation/targets/radioSet/good.html +27 -0
- package/validation/targets/role/bad.html +26 -0
- package/validation/targets/role/good.html +22 -0
- package/validation/targets/styleDiff/bad.html +35 -0
- package/validation/targets/styleDiff/good.html +36 -0
- package/validation/targets/tabNav/bad.html +51 -0
- package/validation/targets/tabNav/bad.js +35 -0
- package/validation/targets/tabNav/good.html +53 -0
- package/validation/targets/tabNav/good.js +83 -0
- package/validation/targets/tabNav/goodMoz.js +206 -0
- package/validation/targets/tabNav/style.css +34 -0
- package/validation/targets/zIndex/bad.html +17 -0
- package/validation/targets/zIndex/good.html +15 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// UTILITIES FOR EVENT HANDLERS
|
|
2
|
+
|
|
3
|
+
// Returns the tab list containing a tab.
|
|
4
|
+
const allTabs = button => Array.from(button.parentElement.children);
|
|
5
|
+
// Returns the panel controlled by a tab.
|
|
6
|
+
const controlledPanel = button => document.getElementById(button.getAttribute('aria-controls'));
|
|
7
|
+
// Returns the tab panels controlled by the tabs of a tab list.
|
|
8
|
+
const allPanels = button => Array.from(controlledPanel(button).parentElement.children);
|
|
9
|
+
// Exposes only the tab panel controlled by a button.
|
|
10
|
+
const showPanel = button => {
|
|
11
|
+
allPanels(button).forEach(panel => {
|
|
12
|
+
panel.setAttribute('hidden', '');
|
|
13
|
+
});
|
|
14
|
+
controlledPanel(button).removeAttribute('hidden');
|
|
15
|
+
};
|
|
16
|
+
// Makes a tab active.
|
|
17
|
+
const makeActive = button => {
|
|
18
|
+
allTabs(button).forEach(tab => {
|
|
19
|
+
tab.classList.remove('active');
|
|
20
|
+
});
|
|
21
|
+
button.classList.add('active');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// EVENT LISTENERS
|
|
25
|
+
|
|
26
|
+
// Handle tab focusing.
|
|
27
|
+
const documentTabs = Array.from(document.body.querySelectorAll('[role=tab]'));
|
|
28
|
+
documentTabs.forEach(tab => {
|
|
29
|
+
tab.addEventListener('focus', () => {
|
|
30
|
+
showPanel(tab);
|
|
31
|
+
if (tab.tabIndex !== 0 || ! tab.classList.contains('active')) {
|
|
32
|
+
makeActive(tab);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Page with standard tab-list navigation</title>
|
|
6
|
+
<meta name="description" content="tester">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
<link rel="stylesheet" href="style.css">
|
|
9
|
+
<script src="good.js" defer></script>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<main>
|
|
13
|
+
<h1>Page with standard tab-list navigation</h1>
|
|
14
|
+
<div class="tabs">
|
|
15
|
+
<p id="tabListLabel">What kind of HTML element do you want to study?</p>
|
|
16
|
+
<div role="tablist" aria-labelledby="tabListLabel">
|
|
17
|
+
<button role="tab" aria-selected="true" aria-controls="ulDoc" id="ul">
|
|
18
|
+
<code>ul</code>
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
role="tab"
|
|
22
|
+
aria-selected="false"
|
|
23
|
+
aria-controls="sectionDoc"
|
|
24
|
+
id="section"
|
|
25
|
+
tabindex="-1"
|
|
26
|
+
>
|
|
27
|
+
<code>section</code>
|
|
28
|
+
</button>
|
|
29
|
+
<button
|
|
30
|
+
role="tab"
|
|
31
|
+
aria-selected="false"
|
|
32
|
+
aria-controls="mainDoc"
|
|
33
|
+
id="main"
|
|
34
|
+
tabindex="-1"
|
|
35
|
+
>
|
|
36
|
+
<code>main</code>
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="tabPanels">
|
|
40
|
+
<div tabindex="0" role="tabpanel" id="ulDoc" aria-labelledby="ul" hidden>
|
|
41
|
+
<p>A <code>ul</code> element encodes an unordered list.</p>
|
|
42
|
+
</div>
|
|
43
|
+
<div tabindex="0" role="tabpanel" id="sectionDoc" aria-labelledby="section" hidden>
|
|
44
|
+
<p>A <code>section</code> element encodes a generic part of a document.</p>
|
|
45
|
+
</div>
|
|
46
|
+
<div tabindex="0" role="tabpanel" id="mainDoc" aria-labelledby="main" hidden>
|
|
47
|
+
<p>A <code>main</code> element encodes the dominant content of a document.</p>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</main>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// UTILITIES FOR EVENT HANDLERS
|
|
2
|
+
|
|
3
|
+
// Returns whether an element is a tab.
|
|
4
|
+
const isTab = element => element.getAttribute('role') === 'tab';
|
|
5
|
+
// Returns the tab list containing a tab.
|
|
6
|
+
const allTabs = button => Array.from(button.parentElement.children);
|
|
7
|
+
// Returns the panel controlled by a tab.
|
|
8
|
+
const controlledPanel = button => document.getElementById(button.getAttribute('aria-controls'));
|
|
9
|
+
// Returns the tab panels controlled by the tabs of a tab list.
|
|
10
|
+
const allPanels = button => Array.from(controlledPanel(button).parentElement.children);
|
|
11
|
+
// Exposes only the tab panel controlled by a button.
|
|
12
|
+
const showPanel = button => {
|
|
13
|
+
allPanels(button).forEach(panel => {
|
|
14
|
+
panel.setAttribute('hidden', '');
|
|
15
|
+
});
|
|
16
|
+
controlledPanel(button).removeAttribute('hidden');
|
|
17
|
+
};
|
|
18
|
+
// Makes a tab active.
|
|
19
|
+
const makeActive = button => {
|
|
20
|
+
allTabs(button).forEach(tab => {
|
|
21
|
+
tab.tabIndex = -1;
|
|
22
|
+
tab.classList.remove('active');
|
|
23
|
+
});
|
|
24
|
+
button.tabIndex = 0;
|
|
25
|
+
button.classList.add('active');
|
|
26
|
+
};
|
|
27
|
+
// Returns the destination of a keyboard navigation within a tab list.
|
|
28
|
+
const destinationTab = (fromTab, key) => {
|
|
29
|
+
const tabs = allTabs(fromTab);
|
|
30
|
+
const tabCount = tabs.length;
|
|
31
|
+
const fromIndex = tabs.indexOf(fromTab);
|
|
32
|
+
// Return the destination of navigation.
|
|
33
|
+
if (key === 'ArrowRight') {
|
|
34
|
+
return tabs[(fromIndex + 1) % tabCount];
|
|
35
|
+
}
|
|
36
|
+
else if (key === 'ArrowLeft') {
|
|
37
|
+
return tabs[(tabCount + fromIndex - 1) % tabCount];
|
|
38
|
+
}
|
|
39
|
+
else if (key === 'Home') {
|
|
40
|
+
return tabs[0];
|
|
41
|
+
}
|
|
42
|
+
else if (key === 'End') {
|
|
43
|
+
return tabs[tabCount - 1];
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// EVENT LISTENERS
|
|
51
|
+
|
|
52
|
+
// Handle key presses.
|
|
53
|
+
window.addEventListener('keydown', event => {
|
|
54
|
+
const key = event.key;
|
|
55
|
+
// If no ineligible modifier key was in effect when the key was depressed:
|
|
56
|
+
if (! (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)) {
|
|
57
|
+
// Initialize the focused element.
|
|
58
|
+
let focus = document.activeElement;
|
|
59
|
+
// If it exists and is within the body:
|
|
60
|
+
if (focus && focus !== document.body) {
|
|
61
|
+
// If it is a tab:
|
|
62
|
+
if (isTab(focus)) {
|
|
63
|
+
// Identify the destination tab.
|
|
64
|
+
const newFocus = destinationTab(focus, key);
|
|
65
|
+
// If it differs from the currently focused element:
|
|
66
|
+
if (newFocus && newFocus !== focus) {
|
|
67
|
+
// Focus it.
|
|
68
|
+
newFocus.focus();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Handle tab focusing.
|
|
75
|
+
const documentTabs = Array.from(document.body.querySelectorAll('[role=tab]'));
|
|
76
|
+
documentTabs.forEach(tab => {
|
|
77
|
+
tab.addEventListener('focus', () => {
|
|
78
|
+
showPanel(tab);
|
|
79
|
+
if (tab.tabIndex !== 0 || ! tab.classList.contains('active')) {
|
|
80
|
+
makeActive(tab);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This content is licensed according to the W3C Software License at
|
|
3
|
+
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
|
|
4
|
+
*/
|
|
5
|
+
const manageTabs = () => {
|
|
6
|
+
const tablist = document.querySelectorAll('[role="tablist"]')[0];
|
|
7
|
+
let tabs;
|
|
8
|
+
let panels;
|
|
9
|
+
|
|
10
|
+
const generateArrays = () => {
|
|
11
|
+
tabs = document.querySelectorAll('[role="tab"]');
|
|
12
|
+
panels = document.querySelectorAll('[role="tabpanel"]');
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
generateArrays();
|
|
16
|
+
|
|
17
|
+
// For easy reference
|
|
18
|
+
const keys = {
|
|
19
|
+
end: 35,
|
|
20
|
+
home: 36,
|
|
21
|
+
left: 37,
|
|
22
|
+
up: 38,
|
|
23
|
+
right: 39,
|
|
24
|
+
down: 40
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Add or substract depending on key pressed
|
|
28
|
+
const direction = {
|
|
29
|
+
37: -1,
|
|
30
|
+
38: -1,
|
|
31
|
+
39: 1,
|
|
32
|
+
40: 1
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// When a tab is clicked, activateTab is fired to activate it
|
|
36
|
+
const clickEventListener = event => {
|
|
37
|
+
const tab = event.target;
|
|
38
|
+
activateTab(tab, false);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Handle keydown on tabs
|
|
42
|
+
const keydownEventListener = event => {
|
|
43
|
+
const key = event.keyCode;
|
|
44
|
+
|
|
45
|
+
switch (key) {
|
|
46
|
+
case keys.end:
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
// Activate last tab
|
|
49
|
+
activateTab(tabs[tabs.length - 1]);
|
|
50
|
+
break;
|
|
51
|
+
case keys.home:
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
// Activate first tab
|
|
54
|
+
activateTab(tabs[0]);
|
|
55
|
+
break;
|
|
56
|
+
|
|
57
|
+
// Up and down are in keydown
|
|
58
|
+
// because we need to prevent page scroll >:)
|
|
59
|
+
case keys.up:
|
|
60
|
+
case keys.down:
|
|
61
|
+
determineOrientation(event);
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Handle keyup on tabs
|
|
67
|
+
const keyupEventListener = event => {
|
|
68
|
+
const key = event.keyCode;
|
|
69
|
+
|
|
70
|
+
switch (key) {
|
|
71
|
+
case keys.left:
|
|
72
|
+
case keys.right:
|
|
73
|
+
determineOrientation(event);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const addListeners = index => {
|
|
79
|
+
tabs[index].addEventListener('click', clickEventListener);
|
|
80
|
+
tabs[index].addEventListener('keydown', keydownEventListener);
|
|
81
|
+
tabs[index].addEventListener('keyup', keyupEventListener);
|
|
82
|
+
|
|
83
|
+
// Build an array with all tabs (<button>s) in it
|
|
84
|
+
tabs[index].index = index;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Bind listeners
|
|
88
|
+
for (let i = 0; i < tabs.length; ++i) {
|
|
89
|
+
addListeners(i);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// When a tablist’s aria-orientation is set to vertical,
|
|
93
|
+
// only up and down arrow should function.
|
|
94
|
+
// In all other cases only left and right arrow function.
|
|
95
|
+
const determineOrientation = event => {
|
|
96
|
+
const key = event.keyCode;
|
|
97
|
+
const vertical = tablist.getAttribute('aria-orientation') == 'vertical';
|
|
98
|
+
let proceed = false;
|
|
99
|
+
|
|
100
|
+
if (vertical) {
|
|
101
|
+
if (key === keys.up || key === keys.down) {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
proceed = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
if (key === keys.left || key === keys.right) {
|
|
108
|
+
proceed = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (proceed) {
|
|
113
|
+
switchTabOnArrowPress(event);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Either focus the next, previous, first, or last tab
|
|
118
|
+
// depening on key pressed
|
|
119
|
+
function switchTabOnArrowPress (event) {
|
|
120
|
+
const pressed = event.keyCode;
|
|
121
|
+
|
|
122
|
+
for (let x = 0; x < tabs.length; x++) {
|
|
123
|
+
tabs[x].addEventListener('focus', focusEventHandler);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (direction[pressed]) {
|
|
127
|
+
const target = event.target;
|
|
128
|
+
if (target.index !== undefined) {
|
|
129
|
+
if (tabs[target.index + direction[pressed]]) {
|
|
130
|
+
tabs[target.index + direction[pressed]].focus();
|
|
131
|
+
}
|
|
132
|
+
else if (pressed === keys.left || pressed === keys.up) {
|
|
133
|
+
focusLastTab();
|
|
134
|
+
}
|
|
135
|
+
else if (pressed === keys.right || pressed == keys.down) {
|
|
136
|
+
focusFirstTab();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Activates any given tab panel
|
|
143
|
+
const activateTab = (tab, setFocus) => {
|
|
144
|
+
setFocus = setFocus || true;
|
|
145
|
+
// Deactivate all other tabs
|
|
146
|
+
deactivateTabs();
|
|
147
|
+
|
|
148
|
+
// Remove tabindex attribute
|
|
149
|
+
tab.removeAttribute('tabindex');
|
|
150
|
+
|
|
151
|
+
// Set the tab as selected
|
|
152
|
+
tab.setAttribute('aria-selected', 'true');
|
|
153
|
+
|
|
154
|
+
// Get the value of aria-controls (which is an ID)
|
|
155
|
+
var controls = tab.getAttribute('aria-controls');
|
|
156
|
+
|
|
157
|
+
// Remove hidden attribute from tab panel to make it visible
|
|
158
|
+
document.getElementById(controls).removeAttribute('hidden');
|
|
159
|
+
|
|
160
|
+
// Set focus when required
|
|
161
|
+
if (setFocus) {
|
|
162
|
+
tab.focus();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Deactivate all tabs and tab panels
|
|
167
|
+
const deactivateTabs = () => {
|
|
168
|
+
for (let t = 0; t < tabs.length; t++) {
|
|
169
|
+
tabs[t].setAttribute('tabindex', '-1');
|
|
170
|
+
tabs[t].setAttribute('aria-selected', 'false');
|
|
171
|
+
tabs[t].removeEventListener('focus', focusEventHandler);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (let p = 0; p < panels.length; p++) {
|
|
175
|
+
panels[p].setAttribute('hidden', 'hidden');
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Make a guess
|
|
180
|
+
const focusFirstTab = () => {
|
|
181
|
+
tabs[0].focus();
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Make a guess
|
|
185
|
+
const focusLastTab = () => {
|
|
186
|
+
tabs[tabs.length - 1].focus();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
//
|
|
190
|
+
const focusEventHandler = event => {
|
|
191
|
+
const target = event.target;
|
|
192
|
+
|
|
193
|
+
setTimeout(checkTabFocus, 0, target);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Only activate tab on focus if it still has focus after the delay
|
|
197
|
+
const checkTabFocus = target => {
|
|
198
|
+
const focused = document.activeElement;
|
|
199
|
+
|
|
200
|
+
if (target === focused) {
|
|
201
|
+
activateTab(target, false);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
manageTabs();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
button {
|
|
2
|
+
min-width: 30%;
|
|
3
|
+
border-width: 3px;
|
|
4
|
+
background-color: #eee;
|
|
5
|
+
font-size: x-large;
|
|
6
|
+
}
|
|
7
|
+
button.active {
|
|
8
|
+
border-bottom: none;
|
|
9
|
+
}
|
|
10
|
+
button.active, .tabPanels {
|
|
11
|
+
background-color: #dfd;
|
|
12
|
+
}
|
|
13
|
+
:focus {
|
|
14
|
+
outline: 2px #00f solid;
|
|
15
|
+
outline-offset: 2px;
|
|
16
|
+
}
|
|
17
|
+
[role=tablist] {
|
|
18
|
+
margin-bottom: 0;
|
|
19
|
+
min-height: 5rem;
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: stretch;
|
|
22
|
+
justify-content: space-evenly;
|
|
23
|
+
}
|
|
24
|
+
.tabPanels {
|
|
25
|
+
margin-top:0;
|
|
26
|
+
padding: 1rem;
|
|
27
|
+
border-width: 0 3px 3px 3px;
|
|
28
|
+
}
|
|
29
|
+
.tabPanels p {
|
|
30
|
+
margin-top: 0;
|
|
31
|
+
}
|
|
32
|
+
.tabs {
|
|
33
|
+
max-width: 40rem;
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Page with explicit z-index attributes</title>
|
|
6
|
+
<meta name="description" content="tester">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<main>
|
|
11
|
+
<h1>Page with explicit z-index attributes</h1>
|
|
12
|
+
<p>The next paragraph contains two overlapping buttons.</p>
|
|
13
|
+
<p style="position: absolute; right: 10rem">
|
|
14
|
+
<button type="button" style="position: absolute; right: 0rem; min-width: 7rem; z-index: 1; background-color: #ff0">Button 0</button> <button type="button" style="position: absolute; right: 1rem; height: 4rem; min-width: 7rem; z-index: 2; background-color: #00ff0040">Button 1</button></p>
|
|
15
|
+
</main>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<title>Page without explicit z-index attributes</title>
|
|
6
|
+
<meta name="description" content="tester">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<main>
|
|
11
|
+
<h1>Page without explicit z-index attributes</h1>
|
|
12
|
+
<p>This paragraph contains two overlapping buttons. <button type="button" style="position: absolute; right: 10rem">Button 0</button> <button type="button" style="position: absolute; right: 11rem; height: 4rem; min-width: 4rem; background-color: #00ff0080">Button 1</button></p>
|
|
13
|
+
</main>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|