kempo-css 1.1.1 → 1.2.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/docs/docs.inc.html +39 -0
- package/docs/kempo.css +36 -2
- package/docs/theme-editor.html +5 -2
- package/package.json +3 -1
- package/scripts/build.js +4 -4
- package/src/kempo.css +36 -2
- package/tests/base_reset.browser-test.js +201 -0
- package/tests/buttons.browser-test.js +223 -0
- package/tests/colors.browser-test.js +221 -0
- package/tests/components.browser-test.js +144 -0
- package/tests/css_variables.browser-test.js +170 -0
- package/tests/display_flex.browser-test.js +159 -0
- package/tests/forms.browser-test.js +224 -0
- package/tests/rows_columns.browser-test.js +171 -0
- package/tests/spacing.browser-test.js +310 -0
- package/tests/tables.browser-test.js +192 -0
- package/tests/typography.browser-test.js +255 -0
package/docs/docs.inc.html
CHANGED
|
@@ -806,6 +806,45 @@
|
|
|
806
806
|
</div>
|
|
807
807
|
</div>
|
|
808
808
|
|
|
809
|
+
<h2 id="drop-shadow">Drop Shadow</h2>
|
|
810
|
+
<p>Add the <code>drop-shadow</code> class to add a box shadow effect to any element. The shadow automatically adjusts for light and dark themes.</p>
|
|
811
|
+
<div class="row -mx">
|
|
812
|
+
<div class="col m-span-12 px">
|
|
813
|
+
<k-card label="HTML">
|
|
814
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"drop-shadow"</span>></span>Drop Shadow<span class="hljs-tag"></<span class="hljs-name">div</span>></span><br /><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card drop-shadow"</span>></span>Card with Drop Shadow<span class="hljs-tag"></<span class="hljs-name">div</span>></span></code></pre>
|
|
815
|
+
</k-card>
|
|
816
|
+
</div>
|
|
817
|
+
<div class="col m-span-12 px">
|
|
818
|
+
<k-card label="Output">
|
|
819
|
+
<div class="d-ib p bg-default r drop-shadow mb">Drop Shadow</div>
|
|
820
|
+
<div class="card drop-shadow">Card with Drop Shadow</div>
|
|
821
|
+
</k-card>
|
|
822
|
+
</div>
|
|
823
|
+
</div>
|
|
824
|
+
<h3>Drop Shadow CSS Variables</h3>
|
|
825
|
+
<table>
|
|
826
|
+
<thead>
|
|
827
|
+
<tr>
|
|
828
|
+
<th>Variable</th>
|
|
829
|
+
<th>Description</th>
|
|
830
|
+
</tr>
|
|
831
|
+
</thead>
|
|
832
|
+
<tbody>
|
|
833
|
+
<tr>
|
|
834
|
+
<td><code>--drop_shadow</code></td>
|
|
835
|
+
<td>The active drop shadow (automatically set based on theme)</td>
|
|
836
|
+
</tr>
|
|
837
|
+
<tr>
|
|
838
|
+
<td><code>--drop_shadow__light</code></td>
|
|
839
|
+
<td>Drop shadow for light theme</td>
|
|
840
|
+
</tr>
|
|
841
|
+
<tr>
|
|
842
|
+
<td><code>--drop_shadow__dark</code></td>
|
|
843
|
+
<td>Drop shadow for dark theme (stronger for better visibility)</td>
|
|
844
|
+
</tr>
|
|
845
|
+
</tbody>
|
|
846
|
+
</table>
|
|
847
|
+
|
|
809
848
|
<h2 id="noScroll">Disable Body Scrolling</h2>
|
|
810
849
|
<p>Add the <code>no-scroll</code> class to the body to temparily disable body scrolling, this is used for things
|
|
811
850
|
like dialogs and side menus that temporarily take over the page.</p>
|
package/docs/kempo.css
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/*
|
|
2
|
+
CSS Variables
|
|
3
|
+
*/
|
|
1
4
|
:root {
|
|
2
5
|
color-scheme: light;
|
|
3
6
|
--ff_body: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
--c_bg__alt: light-dark(rgb(238, 238, 238), rgb(34, 34, 34));
|
|
33
36
|
--c_overscroll: light-dark(rgb(255, 255, 255), rgb(0, 0, 0));
|
|
34
37
|
--c_border: light-dark(rgb(204, 204, 204), rgb(119, 119, 119));
|
|
35
|
-
--c_border__inv: light-dark(
|
|
38
|
+
--c_border__inv: light-dark(rgb(119, 119, 119), rgb(204, 204, 204));
|
|
36
39
|
--c_primary: rgb(51, 102, 255);
|
|
37
40
|
--c_primary__hover: rgb(17, 68, 221);
|
|
38
41
|
--c_secondary: rgb(153, 51, 255);
|
|
@@ -77,7 +80,9 @@
|
|
|
77
80
|
--focus_shadow_on_primary: 0 0 2px 2px var(--tc_on_primary);
|
|
78
81
|
--input_bg: light-dark(white, var(--c_bg__alt));
|
|
79
82
|
--input_tc: light-dark(rgba(0, 0, 0, 0.93), var(--tc));
|
|
80
|
-
--
|
|
83
|
+
--drop_shadow__light: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.333);
|
|
84
|
+
--drop_shadow__dark: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.5);
|
|
85
|
+
--drop_shadow: var(--drop_shadow__light);
|
|
81
86
|
--date_picker_icon_filter: light-dark(invert(0), invert(1));
|
|
82
87
|
}
|
|
83
88
|
[theme="light"] {
|
|
@@ -86,12 +91,21 @@
|
|
|
86
91
|
|
|
87
92
|
[theme="dark"] {
|
|
88
93
|
color-scheme: dark;
|
|
94
|
+
--drop_shadow: var(--drop_shadow__dark);
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
[theme="auto"] {
|
|
92
98
|
color-scheme: light dark;
|
|
93
99
|
}
|
|
100
|
+
@media (prefers-color-scheme: dark) {
|
|
101
|
+
[theme="auto"] {
|
|
102
|
+
--drop_shadow: var(--drop_shadow__dark);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
94
105
|
|
|
106
|
+
/*
|
|
107
|
+
Base / Reset
|
|
108
|
+
*/
|
|
95
109
|
:root {
|
|
96
110
|
interpolate-size: allow-keywords;
|
|
97
111
|
}
|
|
@@ -600,6 +614,10 @@ li ul {
|
|
|
600
614
|
.m-cols-9 { grid-template-columns: repeat(9, 1fr); }
|
|
601
615
|
.m-cols-10 { grid-template-columns: repeat(10, 1fr); }
|
|
602
616
|
}
|
|
617
|
+
|
|
618
|
+
/*
|
|
619
|
+
Buttons
|
|
620
|
+
*/
|
|
603
621
|
button:not(.no-btn):not(.no-style),
|
|
604
622
|
.btn,
|
|
605
623
|
input[type="button"],
|
|
@@ -772,6 +790,10 @@ input[type="reset"].link {
|
|
|
772
790
|
display: block;
|
|
773
791
|
width: 100%;
|
|
774
792
|
}
|
|
793
|
+
|
|
794
|
+
/*
|
|
795
|
+
Forms
|
|
796
|
+
*/
|
|
775
797
|
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="radio"]):not([type="checkbox"]),
|
|
776
798
|
select,
|
|
777
799
|
textarea {
|
|
@@ -864,6 +886,10 @@ input[type="week"]::-webkit-calendar-picker-indicator,
|
|
|
864
886
|
input[type="search"]::-webkit-search-cancel-button {
|
|
865
887
|
filter: var(--date_picker_icon_filter);
|
|
866
888
|
}
|
|
889
|
+
|
|
890
|
+
/*
|
|
891
|
+
Tables
|
|
892
|
+
*/
|
|
867
893
|
.table-wrapper {
|
|
868
894
|
overflow-x: auto;
|
|
869
895
|
}
|
|
@@ -898,6 +924,10 @@ tr:last-child td:first-child {
|
|
|
898
924
|
tr:last-child td:last-child {
|
|
899
925
|
border-bottom-right-radius: var(--radius);
|
|
900
926
|
}
|
|
927
|
+
|
|
928
|
+
/*
|
|
929
|
+
Colors
|
|
930
|
+
*/
|
|
901
931
|
.bg-default {
|
|
902
932
|
background-color: var(--c_bg);
|
|
903
933
|
color: var(--tc);
|
|
@@ -1003,6 +1033,10 @@ tr:last-child td:last-child {
|
|
|
1003
1033
|
.tc-muted {
|
|
1004
1034
|
color: var(--tc_muted);
|
|
1005
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
/*
|
|
1038
|
+
Components
|
|
1039
|
+
*/
|
|
1006
1040
|
.card {
|
|
1007
1041
|
border: 1px solid var(--c_border);
|
|
1008
1042
|
border-radius: var(--radius);
|
package/docs/theme-editor.html
CHANGED
|
@@ -199,7 +199,9 @@
|
|
|
199
199
|
"--focus_shadow_on_primary": "0 0 2px 2px var(--tc_on_primary)",
|
|
200
200
|
"--input_bg": { light: "white", dark: "var(--c_bg__alt)" },
|
|
201
201
|
"--input_tc": { light: "rgba(0, 0, 0, 0.93)", dark: "var(--tc)" },
|
|
202
|
-
"--
|
|
202
|
+
"--drop_shadow__light": "0 0.25rem 0.5rem rgba(0, 0, 0, 0.333)",
|
|
203
|
+
"--drop_shadow__dark": "0 0.25rem 0.5rem rgba(0, 0, 0, 0.5)",
|
|
204
|
+
"--drop_shadow": { light: "var(--drop_shadow__light)", dark: "var(--drop_shadow__dark)" },
|
|
203
205
|
"--date_picker_icon_filter": { light: "invert(0)", dark: "invert(1)" }
|
|
204
206
|
};
|
|
205
207
|
|
|
@@ -282,7 +284,8 @@
|
|
|
282
284
|
title: 'Focus & Effects',
|
|
283
285
|
props: [
|
|
284
286
|
'--focus_shadow', '--focus_shadow_on_primary',
|
|
285
|
-
'--drop_shadow', '--
|
|
287
|
+
'--drop_shadow', '--drop_shadow__light', '--drop_shadow__dark',
|
|
288
|
+
'--date_picker_icon_filter',
|
|
286
289
|
'--c_highlight', '--c_overlay'
|
|
287
290
|
]
|
|
288
291
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kempo-css",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "scripts/build.js",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"build": "node scripts/build.js",
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
24
|
"kempo-server": "^1.9.1",
|
|
25
|
+
"kempo-testing-framework": "^1.4.0",
|
|
24
26
|
"terser": "^5.44.1"
|
|
25
27
|
}
|
|
26
28
|
}
|
package/scripts/build.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { minify } from 'terser';
|
|
7
7
|
|
|
8
8
|
// Check for watch flag
|
|
9
9
|
const isWatchMode = process.argv.includes('--watch');
|
package/src/kempo.css
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/*
|
|
2
|
+
CSS Variables
|
|
3
|
+
*/
|
|
1
4
|
:root {
|
|
2
5
|
color-scheme: light;
|
|
3
6
|
--ff_body: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
@@ -32,7 +35,7 @@
|
|
|
32
35
|
--c_bg__alt: light-dark(rgb(238, 238, 238), rgb(34, 34, 34));
|
|
33
36
|
--c_overscroll: light-dark(rgb(255, 255, 255), rgb(0, 0, 0));
|
|
34
37
|
--c_border: light-dark(rgb(204, 204, 204), rgb(119, 119, 119));
|
|
35
|
-
--c_border__inv: light-dark(
|
|
38
|
+
--c_border__inv: light-dark(rgb(119, 119, 119), rgb(204, 204, 204));
|
|
36
39
|
--c_primary: rgb(51, 102, 255);
|
|
37
40
|
--c_primary__hover: rgb(17, 68, 221);
|
|
38
41
|
--c_secondary: rgb(153, 51, 255);
|
|
@@ -77,7 +80,9 @@
|
|
|
77
80
|
--focus_shadow_on_primary: 0 0 2px 2px var(--tc_on_primary);
|
|
78
81
|
--input_bg: light-dark(white, var(--c_bg__alt));
|
|
79
82
|
--input_tc: light-dark(rgba(0, 0, 0, 0.93), var(--tc));
|
|
80
|
-
--
|
|
83
|
+
--drop_shadow__light: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.333);
|
|
84
|
+
--drop_shadow__dark: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.5);
|
|
85
|
+
--drop_shadow: var(--drop_shadow__light);
|
|
81
86
|
--date_picker_icon_filter: light-dark(invert(0), invert(1));
|
|
82
87
|
}
|
|
83
88
|
[theme="light"] {
|
|
@@ -86,12 +91,21 @@
|
|
|
86
91
|
|
|
87
92
|
[theme="dark"] {
|
|
88
93
|
color-scheme: dark;
|
|
94
|
+
--drop_shadow: var(--drop_shadow__dark);
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
[theme="auto"] {
|
|
92
98
|
color-scheme: light dark;
|
|
93
99
|
}
|
|
100
|
+
@media (prefers-color-scheme: dark) {
|
|
101
|
+
[theme="auto"] {
|
|
102
|
+
--drop_shadow: var(--drop_shadow__dark);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
94
105
|
|
|
106
|
+
/*
|
|
107
|
+
Base / Reset
|
|
108
|
+
*/
|
|
95
109
|
:root {
|
|
96
110
|
interpolate-size: allow-keywords;
|
|
97
111
|
}
|
|
@@ -600,6 +614,10 @@ li ul {
|
|
|
600
614
|
.m-cols-9 { grid-template-columns: repeat(9, 1fr); }
|
|
601
615
|
.m-cols-10 { grid-template-columns: repeat(10, 1fr); }
|
|
602
616
|
}
|
|
617
|
+
|
|
618
|
+
/*
|
|
619
|
+
Buttons
|
|
620
|
+
*/
|
|
603
621
|
button:not(.no-btn):not(.no-style),
|
|
604
622
|
.btn,
|
|
605
623
|
input[type="button"],
|
|
@@ -772,6 +790,10 @@ input[type="reset"].link {
|
|
|
772
790
|
display: block;
|
|
773
791
|
width: 100%;
|
|
774
792
|
}
|
|
793
|
+
|
|
794
|
+
/*
|
|
795
|
+
Forms
|
|
796
|
+
*/
|
|
775
797
|
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="radio"]):not([type="checkbox"]),
|
|
776
798
|
select,
|
|
777
799
|
textarea {
|
|
@@ -864,6 +886,10 @@ input[type="week"]::-webkit-calendar-picker-indicator,
|
|
|
864
886
|
input[type="search"]::-webkit-search-cancel-button {
|
|
865
887
|
filter: var(--date_picker_icon_filter);
|
|
866
888
|
}
|
|
889
|
+
|
|
890
|
+
/*
|
|
891
|
+
Tables
|
|
892
|
+
*/
|
|
867
893
|
.table-wrapper {
|
|
868
894
|
overflow-x: auto;
|
|
869
895
|
}
|
|
@@ -898,6 +924,10 @@ tr:last-child td:first-child {
|
|
|
898
924
|
tr:last-child td:last-child {
|
|
899
925
|
border-bottom-right-radius: var(--radius);
|
|
900
926
|
}
|
|
927
|
+
|
|
928
|
+
/*
|
|
929
|
+
Colors
|
|
930
|
+
*/
|
|
901
931
|
.bg-default {
|
|
902
932
|
background-color: var(--c_bg);
|
|
903
933
|
color: var(--tc);
|
|
@@ -1003,6 +1033,10 @@ tr:last-child td:last-child {
|
|
|
1003
1033
|
.tc-muted {
|
|
1004
1034
|
color: var(--tc_muted);
|
|
1005
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
/*
|
|
1038
|
+
Components
|
|
1039
|
+
*/
|
|
1006
1040
|
.card {
|
|
1007
1041
|
border: 1px solid var(--c_border);
|
|
1008
1042
|
border-radius: var(--radius);
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
const getStyle = (el, prop) => getComputedStyle(el)[prop];
|
|
2
|
+
|
|
3
|
+
export const beforeAll = async () => {
|
|
4
|
+
const link = document.createElement('link');
|
|
5
|
+
link.rel = 'stylesheet';
|
|
6
|
+
link.href = '/src/kempo.css';
|
|
7
|
+
document.head.appendChild(link);
|
|
8
|
+
await new Promise(resolve => link.onload = resolve);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
'should apply box-sizing border-box to all elements': ({pass, fail}) => {
|
|
13
|
+
const div = document.createElement('div');
|
|
14
|
+
document.body.appendChild(div);
|
|
15
|
+
const boxSizing = getStyle(div, 'boxSizing');
|
|
16
|
+
div.remove();
|
|
17
|
+
if(boxSizing === 'border-box'){
|
|
18
|
+
pass('box-sizing is border-box');
|
|
19
|
+
} else {
|
|
20
|
+
fail(`Expected border-box, got ${boxSizing}`);
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
'should reset margin on body': ({pass, fail}) => {
|
|
25
|
+
const margin = getStyle(document.body, 'margin');
|
|
26
|
+
if(margin === '0px'){
|
|
27
|
+
pass('Body margin is reset to 0');
|
|
28
|
+
} else {
|
|
29
|
+
fail(`Expected 0px margin, got ${margin}`);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
'should set min-height 100vh on body': ({pass, fail}) => {
|
|
34
|
+
const minHeight = getStyle(document.body, 'minHeight');
|
|
35
|
+
const viewportHeight = window.innerHeight;
|
|
36
|
+
const minHeightValue = parseFloat(minHeight);
|
|
37
|
+
if(minHeightValue >= viewportHeight){
|
|
38
|
+
pass('Body min-height is at least 100vh');
|
|
39
|
+
} else {
|
|
40
|
+
fail(`Expected min-height >= ${viewportHeight}px, got ${minHeight}`);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
'should apply background color to body': ({pass, fail}) => {
|
|
45
|
+
const bg = getStyle(document.body, 'backgroundColor');
|
|
46
|
+
if(bg && bg !== 'transparent' && bg !== 'rgba(0, 0, 0, 0)'){
|
|
47
|
+
pass(`Body has background color: ${bg}`);
|
|
48
|
+
} else {
|
|
49
|
+
fail('Body should have a background color');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
'should apply text color to body': ({pass, fail}) => {
|
|
54
|
+
const color = getStyle(document.body, 'color');
|
|
55
|
+
if(color && color !== 'transparent' && color !== 'rgba(0, 0, 0, 0)'){
|
|
56
|
+
pass(`Body has text color: ${color}`);
|
|
57
|
+
} else {
|
|
58
|
+
fail('Body should have a text color');
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
'should reset top margin on headings': ({pass, fail}) => {
|
|
63
|
+
const headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
|
64
|
+
const failed = [];
|
|
65
|
+
headings.forEach(tag => {
|
|
66
|
+
const el = document.createElement(tag);
|
|
67
|
+
document.body.appendChild(el);
|
|
68
|
+
const marginTop = getStyle(el, 'marginTop');
|
|
69
|
+
el.remove();
|
|
70
|
+
if(marginTop !== '0px'){
|
|
71
|
+
failed.push(`${tag}: ${marginTop}`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
if(failed.length === 0){
|
|
75
|
+
pass('All headings have top margin reset to 0');
|
|
76
|
+
} else {
|
|
77
|
+
fail(`Headings with non-zero top margin: ${failed.join(', ')}`);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
'should apply bottom margin to headings': ({pass, fail}) => {
|
|
82
|
+
const h1 = document.createElement('h1');
|
|
83
|
+
document.body.appendChild(h1);
|
|
84
|
+
const marginBottom = parseFloat(getStyle(h1, 'marginBottom'));
|
|
85
|
+
h1.remove();
|
|
86
|
+
if(marginBottom > 0){
|
|
87
|
+
pass(`Headings have bottom margin: ${marginBottom}px`);
|
|
88
|
+
} else {
|
|
89
|
+
fail('Headings should have bottom margin for spacing');
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
'should apply bottom margin to paragraphs': ({pass, fail}) => {
|
|
94
|
+
const p = document.createElement('p');
|
|
95
|
+
document.body.appendChild(p);
|
|
96
|
+
const marginBottom = parseFloat(getStyle(p, 'marginBottom'));
|
|
97
|
+
const marginTop = getStyle(p, 'marginTop');
|
|
98
|
+
p.remove();
|
|
99
|
+
if(marginTop === '0px' && marginBottom > 0){
|
|
100
|
+
pass(`Paragraphs have 0 top margin and ${marginBottom}px bottom margin`);
|
|
101
|
+
} else {
|
|
102
|
+
fail(`Expected 0 top margin and positive bottom margin, got top: ${marginTop}, bottom: ${marginBottom}px`);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
'should apply container max-width': ({pass, fail}) => {
|
|
107
|
+
const container = document.createElement('div');
|
|
108
|
+
container.className = 'container';
|
|
109
|
+
document.body.appendChild(container);
|
|
110
|
+
const maxWidth = getStyle(container, 'maxWidth');
|
|
111
|
+
container.remove();
|
|
112
|
+
if(maxWidth && maxWidth !== 'none'){
|
|
113
|
+
pass(`Container has max-width: ${maxWidth}`);
|
|
114
|
+
} else {
|
|
115
|
+
fail('Container should have a max-width');
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
'should center container horizontally': ({pass, fail}) => {
|
|
120
|
+
const container = document.createElement('div');
|
|
121
|
+
container.className = 'container';
|
|
122
|
+
document.body.appendChild(container);
|
|
123
|
+
const marginLeft = getStyle(container, 'marginLeft');
|
|
124
|
+
const marginRight = getStyle(container, 'marginRight');
|
|
125
|
+
container.remove();
|
|
126
|
+
// When container is narrower than viewport, auto margins compute to equal pixel values
|
|
127
|
+
// When container fills viewport, they're both 0 or equal
|
|
128
|
+
if(marginLeft === marginRight){
|
|
129
|
+
pass('Container is horizontally centered');
|
|
130
|
+
} else {
|
|
131
|
+
fail(`Expected equal margins, got left: ${marginLeft}, right: ${marginRight}`);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
'should apply padding to container': ({pass, fail}) => {
|
|
136
|
+
const container = document.createElement('div');
|
|
137
|
+
container.className = 'container';
|
|
138
|
+
document.body.appendChild(container);
|
|
139
|
+
const paddingLeft = parseFloat(getStyle(container, 'paddingLeft'));
|
|
140
|
+
const paddingRight = parseFloat(getStyle(container, 'paddingRight'));
|
|
141
|
+
container.remove();
|
|
142
|
+
if(paddingLeft > 0 && paddingRight > 0){
|
|
143
|
+
pass(`Container has padding: left ${paddingLeft}px, right ${paddingRight}px`);
|
|
144
|
+
} else {
|
|
145
|
+
fail('Container should have left and right padding');
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
'should style main element like container': ({pass, fail}) => {
|
|
150
|
+
const main = document.createElement('main');
|
|
151
|
+
document.body.appendChild(main);
|
|
152
|
+
const maxWidth = getStyle(main, 'maxWidth');
|
|
153
|
+
const marginLeft = getStyle(main, 'marginLeft');
|
|
154
|
+
const marginRight = getStyle(main, 'marginRight');
|
|
155
|
+
main.remove();
|
|
156
|
+
if(maxWidth && maxWidth !== 'none' && marginLeft === marginRight){
|
|
157
|
+
pass('Main element is styled like container');
|
|
158
|
+
} else {
|
|
159
|
+
fail(`Main should have max-width and centered margins, got maxWidth: ${maxWidth}, margins: ${marginLeft}/${marginRight}`);
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
|
|
163
|
+
'should hide overflow on body.no-scroll': ({pass, fail}) => {
|
|
164
|
+
document.body.classList.add('no-scroll');
|
|
165
|
+
const overflow = getStyle(document.body, 'overflow');
|
|
166
|
+
document.body.classList.remove('no-scroll');
|
|
167
|
+
if(overflow === 'hidden'){
|
|
168
|
+
pass('body.no-scroll hides overflow');
|
|
169
|
+
} else {
|
|
170
|
+
fail(`Expected overflow hidden, got ${overflow}`);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
'should style summary element with pointer cursor': ({pass, fail}) => {
|
|
175
|
+
const details = document.createElement('details');
|
|
176
|
+
const summary = document.createElement('summary');
|
|
177
|
+
summary.textContent = 'Test';
|
|
178
|
+
details.appendChild(summary);
|
|
179
|
+
document.body.appendChild(details);
|
|
180
|
+
const cursor = getStyle(summary, 'cursor');
|
|
181
|
+
details.remove();
|
|
182
|
+
if(cursor === 'pointer'){
|
|
183
|
+
pass('Summary has pointer cursor');
|
|
184
|
+
} else {
|
|
185
|
+
fail(`Expected pointer cursor, got ${cursor}`);
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
'should reset menu margin and padding': ({pass, fail}) => {
|
|
190
|
+
const menu = document.createElement('menu');
|
|
191
|
+
document.body.appendChild(menu);
|
|
192
|
+
const margin = getStyle(menu, 'margin');
|
|
193
|
+
const padding = getStyle(menu, 'padding');
|
|
194
|
+
menu.remove();
|
|
195
|
+
if(margin === '0px' && padding === '0px'){
|
|
196
|
+
pass('Menu margin and padding reset');
|
|
197
|
+
} else {
|
|
198
|
+
fail(`Menu should have 0 margin/padding, got margin: ${margin}, padding: ${padding}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|